JUCE Accessibility on `develop`

Using a staticText role with AccessibilityTextValueInterface again limits the readable text to 1000 characters. Should we use a read-only AccessibilityTextInterface now?

Thanks for the help - I was just expecting different behaviour, it’s working now

Is there a way to test this behavior?

Using the AccessibilityRole::staticText role won’t limit the number of characters, but for text > 1000 characters you’ll need to implement a read-only AccessibilityTextInterface. Take a look at the TextEditorAccessibilityHandler and CodeEditorComponent::CodeEditorAccessibilityHandler for how we handle it there - they no longer implement an AccessibilityValueInterface and instead only expose the text via the text interface.

1 Like

Strange regression on macos, it seems that other applications cannot retrieve the title of JUCE windows. If I run this command line, while DemoRunner is running:

osascript -e 'tell application "System Events" to get the title of every window of every process'

With DemoRunner from ‘master’, I get:

,,,,,,,,,,,,,,,,,,,,,,,,,,, Hammerspoon Console,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 
Default (tmux),,,,,,,,,,,,,,,,, juce_gui_basics.cpp,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 

While with DemoRunner from ‘develop’, I get:

,,,,,,,,,,,,,,,,,,,,,,,,,,, Hammerspoon Console,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 
Default (tmux),,,,,,,,,,,,,,,,, juce_gui_basics.cpp,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, 
missing value,

On windows, AccessibilityHandler::postAnnouncement works even when Narrator is turned off.

Btw I think it could be convenient to have a function that returns true if VoiceOver or Narrator is currently enabled.

1 Like

Hi all

I want to add accessibility to a listbox that contains a sample library and would like to have some pointers on how to implement it.

The first issue is that when the listbox is selected using the tab key, Narrator says “selection contains 0 items” which is not the case since the list contains hundreds of items. How do I make it read to correct number of lines?

The second issue is that when using up and down arrows, the list items are not selected in terms of accessibility. Meaning that they are highlighted but not showing Narrator’s selection rectangle around them so of course nothing happens. I would like Narrator’s to read the first cell of a row which has the sample’s file name but I think this will involve grabbing the keyboard focus which will force the user to painfully go through all items in the list just to get out of it, or am I wrong?

The third issue is that I would also like to read the rest of the columns of each line since they have useful info about the sample such as description, category and duration. This seems like an issue because the listbox itself doesn’t respond to left and right keys so do I first need to customize the listbox to highlight single cells instead of entire rows? Or, is there another way to solve this using a custom AccessibilityHandler?

On Windows, AccessibilityHandler::postAnnouncement is speaking the announcement even when the screen reader is off. Is this the expected behaviour?

1 Like

Thanks, this is fixed in cae59fa.

Unlike VoiceOver, Narrator doesn’t have built-in functionality for announcing text so we’re using SpVoice as a workaround. Because this isn’t linked to Narrator it’ll read out the text regardless of whether Narrator is enabled or not.

We could work around this by checking whether Narrator is enabled and only posting the announcement in that case, but there’s also no way of checking this. Screen readers set the SPI_GETSCREENREADER system parameter but Narrator does not (Screen reader parameter - Win32 apps | Microsoft Docs) and using UiaClientsAreListening() will only work until Narrator is enabled the first time after which it will return true even when it’s been turned off. I’ve added some checks in cdf3b61 but this isn’t 100% reliable unfortunately.

Unlike VoiceOver, Narrator doesn’t have built-in functionality for announcing text

Have you considered using the RaiseNotificationEvent function available in UIAutomationCore.dll? You can use that to announce notifications with Narrator and NVDA? An example of this can be found in the REAPER OSARA plugin

Also, what would be the use case to announce a message by the screen reader explicitly? If the message is on screen, the screen reader should be able to announce it. I believe if you want to announce it explicitly, you can raise an automation event of type SystemAlertEvent. I believe that should force the screen reader to read the name of the event for which the event is fired.

Hope this wasn’t written before (I wasn’t able to find anything with the exception of PopUp menus).

Testing some of our code I’ve noticed juce::MenuBarComponent isn’t accessible.
(I’ve used Apple’s Accessibility inspector)

It’s reasonable to have a menubar in an app in addition to the native one.

(mind the two Edit / View menus or the Functions for the editor view).

The MenuBarComponent itself is ignored, but the actual items should be accessible. Testing the MenusDemo on macOS using VoiceOver I can navigate each of the menu items and trigger them to show their associated popup menus - are you seeing different behaviour?

Sorry, my bad. I’ve just tried it under VoiceOver and it seems to work.
(oddly AccessibilityInspector is behaving differently and might miss elements by just querying a specific point on display).


One of my testers found some interesting interaction between tooltips and MacOS VoiceOver. When you select “mouse pointer follows Voiceover cursor” in the Voiceover utility, a problem arises. As the mouse hovers over a control with a tooltip, the tooltip displays and the tooltip grabs the keyboard focus. Voiceover starts reading the tooltip text, but quickly something (I can’t work out what) grabs the keyboard focus back to the control and Voiceover starts reading that text. However, because we are hovering, the focus goes back to the tooltip and the process continues ad infinitum until the mouse cursor is moved away. You can reproduce this in the Jucedemo with the widgets demo, tabbing through the buttons demo

I believe the tooltip windows should be set with ‘setAccessible(false)’ – that’s what I did because otherwise it is really annoying with voiceover.

Thanks, that will work for me because I automatically set the help text from the tooltip text. But I can imagine scenarios where you would like Voiceover to read out the tooltip

For some reason I can’t get Voiceover to cooperate while Narrator seems to work. I created a very simple project with a listbox and a dummy component to toggle with. With Narrator I can toggle components and access the table’s header component. With Voiceover the curser is stuck on the table, not being able to toggle the other component or access the table header.

Also, with Narrator I can access the dummy component by clicking on it while Voiceover fails.

I figured this must be something on my local Voiceover settings so I tested on a different machine and again no luck.

Can someone have a look and either confirm that he is able to toggle components with Voiceover, or tell me what exactly is missing?
TableAccessibility.zip (2.9 MB)

Just downloaded the latest development build (1/7) and modal loops have now been disabled by default. I can’t find the rationale for this and was wondering if it’s safe to just enable modal loops in the projucer settings.

In general, breaking changes and their rationales can be found in the ‘BREAKING-CHANGES.txt’ document in the JUCE repo.

Modal operations are a frequent source of problems, particularly when used in plug-ins. On Android modal loops are not possible, so people wanting to target Android often have an unwelcome surprise when then have to rewrite what they assumed to be platform independent code. Changing the default addresses these problems.

If you’re writing a plugin, I’d strongly recommend against enabling modal loops. If you really need modal loops, you can re-enable them by adding JUCE_MODAL_LOOPS_PERMITTED=1 to your preprocessor definitions.