fuo
June 27, 2026, 4:02pm
1
It find JUCE to be a bit peculiar with the way it decides how to position sub menus.
Looking at the code it looks like sub menus will open upwards relative to the parent menu item when past the middle of the display:
tendTowardsRight = (parentArea.getRight() - target.getRight()) >= (target.getX() - parentArea.getX());
}
x = tendTowardsRight ? jmin (parentArea.getRight() - widthToUse - 4, target.getRight())
: jmax (parentArea.getX() + 4, target.getX() - widthToUse);
if (getLookAndFeel().getPopupMenuBorderSizeWithOptions (options) == 0) // workaround for dismissing the window on mouse up when border size is 0
x += tendTowardsRight ? 1 : -1;
const auto border = getLookAndFeel().getPopupMenuBorderSizeWithOptions (options);
y = target.getCentreY() > parentArea.getCentreY() ? jmax (parentArea.getY(), target.getBottom() - heightToUse) + border
: target.getY() - border;
}
x = jmax (parentArea.getX() + 1, jmin (parentArea.getRight() - (widthToUse + 6), x));
y = jmax (parentArea.getY() + 1, jmin (parentArea.getBottom() - (heightToUse + 6), y));
windowPos.setBounds (x, y, widthToUse, heightToUse);
// sets this flag if it's big enough to obscure any of its parent menus
hideOnExit = parent != nullptr
Here simply replacing that line with y = target.getY() - border; seems to give the more common behavior of always opening sub menus downwards, within screen limits.
What’s the rational behind JUCE’s current behavior?
There’s a dozen different ways you might want a submenu to appear. JUCE can’t implement them all so it chooses a reasonable default.
You can use withPreferredPopupDirection() to customise the behaviour, and/or possibly withTargetScreenArea() .
fuo
June 29, 2026, 10:28am
3
This is specific to submenus, and the solutions you propose do not work in that case.
This behavior is hardcoded and cannot be changed, and is not the common behavior you find on native MacOS or Windows sub menus (and propably most Linux flavors as well).
In fact the problem has already been raised in the past:
Hello guys,
Just noticed that when opening a sub menu, it is either aligned on top with its parent item if the latter is in the top half of the screen, either aligned on bottom if the parent is in the bottom half of the screen.
Here is an example with the projucer:
[image][image]
Is there is any specific reason why it happens? This behavior looks weird to me…
The code in question is in juce_PopupMenu.cpp lines 670-671. Works as expected if I comment out those lines.
if (target.getCentreY()…
And this one with nice illustrations:
On the current dev branch, line 916 of juce_PopupMenu.cpp, in the struct MenuWindow final : public Component struct, there is some logic which I would consider a bug. It breaks convention for popup menus at large, and also goes against the intention of the option which sets the preferred popup direction.
y = target.getCentreY() > parentArea.getCentreY() ? jmax (parentArea.getY(), target.getBottom() - heightToUse) + border : target.getY() - border;
This is setting a sub menus popup direction ba…
Sorry I missed that this is with submenus.
Yes it looks like alignToRectangle is hard-coded to false for sub-menus and so the branch that uses PopupDirection isn’t called: JUCE/modules/juce_gui_basics/menus/juce_PopupMenu.cpp at 2cdfca8feb300fb424002ba2c2751569e5bacb64 · juce-framework/JUCE · GitHub