BR: ComboBox selection does not work if the menu overlaps the macOS menu bar

ComboBox selection does not work if the menu is over the macOS menu bar. mainMenuTrackingBegan is called which calls PopupMenu::dismissAllActiveMenus(); before the PopupMenu has time to handle the mouse click.

Code to reproduce:

Video:

One solution could be to give the PopupMenu a chance to close before dismissing. Or keep popup menus within the user area or the desktop.

--- a/modules/juce_gui_basics/native/juce_MainMenu_mac.mm
+++ b/modules/juce_gui_basics/native/juce_MainMenu_mac.mm
@@ -808,7 +808,7 @@ extern MenuTrackingChangedCallback menuTrackingChangedCallback;
 
 static void mainMenuTrackingChanged (bool isTracking)
 {
-    PopupMenu::dismissAllActiveMenus();
+    juce::Timer::callAfterDelay (50, [] { PopupMenu::dismissAllActiveMenus(); });
 
     if (auto* menuHandler = JuceMainMenuHandler::instance)
     {
1 Like

I have a similar issue except the popup menu gets cut off by the notch on new MacBooks.
I second the idea of keeping it within the desktop area

Looks like the PopupMenu used to not cover the menu bar and was broken in this commit:

I believe it should be correctly fixed as follows:

    Rectangle<int> getParentArea (Point<int> targetPoint, Component* relativeTo = nullptr)
    {
        if (relativeTo != nullptr)
            targetPoint = relativeTo->localPointToGlobal (targetPoint);

        auto* display = Desktop::getInstance().getDisplays().getDisplayForPoint (targetPoint * scaleFactor);
       #if JUCE_MAC
        auto parentArea = display->userArea.getIntersection (display->safeAreaInsets.subtractedFrom (display->totalArea));
       #else
        auto parentArea = display->safeAreaInsets.subtractedFrom (display->totalArea);
       #endif

        if (auto* pc = options.getParentComponent())
        {
            return pc->getLocalArea (nullptr,
                                     pc->getScreenBounds()
                                           .reduced (getLookAndFeel().getPopupMenuBorderSizeWithOptions (options))
                                           .getIntersection (parentArea));
        }

        return parentArea;
    }

@evanberard looks like your issue is due to the fact safeAreaInsets is not implemented on macOS

Can you try this and confirm if it fixes your issue:

static Displays::Display getDisplayFromScreen (NSScreen* s, CGFloat& mainScreenBottom, const float masterScale)
{
    Displays::Display d;

    d.isMain = (approximatelyEqual (mainScreenBottom, 0.0));

    if (d.isMain)
        mainScreenBottom = [s frame].size.height;

    d.userArea  = convertDisplayRect ([s visibleFrame], mainScreenBottom) / masterScale;
    d.totalArea = convertDisplayRect ([s frame], mainScreenBottom) / masterScale;
    d.scale = masterScale;

	if (@available (macOS 12.0, *))
	{
		d.safeAreaInsets = {
			int (std::ceil (s.safeAreaInsets.top / masterScale)),
			int (std::ceil (s.safeAreaInsets.left / masterScale)),
			int (std::ceil (s.safeAreaInsets.bottom / masterScale)),
			int (std::ceil (s.safeAreaInsets.right / masterScale))
		};
	}

    if ([s respondsToSelector: @selector (backingScaleFactor)])
        d.scale *= s.backingScaleFactor;

    NSSize dpi = [[[s deviceDescription] objectForKey: NSDeviceResolution] sizeValue];
    d.dpi = (dpi.width + dpi.height) / 2.0;

    return d;
}
1 Like

Yes nice! pasted that code block into JUCE and it’s keeping it in the desktop area nicely

Thanks for reporting, we now respect the safe area insets on macOS:

1 Like

Still not working on non notch macs. See:

When I select ‘Default’ from the menu, the selection is ignored. My above change to getParentArea is still required.