JUCE Accessibility on `develop`

Another one: in TextEditorTextInterface::getTextBounds(), the border should be included too. Otherwise Narrator’s cursor gets shifted.

auto localRects = textEditor.getTextBounds (textRange);
localRects.offsetAll (textEditor.getBorder().getLeft(), textEditor.getBorder().getTop());

So now with macOS: Disable accessibility on deployment targets < 10.10 · juce-framework/JUCE@02c5ad2 · GitHub , building juce with a deployment target set to 10.9 disables all accessibility support on all macos versions – is that what was planned ?

If yes, it is a bit annoying as it will force me to deprecate macos < 10.10 for all my users.

1 Like

Thanks, I’ve added this to develop here:

1 Like

Yes, the accessibility API we’re using on macOS requires a deployment target of 10.10 or above.

Wouldn’t using an if (@available) runtime check allow both, targeting a lower deployment target and enabling accessibility in case we are running at least on macOS 10.10?

In juce_Button.cpp : ButtonAccessibilityHandler::getCurrentState() you should add a check if the button is also in a radio group, so that the selected item state is presented by accessibility, as shown in the modification below:

        if (button.getClickingTogglesState() || button.getRadioGroupId() != 0)

Did something change recently? When I use the tab key, Voice Over no longer follows the selection, it’s just stuck on the Window. The VO arrow keys don’t work either.

You probably need to set your deployment target to > 10.9.

That was it, thanks.

This commit Accessibility: Improved PopupMenu focus handling when opening and ad… · juce-framework/JUCE@b6bb2f4 · GitHub broke something in the popupmenu focus transfer when the menu is dismissed

Here is how to reproduce with the WindowsDemo of DemoRunner: replace the showDocumentWindow with this one:

    void showDocumentWindow (bool native)
      auto* dw = new DocumentWindow ("Document Window", getRandomBrightColour(), DocumentWindow::allButtons, false);
        windows.add (dw);

        Rectangle<int> area (0, 0, 300, 400);

        RectanglePlacement placement ((native ? RectanglePlacement::xLeft
                                              : RectanglePlacement::xRight)
                                       | RectanglePlacement::yTop
                                       | RectanglePlacement::doNotResize);

        auto result = placement.appliedTo (area, Desktop::getInstance().getDisplays()
                                                         .getPrimaryDisplay()->userArea.reduced (20));
        dw->setBounds (result);

        dw->setResizable (true, ! native);
        dw->setUsingNativeTitleBar (native);

        dw->setVisible (true);

        auto *bt = new TextButton("Hello");
        bt->onClick = [bt]() {
          PopupMenu m;
          m.addItem(1, "item1");
          m.addItem(2, "item2");
          m.addItem(3, "item3");
          m.showMenuAsync(PopupMenu::Options().withTargetComponent(bt), [](int result) {
            std::cerr << "menu done with result: " << result << "\n";
        dw->setContentOwned(bt, false);

and keep only one window in the showAllWindows method:

    void showAllWindows()

        showDocumentWindow (false);
        //showDocumentWindow (true);

Then launch demorunner, start voiceover, select the windows demo, click the “show windows” button and in the document window, click on the “Hello” button. A PopupMenu appear. Now select some menu entry. When the menu is hidden, the focus is restored to the DemoRunner window, not the DocumentWindow.

Commenting the visibilityChanged() function that has been added in the commit fixes the issue, although I don’t understand why.

On Windows, Narrator focus seems to get stuck when it hits a Label when in scan mode (Narrator + space). For example open the DemoRunner settings panel, there are many labels and each time one of them gets the focus, the “Up” and “Down” keys won’t move anymore to the next accessible element. We can still move with “Narrator + Left” or “Narrator + right”, though. But the previous versions of juce develop did not get stuck on labels in scan mode.

Does anybody know a good way to handle Dialogs in plugins? It’s not a good idea for plugins to open new windows, so when I want to show a dialog in my plugin, I frost the UI, add a component on top and that component enters modal state.

In that component I added:

std::unique_ptr<juce::AccessibilityHandler> Modal::createAccessibilityHandler()
	return std::make_unique<juce::AccessibilityHandler> ( *this, juce::AccessibilityRole::dialogWindow );

This works is the dialog accepts keyboard focus, then it reads the text of the dialog. However, I don’t want the dialog to accept keyboard focus, just the components on the dialog. Is there a way I can tell Voice Over I’m entering a dialog?

It looks like some of our devs on macOS can’t build our project with their slightly older systems (older Xcode and older OS) due to the NSAccessibilityRole being supported only from 10.13 and up.

What are we to do when we want to support 10.9 and up?

1 Like

The @available keyword was only introduced with the version of Clang shipped in Xcode 9 and JUCE needs to support back to Xcode 7.3.1, so we can’t use it here unfortunately.

who still use this version of Xcode ?

While I can understand to support users up to 10.9, there are other way to do that besides using an Xcode version of 2016

These are just NSString*s under the hood and we typedef NSAccessibilityRole on older SDKs -

Is this not working for you?

JUCE supports back to building against the 10.11 SDK which was included in Xcode 7.

Using the @available keyword would require bumping the minimum macOS SDK version to 10.13 and the Xcode version to 9. Xcode 9 also requires macOS 10.12.6 so we’d be restricting users there too. It’s a little bit too much of a jump to justify for this currently I think.

You can build with 10.11 SDK with xcode 12 with some hack.
@available is related to the SDK version or xcode version ?

@available is a compiler feature so it depends on the Xcode version not the SDK version.