ComboBox Accessibility - Inconsistencies between Standalone and Plugin

We’ve been finding some inconsistencies with ComboBox’s accessibility (screen reader) support when attaching a ComboBox’s PopupMenu to a parent component. We’re using PopupMenu::Options::withParentComponent(&editor) in our implementation of LookAndFeel::getOptionsForComboBoxPopupMenu() to make the editor the parent component of the menu. Unfortunately creating the menu on the desktop is not an option in this case.

Oddly, when building a Standalone version our plugin, the macOS screen reader can jump into the popup menu’s window and intuitively navigate through, select an option, and return focus. For any plugin format (VST3 etc) we build, this behavior is different: the screen reader gets stuck in an empty window component with no children, no way to exit, and locks the screen reader. This forces the user to close out of the plugin and reopen to regain control over tabbing and VO+arrow keys functionality.

Interestingly, none of this happens if we don’t use withParentComponent(&editor) - the screen reader works properly.

Has anyone dealt with similar inconsistencies w.r.t macOS screen reader support in plugin vs standalone environments? We’ve been testing in macOS Sequoia 15.5.

Which DAW are you testing with?

With Reaper I found I can navigate using the VO+right/left to go from the plugin window to other items. VO+up/down to enter into the plugin or even in/out of the menu. And this was regardless of if I was using VST3 or AUv2.

With Cubase I found once I was in the plugin window I had to use VO+fn+F2+F2 (not the nicest key combo I’ve ever used!!) to switch between windows, as per this Apple support article

I guess the big difference here is that the plugin is a Window within some other application, where-as stand alone the plugin is the only Window.

I don’t think I’m able to reproduce what is being described, however, there’s a lot of variables involved here so maybe if you could share a simplified code example, plus a video demonstarting the issue? That might help to make sure we’re completley in sync.

I will say I was testing on 14.5 so I’ll upgrade and test on the latest version of macOS 15 too.

Hey Anthony,

Thanks for trying to repro! We were using Reaper and Live to test.

After updating the DSPModulePluginDemo example plugin (which has a combo box) to provide a code snippet, it seems like the original issue is probably something in our code - it doesn’t happen in the modified demo. Focus correctly transfers into the PopupMenu. We’ll need to investigate what the difference on our end is.

However, we did find that when overriding the combo box options to use the editor as the parent, focus is not correctly returned after item selection.

To replicate, in DSPModulePluginDemo.h, create a custom LookAndFeel_V4 with an overridden getOptionsForComboBoxPopup() like so:

class CustomLaf : public LookAndFeel_V4
{
    PopupMenu::Options getOptionsForComboBoxPopupMenu (ComboBox& box, Label& label) override
    {
        return LookAndFeel_V4::getOptionsForComboBoxPopupMenu(box, label).withParentComponent(box.findParentComponentOfClass<juce::AudioProcessorEditor>());
    }
};

Then add a CustomLaf customLaf member in the DspModulePluginDemoEditor and add setLookAndFeel(&customLaf) in the constructor.

Upon selection of an item while using a screen reader in REAPER, with this change, the screen reader focus goes to the top of the plugin window. Without this change, the screen reader focus helpfully returns to the combo box button. Seems like the ideal behavior should be the latter in both cases?

We released a fix on develop addressing the “lost focus” problem when the ComboBox has a parent specified