diff --git a/modules/juce_events/native/juce_mac_MessageManager.mm b/modules/juce_events/native/juce_mac_MessageManager.mm index 8aa275647f..be061fc184 100644 --- a/modules/juce_events/native/juce_mac_MessageManager.mm +++ b/modules/juce_events/native/juce_mac_MessageManager.mm @@ -29,8 +29,8 @@ AppFocusChangeCallback appFocusChangeCallback = nullptr; typedef bool (*CheckEventBlockedByModalComps) (NSEvent*); CheckEventBlockedByModalComps isEventBlockedByModalComps = nullptr; -typedef void (*MenuTrackingBeganCallback)(); -MenuTrackingBeganCallback menuTrackingBeganCallback = nullptr; +typedef void (*MenuTrackingChangedCallback)(bool); +MenuTrackingChangedCallback menuTrackingChangedCallback = nullptr; //============================================================================== struct AppDelegate @@ -45,6 +45,8 @@ public: [center addObserver: delegate selector: @selector (mainMenuTrackingBegan:) name: NSMenuDidBeginTrackingNotification object: nil]; + [center addObserver: delegate selector: @selector (mainMenuTrackingEnded:) + name: NSMenuDidEndTrackingNotification object: nil]; if (JUCEApplicationBase::isStandaloneApp()) { @@ -111,6 +113,7 @@ private: addMethod (@selector (applicationWillUnhide:), applicationWillUnhide, "v@:@"); addMethod (@selector (broadcastMessageCallback:), broadcastMessageCallback, "v@:@"); addMethod (@selector (mainMenuTrackingBegan:), mainMenuTrackingBegan, "v@:@"); + addMethod (@selector (mainMenuTrackingEnded:), mainMenuTrackingEnded, "v@:@"); addMethod (@selector (dummyMethod), dummyMethod, "v@:"); registerClass(); @@ -178,8 +181,14 @@ private: static void mainMenuTrackingBegan (id /*self*/, SEL, NSNotification*) { - if (menuTrackingBeganCallback != nullptr) - (*menuTrackingBeganCallback)(); + if (menuTrackingChangedCallback != nullptr) + (*menuTrackingChangedCallback) (true); + } + + static void mainMenuTrackingEnded (id /*self*/, SEL, NSNotification*) + { + if (menuTrackingChangedCallback != nullptr) + (*menuTrackingChangedCallback) (false); } static void dummyMethod (id /*self*/, SEL) {} // (used as a way of running a dummy thread) diff --git a/modules/juce_gui_basics/native/juce_mac_MainMenu.mm b/modules/juce_gui_basics/native/juce_mac_MainMenu.mm index 3ea1bba86c..ab39adf07b 100644 --- a/modules/juce_gui_basics/native/juce_mac_MainMenu.mm +++ b/modules/juce_gui_basics/native/juce_mac_MainMenu.mm @@ -29,7 +29,8 @@ class JuceMainMenuHandler : private MenuBarModel::Listener, public: JuceMainMenuHandler() : currentModel (nullptr), - lastUpdateTime (0) + lastUpdateTime (0), + isOpen (false) { static JuceMenuCallbackClass cls; callback = [cls.createInstance() init]; @@ -76,7 +77,7 @@ public: keyEquivalent: nsEmptyString()]; [item setTag: tag]; - NSMenu* sub = createMenu (child, name, menuId, tag); + NSMenu* sub = createMenu (child, name, menuId, tag, true); [parent setSubmenu: sub forItem: item]; [sub setAutoenablesItems: false]; @@ -125,6 +126,9 @@ public: void menuBarItemsChanged (MenuBarModel*) { + if (isOpen) + return; + lastUpdateTime = Time::getMillisecondCounter(); StringArray menuNames; @@ -231,8 +235,7 @@ public: [item setTag: iter.itemId]; [item setEnabled: iter.isEnabled]; - NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, topLevelMenuId, topLevelIndex); - [sub setDelegate: nil]; + NSMenu* sub = createMenu (*iter.subMenu, iter.itemName, topLevelMenuId, topLevelIndex, false); [menuToAddTo setSubmenu: sub forItem: item]; [sub release]; } @@ -282,6 +285,7 @@ public: uint32 lastUpdateTime; NSObject* callback; String recentItemsMenuName; + bool isOpen; private: struct RecentFilesMenuItem @@ -335,17 +339,21 @@ private: NSMenu* createMenu (const PopupMenu menu, const String& menuName, const int topLevelMenuId, - const int topLevelIndex) + const int topLevelIndex, + const bool addDelegate) { NSMenu* m = [[NSMenu alloc] initWithTitle: juceStringToNS (menuName)]; [m setAutoenablesItems: false]; - #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 - [m setDelegate: (id) callback]; - #else - [m setDelegate: callback]; - #endif + if (addDelegate) + { + #if defined (MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 + [m setDelegate: (id) callback]; + #else + [m setDelegate: callback]; + #endif + } for (PopupMenu::MenuItemIterator iter (menu); iter.next();) addMenuItem (iter, m, topLevelMenuId, topLevelIndex); @@ -476,12 +484,10 @@ private: } private: - static void menuItemInvoked (id self, SEL, id menu) + static void menuItemInvoked (id self, SEL, NSMenuItem* item) { JuceMainMenuHandler* const owner = getIvar (self, "owner"); - NSMenuItem* item = (NSMenuItem*) menu; - if ([[item representedObject] isKindOfClass: [NSArray class]]) { // If the menu is being triggered by a keypress, the OS will have picked it up before we had a chance to offer it to @@ -643,17 +649,20 @@ const PopupMenu* MenuBarModel::getMacExtraAppleItemsMenu() ? JuceMainMenuHandler::instance->extraAppleMenuItems.get() : nullptr; } -typedef void (*MenuTrackingBeganCallback)(); -extern MenuTrackingBeganCallback menuTrackingBeganCallback; +typedef void (*MenuTrackingChangedCallback) (bool); +extern MenuTrackingChangedCallback menuTrackingChangedCallback; -static void mainMenuTrackingBegan() +static void mainMenuTrackingChanged (bool isTracking) { PopupMenu::dismissAllActiveMenus(); + + if (JuceMainMenuHandler::instance != nullptr) + JuceMainMenuHandler::instance->isOpen = isTracking; } void juce_initialiseMacMainMenu() { - menuTrackingBeganCallback = mainMenuTrackingBegan; + menuTrackingChangedCallback = mainMenuTrackingChanged; if (JuceMainMenuHandler::instance == nullptr) MainMenuHelpers::rebuildMainMenu (nullptr);