PopupMenu and Acessibility Focus

Hi all,

I’ve come across a bug regarding how focus is passed into a PopupMenu when it is opened with macOS Voiceover - namely, if you use PopupMenu::Options’s .withParentComponent(<comp>) and do not use .withInitiallySelectedItem(), focus will not properly transfer into the `PopupMenu`.

I’m testing on macOS Tahoe 26.2, Apple Silicon. Note that in VoiceOver Utility, “Navigation” → “Mouse Pointer” shouId be set to “gnores VoiceOver cursor”. If it’s set to “Follows VoiceOver Cursor”, then focus sometimes works correctly, but not always.

Attached are two videos which illustrate the issue. I’ve updated the DSPModulePluginDemo, adding the following to the DspModulePluginDemoEditor and setting a CustomLaf member as the look and feel in the editor’s constructor. This is with the latest tip of develop.

class CustomLaf : public LookAndFeel_V4
{
    PopupMenu::Options getOptionsForComboBoxPopupMenu (ComboBox& box, Label& label) override
    {
        return LookAndFeel_V4::getOptionsForComboBoxPopupMenu(box, label)
                              .withInitiallySelectedItem(0) // effectively turns off base behavior
                              .withParentComponent(box.findParentComponentOfClass<juce::AudioProcessorEditor>();
    }
};

In this first video, you can see that after the PopupMenu opens, I cannot use VO+Up/Down to start navigating the menu entries. Even though I’m spamming it, just gets stuck:

In this second video, I updated to withInitiallySelectedItem(box.getSelectedId()), and you’ll see focus correctly transfers:

Also for what it’s worth, keeping withInitiallySelectedItem(0) and removing .withParentComponent(box.findParentComponentOfClass<juce::AudioProcessorEditor>();, it works fine:

Digging into the PopupMenu code with a debugger, it appears that MenuWindow::handleAsyncUpdate() and the AccessibilityActions for MenuWindow are getting called correctly when I use VO+Up/Down (calling setNextItem()), but it’s still not correctly moving the focus into the row components in the PopupMenu.

Any ideas? I need to use withParentComponent() but I can’t use withInitiallySelectedItem() for various reasons. Thanks!

1 Like

Thank you for reporting. We’re working on a fix.

1 Like

A fix is now out on develop.

Thanks, I can confirm this fixes the issue on my end!

Hiya, unfortunately I’ve encountered 3 more issues that need addressing. Let me know if you’d like me to create separate forum threads for each, but I figured I’d keep using this thread since they are all related to PopupMenu / ComboBox and accessibility.

I modified the examples/CMake/AudioPlugin project to show the issues. Attached are my modifications to the code.
PluginEditor.cpp (2.3 KB)
PluginEditor.h (1.3 KB)

Bug #1:
Submenus simply read out the name of the submenu, and do not indicate that they are actually submenus. Native macOS menus are much more helpful → they say “Submenu Name, submenu, N items”

Bug #2:
If using withParentComponent(editor) and a submenu only has 1 item, selecting that item does not work. The item is not selected and focus doesn’t return to the combo. Submenus with 2 or more items work fine. Additionally, without withParentComponent(editor), 1 item works fine.

  • 1 Item (doesn’t work):

  • 2 Items (works):

  • 1 Item without withParentComponent(editor) (works):

Bug #3:
If “Navigation” → “Mouse Pointer” is set to “Follows VoiceOver cursor” in VoiceOver Utility (which is a typical setting for visually impaired users), hovering over a submenu item immediately moves the focus into the submenu. This can be especially confusing if the first item in the submenu is also a submenu item, as it then moves focus into that item’s submenu. Native macOS popups keep the mouse pointer on the item until the user selects it and then transfers focus into the submenu.

We have preset menus in our plugins which are organized hierarchically by folders, where the folders are listed before individual presets (selectable items), so you can see why this could get confusing very fast.

Let me know if I can provide any other info, thanks!