mirror of
https://github.com/cappuccino/cappuccino.git
synced 2026-08-25 04:57:03 +00:00
Fixed: menus not closing on left click.
Previously, clicking outside a menu on a control would not close the menu. Also clicking on the menu header again would open a second menu. This error was caused by the control receiving the click and starting its own tracking, depriving the menu of the mouse up event it was awaiting. The behaviour to wait for the mouse up was wrong to begin with. Menus should close on mouse down. This fix closes the menu on left mouse down anywhere but the menu, while still allowing the click to pass through to any control underneath the cursor. Fixes #1833.
This commit is contained in:
@@ -132,6 +132,11 @@ var STICKY_TIME_INTERVAL = 0.4,
|
||||
[self trackEvent:anEvent];
|
||||
}
|
||||
|
||||
- (void)_trackAgain
|
||||
{
|
||||
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseDownMask | CPLeftMouseUpMask | CPRightMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES];
|
||||
}
|
||||
|
||||
- (void)trackEvent:(CPEvent)anEvent
|
||||
{
|
||||
var type = [anEvent type],
|
||||
@@ -141,8 +146,6 @@ var STICKY_TIME_INTERVAL = 0.4,
|
||||
if (type === CPAppKitDefined)
|
||||
return [self completeTracking];
|
||||
|
||||
[CPApp setTarget:self selector:@selector(trackEvent:) forNextEventMatchingMask:CPKeyDownMask | CPPeriodicMask | CPMouseMovedMask | CPLeftMouseDraggedMask | CPLeftMouseUpMask | CPRightMouseUpMask | CPAppKitDefinedMask | CPScrollWheelMask untilDate:nil inMode:nil dequeue:YES];
|
||||
|
||||
if (type === CPKeyDown)
|
||||
{
|
||||
var menu = trackingMenu,
|
||||
@@ -158,6 +161,7 @@ var STICKY_TIME_INTERVAL = 0.4,
|
||||
if ([menu numberOfItems])
|
||||
[self interpretKeyEvent:anEvent forMenu:menu];
|
||||
|
||||
[self _trackAgain];
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -165,7 +169,10 @@ var STICKY_TIME_INTERVAL = 0.4,
|
||||
var globalLocation = type === CPPeriodic ? _lastGlobalLocation : [anEvent globalLocation];
|
||||
|
||||
if (!globalLocation)
|
||||
{
|
||||
[self _trackAgain];
|
||||
return;
|
||||
}
|
||||
|
||||
// Find which menu window the mouse is currently on top of
|
||||
var activeMenuContainer = [self menuContainerForPoint:globalLocation],
|
||||
@@ -176,6 +183,28 @@ var STICKY_TIME_INTERVAL = 0.4,
|
||||
activeItemIndex = activeMenuContainer ? [activeMenuContainer itemIndexAtPoint:menuLocation] : CPNotFound,
|
||||
activeItem = activeItemIndex !== CPNotFound ? [activeMenu itemAtIndex:activeItemIndex] : nil;
|
||||
|
||||
// Click outside the menu structure?
|
||||
if (type === CPLeftMouseDown && (!activeMenuContainer || !CGRectContainsPoint([activeMenuContainer globalFrame], globalLocation)))
|
||||
{
|
||||
[self completeTracking];
|
||||
|
||||
/*
|
||||
You can close and interact with a control in a single click. E.g. you can have a menu open,
|
||||
click on a button outside of it and have the menu immediately close and the button activate,
|
||||
without having to click once to close the menu and once to activate the button.
|
||||
|
||||
Since we normally dequeue the event after tracking it, we'll have to put it back on the stack
|
||||
in this special case. Note that it's important the event is executed /right now/, since certain
|
||||
controls such as HTML upload buttons need a native click event at the top of the stack trace
|
||||
to activate - it's not something we can fake later.
|
||||
*/
|
||||
[CPApp sendEvent:anEvent];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
[self _trackAgain];
|
||||
|
||||
if (_keyBuffer)
|
||||
{
|
||||
if (([anEvent timestamp] - _startTime) > (STICKY_TIME_INTERVAL + [activeMenu numberOfItems] / 2))
|
||||
@@ -252,7 +281,7 @@ var STICKY_TIME_INTERVAL = 0.4,
|
||||
_lastMouseOverMenuView = nil;
|
||||
}
|
||||
|
||||
if (activeItemIndex != CPNotFound)
|
||||
if (activeItemIndex !== CPNotFound)
|
||||
[activeMenu _highlightItemAtIndex:activeItemIndex];
|
||||
|
||||
if (type === CPMouseMoved || type === CPLeftMouseDragged || type === CPLeftMouseDown || type === CPPeriodic)
|
||||
|
||||
Reference in New Issue
Block a user