isTicked parameter ignored for submenu items on macOS

NOTE: this bug found and fixed by and AI agent - take it or leave it, but it’s definitely broken and this is definitely a fix:

Bug: isTicked parameter ignored for submenu items on macOS (the parent menu item which reveals a submenu)

Summary:
The isTicked parameter in PopupMenu::addSubMenu() is ignored on macOS. Submenu items never show checkmarks, even when isTicked is true.

Location:
modules/juce_gui_basics/native/juce_MainMenu_mac.mm, in JuceMainMenuHandler::addMenuItem() around line 283-293.

The Bug:
When creating an NSMenuItem with a submenu, the code sets tag and enabled but never calls setState::

if (i.subMenu != nullptr)
{
    NSMenuItem* item = [menuToAddTo addItemWithTitle: text
                                              action: nil
                                       keyEquivalent: nsEmptyString()];

    [item setTag: i.itemID];
    [item setEnabled: i.isEnabled];
    // ❌ MISSING: [item setState: i.isTicked ? NSControlStateValueOn : NSControlStateValueOff];

    NSMenu* sub = createMenu (*i.subMenu, i.text, topLevelMenuId, topLevelIndex, false);
    [menuToAddTo setSubmenu: sub forItem: item];
    [sub release];
}

For regular menu items (the else block), setState: is correctly called (line 303).

The Fix:
Add the missing setState: call after line 289:
[item setState: i.isTicked ? NSControlStateValueOn : NSControlStateValueOff];

Note:
This works on Windows because JUCE draws its own menus there, and drawPopupMenuItem() correctly handles isTicked for submenu items. On macOS, JUCE uses native NSMenu/NSMenuItem, so the state must be set explicitly.

Test Case:
PopupMenu menu;PopupMenu submenu;submenu.addItem(“Sub Item”, {});menu.addSubMenu(“Parent Item”, submenu, true, nullptr, true); // isTicked=true// Expected: Parent Item shows checkmark// Actual: No checkmark appears

Version:
JUCE 8.x (tested with the version in the repository)

1 Like

FWIW: I changed the implementation to this

[item setState: i.isTicked ? NSControlStateValueMixed : NSControlStateValueOff];

as this shows the little “-” (dash), showing that something in the submenu is selected.