| @@ -1141,3 +1141,8 @@ void GraphDocumentComponent::createNewPlugin (const PluginDescription* desc, int | |||||
| { | { | ||||
| graphPanel->createNewPlugin (desc, x, y); | graphPanel->createNewPlugin (desc, x, y); | ||||
| } | } | ||||
| void GraphDocumentComponent::unfocusKeyboardComponent() | |||||
| { | |||||
| keyboardComp->unfocusAllComponents(); | |||||
| } | |||||
| @@ -96,6 +96,9 @@ public: | |||||
| //============================================================================== | //============================================================================== | ||||
| void resized(); | void resized(); | ||||
| //============================================================================== | |||||
| void unfocusKeyboardComponent(); | |||||
| private: | private: | ||||
| //============================================================================== | //============================================================================== | ||||
| AudioDeviceManager* deviceManager; | AudioDeviceManager* deviceManager; | ||||
| @@ -291,6 +291,14 @@ void MainHostWindow::menuItemSelected (int menuItemID, int /*topLevelMenuIndex*/ | |||||
| } | } | ||||
| } | } | ||||
| void MainHostWindow::menuBarActivated (bool isActivated) | |||||
| { | |||||
| GraphDocumentComponent* const graphEditor = getGraphEditor(); | |||||
| if (graphEditor != nullptr && isActivated) | |||||
| graphEditor->unfocusKeyboardComponent(); | |||||
| } | |||||
| void MainHostWindow::createPlugin (const PluginDescription* desc, int x, int y) | void MainHostWindow::createPlugin (const PluginDescription* desc, int x, int y) | ||||
| { | { | ||||
| GraphDocumentComponent* const graphEditor = getGraphEditor(); | GraphDocumentComponent* const graphEditor = getGraphEditor(); | ||||
| @@ -70,6 +70,8 @@ public: | |||||
| void fileDragExit (const StringArray& files); | void fileDragExit (const StringArray& files); | ||||
| void filesDropped (const StringArray& files, int, int); | void filesDropped (const StringArray& files, int, int); | ||||
| void menuBarActivated (bool isActive); | |||||
| StringArray getMenuBarNames(); | StringArray getMenuBarNames(); | ||||
| PopupMenu getMenuForIndex (int topLevelMenuIndex, const String& menuName); | PopupMenu getMenuForIndex (int topLevelMenuIndex, const String& menuName); | ||||
| void menuItemSelected (int menuItemID, int topLevelMenuIndex); | void menuItemSelected (int menuItemID, int topLevelMenuIndex); | ||||
| @@ -90,7 +90,6 @@ MidiKeyboardComponent::MidiKeyboardComponent (MidiKeyboardState& s, Orientation | |||||
| colourChanged(); | colourChanged(); | ||||
| setWantsKeyboardFocus (true); | setWantsKeyboardFocus (true); | ||||
| setLosesFocusWhenAccessingMainMenuBar (true); | |||||
| state.addListener (this); | state.addListener (this); | ||||
| @@ -880,18 +880,6 @@ public: | |||||
| bool& allowsClicksOnChildComponents) const noexcept; | bool& allowsClicksOnChildComponents) const noexcept; | ||||
| /** Changes the focus behavior when the main menu bar is accessed. | |||||
| If set to true, then clicking the main menu bar on Mac will unfocus the component. | |||||
| */ | |||||
| void setLosesFocusWhenAccessingMainMenuBar (bool loseFocus) noexcept { flags.shouldReleaseFocusOnMainMenuBarAccess = loseFocus; } | |||||
| /** Retrieves the focus behavior when the main menu bar is accessed. | |||||
| Returns true if clicking the main menu bar on Mac will unfocus this component. | |||||
| */ | |||||
| bool getLosesFocusWhenAccessingMainMenuBar() const noexcept { return flags.shouldReleaseFocusOnMainMenuBarAccess; } | |||||
| /** Returns true if a given point lies within this component or one of its children. | /** Returns true if a given point lies within this component or one of its children. | ||||
| Never override this method! Use hitTest to create custom hit regions. | Never override this method! Use hitTest to create custom hit regions. | ||||
| @@ -2278,28 +2266,27 @@ private: | |||||
| struct ComponentFlags | struct ComponentFlags | ||||
| { | { | ||||
| bool hasHeavyweightPeerFlag : 1; | |||||
| bool visibleFlag : 1; | |||||
| bool opaqueFlag : 1; | |||||
| bool ignoresMouseClicksFlag : 1; | |||||
| bool allowChildMouseClicksFlag : 1; | |||||
| bool wantsFocusFlag : 1; | |||||
| bool isFocusContainerFlag : 1; | |||||
| bool dontFocusOnMouseClickFlag : 1; | |||||
| bool alwaysOnTopFlag : 1; | |||||
| bool bufferToImageFlag : 1; | |||||
| bool bringToFrontOnClickFlag : 1; | |||||
| bool repaintOnMouseActivityFlag : 1; | |||||
| bool isDisabledFlag : 1; | |||||
| bool childCompFocusedFlag : 1; | |||||
| bool dontClipGraphicsFlag : 1; | |||||
| bool mouseDownWasBlocked : 1; | |||||
| bool isMoveCallbackPending : 1; | |||||
| bool isResizeCallbackPending : 1; | |||||
| bool hasHeavyweightPeerFlag : 1; | |||||
| bool visibleFlag : 1; | |||||
| bool opaqueFlag : 1; | |||||
| bool ignoresMouseClicksFlag : 1; | |||||
| bool allowChildMouseClicksFlag : 1; | |||||
| bool wantsFocusFlag : 1; | |||||
| bool isFocusContainerFlag : 1; | |||||
| bool dontFocusOnMouseClickFlag : 1; | |||||
| bool alwaysOnTopFlag : 1; | |||||
| bool bufferToImageFlag : 1; | |||||
| bool bringToFrontOnClickFlag : 1; | |||||
| bool repaintOnMouseActivityFlag : 1; | |||||
| bool isDisabledFlag : 1; | |||||
| bool childCompFocusedFlag : 1; | |||||
| bool dontClipGraphicsFlag : 1; | |||||
| bool mouseDownWasBlocked : 1; | |||||
| bool isMoveCallbackPending : 1; | |||||
| bool isResizeCallbackPending : 1; | |||||
| #if JUCE_DEBUG | #if JUCE_DEBUG | ||||
| bool isInsidePaintCall : 1; | |||||
| bool isInsidePaintCall : 1; | |||||
| #endif | #endif | ||||
| bool shouldReleaseFocusOnMainMenuBarAccess : 1; | |||||
| }; | }; | ||||
| union | union | ||||
| @@ -143,6 +143,11 @@ void MenuBarComponent::setOpenItem (int index) | |||||
| { | { | ||||
| if (currentPopupIndex != index) | if (currentPopupIndex != index) | ||||
| { | { | ||||
| if (currentPopupIndex < 0 && index >= 0) | |||||
| model->handleMenuBarActivate (true); | |||||
| else if (currentPopupIndex >= 0 && index < 0) | |||||
| model->handleMenuBarActivate (false); | |||||
| repaintMenuItem (currentPopupIndex); | repaintMenuItem (currentPopupIndex); | ||||
| currentPopupIndex = index; | currentPopupIndex = index; | ||||
| repaintMenuItem (currentPopupIndex); | repaintMenuItem (currentPopupIndex); | ||||
| @@ -82,3 +82,12 @@ void MenuBarModel::applicationCommandListChanged() | |||||
| { | { | ||||
| menuItemsChanged(); | menuItemsChanged(); | ||||
| } | } | ||||
| void MenuBarModel::handleMenuBarActivate (bool isActive) | |||||
| { | |||||
| menuBarActivated (isActive); | |||||
| listeners.call (&MenuBarModel::Listener::menuBarActivated, this, isActive); | |||||
| } | |||||
| void MenuBarModel::menuBarActivated (bool) {} | |||||
| void MenuBarModel::Listener::menuBarActivated (MenuBarModel*, bool) {} | |||||
| @@ -88,6 +88,10 @@ public: | |||||
| */ | */ | ||||
| virtual void menuCommandInvoked (MenuBarModel* menuBarModel, | virtual void menuCommandInvoked (MenuBarModel* menuBarModel, | ||||
| const ApplicationCommandTarget::InvocationInfo& info) = 0; | const ApplicationCommandTarget::InvocationInfo& info) = 0; | ||||
| /** Called when the menu bar is first activated or when the user finished interacting | |||||
| with the menu bar. */ | |||||
| virtual void menuBarActivated (MenuBarModel* menuBarModel, bool isActive); | |||||
| }; | }; | ||||
| /** Registers a listener for callbacks when the menu items in this model change. | /** Registers a listener for callbacks when the menu items in this model change. | ||||
| @@ -126,6 +130,12 @@ public: | |||||
| virtual void menuItemSelected (int menuItemID, | virtual void menuItemSelected (int menuItemID, | ||||
| int topLevelMenuIndex) = 0; | int topLevelMenuIndex) = 0; | ||||
| /** This is called when the user starts/stops navigating the maenu bar. | |||||
| @param isActive true when the user starts navigating the menu bar | |||||
| */ | |||||
| virtual void menuBarActivated (bool isActive); | |||||
| //============================================================================== | //============================================================================== | ||||
| #if JUCE_MAC || DOXYGEN | #if JUCE_MAC || DOXYGEN | ||||
| /** OSX ONLY - Sets the model that is currently being shown as the main | /** OSX ONLY - Sets the model that is currently being shown as the main | ||||
| @@ -167,7 +177,8 @@ public: | |||||
| void applicationCommandListChanged() override; | void applicationCommandListChanged() override; | ||||
| /** @internal */ | /** @internal */ | ||||
| void handleAsyncUpdate() override; | void handleAsyncUpdate() override; | ||||
| /** @internal */ | |||||
| void handleMenuBarActivate (bool isActive); | |||||
| private: | private: | ||||
| ApplicationCommandManager* manager; | ApplicationCommandManager* manager; | ||||
| ListenerList<Listener> listeners; | ListenerList<Listener> listeners; | ||||
| @@ -728,19 +728,13 @@ static void mainMenuTrackingChanged (bool isTracking) | |||||
| { | { | ||||
| menuHandler->isOpen = isTracking; | menuHandler->isOpen = isTracking; | ||||
| if (isTracking) | |||||
| { | |||||
| if (Component* c = Component::getCurrentlyFocusedComponent()) | |||||
| if (c->getLosesFocusWhenAccessingMainMenuBar()) | |||||
| c->unfocusAllComponents(); | |||||
| } | |||||
| else | |||||
| if (MenuBarModel* model = menuHandler->currentModel) | |||||
| model->handleMenuBarActivate (isTracking); | |||||
| if (menuHandler->defferedUpdateRequested && ! isTracking) | |||||
| { | { | ||||
| if (menuHandler->defferedUpdateRequested) | |||||
| { | |||||
| menuHandler->defferedUpdateRequested = false; | |||||
| menuHandler->menuBarItemsChanged (menuHandler->currentModel); | |||||
| } | |||||
| menuHandler->defferedUpdateRequested = false; | |||||
| menuHandler->menuBarItemsChanged (menuHandler->currentModel); | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||