From cd148c36c93c97b40b681652ffe8a49d6edddc25 Mon Sep 17 00:00:00 2001 From: Aparajita Fishman Date: Mon, 26 Mar 2012 12:38:50 -0700 Subject: [PATCH] Menu tracking fixes: - Finally fixed #1457. - Fixed case where mouse is dragged and then released over a submenu, which should release the menu. - Fixed case where clicking without dragging, then clicking again on a menu title would not close the menu. --- AppKit/CPMenu/_CPMenuManager.j | 47 ++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/AppKit/CPMenu/_CPMenuManager.j b/AppKit/CPMenu/_CPMenuManager.j index 062571161..b97f47331 100644 --- a/AppKit/CPMenu/_CPMenuManager.j +++ b/AppKit/CPMenu/_CPMenuManager.j @@ -11,7 +11,7 @@ var STICKY_TIME_INTERVAL = 500, @implementation _CPMenuManager: CPObject { CPTimeInterval _startTime; - BOOL _hasMouseGoneUpAfterStartedTracking; + BOOL _mouseWasDragged; int _scrollingState; CGPoint _lastGlobalLocation; @@ -66,7 +66,7 @@ var STICKY_TIME_INTERVAL = 500, CPApp._activeMenu = menu; - _startTime = [anEvent timestamp];//new Date(); + _startTime = [anEvent timestamp]; _scrollingState = _CPMenuManagerScrollingStateNone; _constraintRect = aRect; @@ -91,7 +91,7 @@ var STICKY_TIME_INTERVAL = 500, return [self trackMenuBarButtonEvent:anEvent]; } - _hasMouseGoneUpAfterStartedTracking = NO; + _mouseWasDragged = NO; [self trackEvent:anEvent]; } @@ -189,7 +189,7 @@ var STICKY_TIME_INTERVAL = 500, var menuContainerWindow = activeMenuContainer; - if (![menuContainerWindow isKindOfClass:[CPWindow class]]) + if (![menuContainerWindow isKindOfClass:CPWindow]) menuContainerWindow = [menuContainerWindow window]; [menuContainerWindow @@ -215,6 +215,9 @@ var STICKY_TIME_INTERVAL = 500, if (type === CPMouseMoved || type === CPLeftMouseDragged || type === CPLeftMouseDown || type === CPPeriodic) { + if (type === CPLeftMouseDragged) + _mouseWasDragged = YES; + var oldScrollingState = _scrollingState; _scrollingState = [activeMenuContainer scrollingStateForPoint:globalLocation]; @@ -229,17 +232,35 @@ var STICKY_TIME_INTERVAL = 500, } else if (type === CPLeftMouseUp || type === CPRightMouseUp) { - if (_hasMouseGoneUpAfterStartedTracking) - { - // Don't close the menu if the current item has a submenu - // and did not override it's default action - if ([activeItem action] === @selector(submenuAction:)) - return; + /* + There are a few possibilites: - [trackingMenu cancelTracking]; + 1. The user clicks and releases without dragging within the sticky time. + This is considered a regular mouse click and not a drag. In this case + we allow the user to track the menu by moving the mouse. The next + mouse up will end tracking. + + 2. The user clicks and releases without dragging after the sticky time. + This is considered a drag and release and tracking ends. + + 3. The user clicks, drags and then releases. Tracking ends. + */ + if (_mouseWasDragged || [anEvent timestamp] - _startTime > STICKY_TIME_INTERVAL) + { + /* + Close the menu if: + + 1. The mouse was dragged. + 2. The mouse is released in the menubar. + 3. The current item has a submenu with a custom action. + */ + if (_mouseWasDragged || + [activeMenuContainer isKindOfClass:_CPMenuBarWindow] || + [activeItem action] !== @selector(submenuAction:)) + { + [trackingMenu cancelTracking]; + } } - else - _hasMouseGoneUpAfterStartedTracking = YES; } }