Browse Source

MenuBarComponent: Fix incorrect deactivation of the menu bar

Prior to this commit it was possible to get the menu bar deactivated
by moving the mouse to an adjacent menu item and then back again. If
the movement was quick enough the corresponding PopupMenu would be
dismissed and created again before the dismissal's async command
handler would run. The command handler would see that the dismissed
menu's index and the currently activated index are equal and
deactivate the menu bar.
v7.0.9
attila Attila Szarvas 2 years ago
parent
commit
c05ec5f9d0
2 changed files with 35 additions and 28 deletions
  1. +33
    -27
      modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp
  2. +2
    -1
      modules/juce_gui_basics/menus/juce_MenuBarComponent.h

+ 33
- 27
modules/juce_gui_basics/menus/juce_MenuBarComponent.cpp View File

@@ -223,41 +223,47 @@ void MenuBarComponent::updateItemUnderMouse (Point<int> p)
void MenuBarComponent::showMenu (int index)
{
if (index != currentPopupIndex)
{
PopupMenu::dismissAllActiveMenus();
menuBarItemsChanged (nullptr);
if (index == currentPopupIndex)
return;
setOpenItem (index);
setItemUnderMouse (index);
const auto needToOpenNewSubMenu = isPositiveAndBelow (index, (int) itemComponents.size());
if (isPositiveAndBelow (index, (int) itemComponents.size()))
{
const auto& itemComponent = itemComponents[(size_t) index];
auto m = model->getMenuForIndex (itemUnderMouse, itemComponent->getName());
if (needToOpenNewSubMenu)
++numActiveMenus;
if (m.lookAndFeel == nullptr)
m.setLookAndFeel (&getLookAndFeel());
PopupMenu::dismissAllActiveMenus();
menuBarItemsChanged (nullptr);
auto itemBounds = itemComponent->getBounds();
setOpenItem (index);
setItemUnderMouse (index);
const auto callback = [ref = SafePointer<MenuBarComponent> (this), index] (int result)
{
if (ref != nullptr)
ref->menuDismissed (index, result);
};
m.showMenuAsync (PopupMenu::Options().withTargetComponent (this)
.withTargetScreenArea (localAreaToGlobal (itemBounds))
.withMinimumWidth (itemBounds.getWidth()),
callback);
}
if (needToOpenNewSubMenu)
{
const auto& itemComponent = itemComponents[(size_t) index];
auto m = model->getMenuForIndex (itemUnderMouse, itemComponent->getName());
if (m.lookAndFeel == nullptr)
m.setLookAndFeel (&getLookAndFeel());
auto itemBounds = itemComponent->getBounds();
const auto callback = [ref = SafePointer<MenuBarComponent> (this), index] (int result)
{
if (ref != nullptr)
ref->menuDismissed (index, result);
};
m.showMenuAsync (PopupMenu::Options().withTargetComponent (this)
.withTargetScreenArea (localAreaToGlobal (itemBounds))
.withMinimumWidth (itemBounds.getWidth()),
callback);
}
}
void MenuBarComponent::menuDismissed (int topLevelIndex, int itemId)
{
topLevelIndexClicked = topLevelIndex;
topLevelIndexDismissed = topLevelIndex;
--numActiveMenus;
postCommandMessage (itemId);
}
@@ -265,11 +271,11 @@ void MenuBarComponent::handleCommandMessage (int commandId)
{
updateItemUnderMouse (getMouseXYRelative());
if (currentPopupIndex == topLevelIndexClicked)
if (numActiveMenus == 0)
setOpenItem (-1);
if (commandId != 0 && model != nullptr)
model->menuItemSelected (commandId, topLevelIndexClicked);
model->menuItemSelected (commandId, topLevelIndexDismissed);
}
//==============================================================================


+ 2
- 1
modules/juce_gui_basics/menus/juce_MenuBarComponent.h View File

@@ -119,7 +119,8 @@ private:
std::vector<std::unique_ptr<AccessibleItemComponent>> itemComponents;
Point<int> lastMousePos;
int itemUnderMouse = -1, currentPopupIndex = -1, topLevelIndexClicked = 0;
int itemUnderMouse = -1, currentPopupIndex = -1, topLevelIndexDismissed = 0;
int numActiveMenus = 0;
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MenuBarComponent)
};


Loading…
Cancel
Save