JUCE Accessibility on `develop`

Has accessibility support been released as stable in master nowadays? It’s mostly 6 months with it being the only upcoming feature that is grabbing the team attention from other tasks… Is there something else in the pipe or ? The world moves fast…

Yes, accessibility support was a part of the 6.1 release - JUCE 6.1 Released | JUCE.

If you look at the release notes for 6.1 there are plenty of other features and important bug-fixes and the recent commit log on develop will show you that we certainly haven’t been neglecting other work on the library.


This seems to have fixed the basic slider info, but it’s still not reading out values as you change the slider

Overlaying a component in iOS: if you display a child component such that it obscures part of the parent, the Accessibility handler will action the children of the parent component if there are blank spaces at that position on the child. This is a bit of a problem when you want to display configuration panels overlaid on the main screen, without having to change the visibility status of the parent. A typical use case in my case is that I have a main screen full of sliders, buttons and meters and I cover it with a panel with a few text fields, the underlying controls are not visible but are still actioned in VoiceOver.

This is similar to the overlay case I mentioned before, so it would happen in all platforms. It’s solved for the case when the overlay is modal, otherwise you have to resort to visibility or enablement.

Thanks - that works fine. I do find it a bit confusing that the Accessibility interface works differently than the GUI

Hmm, I think this change is a step backwards… for the extremely common case of people using a regular button (not an actual check-boxy ToggleButton) as a toggle-able button that visually shows its toggle state via background color or image, now they are no longer presented with their selected state read out by the Accessibility. The previous way of distinguishing them by using the getClickingTogglesState() just worked great. And there doesn’t appear to be a way for us to set the new toggle button accessibility role on individual instances of buttons, to get it back to the way it worked before, or am I just missing it? I don’t think @Roland1 requested you remove the getClickingTogglesState() as a distinguisher, I think they just requested a way to specify that any particular button instance might be toggle-able… am I right?

1 Like

@ed95 In testing the latest develop on iOS, it seems that normal async CalloutBoxes are impossible to dismiss with VoiceOver enabled… I can navigate through the items in it normally, but no VoiceOver gestures will get you out or dismiss the calloutbox. Note that this is happening with CalloutBoxes that have a parent component, I haven’t tried ones without.

As a point of comparison, in native iOS apps when a UIPopoverController is used, it seems the only 2 ways to dismiss them is to tap outside their bounds, and the VoiceOver asks to dismiss popup, and a double-tap does it. The other way is to use the “escape gesture”, which is a two finger “Z” movement. This site describes how it can be used: Adding accessible behavior .

More than confusing it’s a problem, kinda works for now with modals but it’s not the same.

I hadn’t noticed this change -completely second this. The state is not even read on change, so it’s totally inaccessible now.

To clarify: this change forces to distinguish all toggle buttons by deriving them from ToggleButton, or to rewrite ButtonAccessibilityHandler and derive all buttons from a Button subclass. I don’t think it makes sense to force subclassing for toggle behavior, it certainly doesn’t in my case. So for now ButtonAccessibilityHandler is useless for me. Is this settled or should I wait for a fix? Otherwise I should rewrite the handler.

I assume they will fix it because it is clear there was a miscommunication of intent. In the meantime, I have adapted my local version to bring back the old behavior.

Yes this should be the case. I’ve just verified by adding 2 buttons to the default JUCE GUI template app, using addAndMakeVisible() for the first and addChildComponent() for the second and the second, invisible button is not accessible to the screen reader.

Can you provide a code example that reproduces the issue?

I’m not seeing this behaviour on iOS. If I build the DemoRunner and open the slider page of the WidgetsDemo the slider value is read out as I change it using a single-finger swipe up or down. Can you try this and let me know if it works for you?

The z-order of components will be used for focus traversal if they are set to be always on top using Component::setAlwaysOnTop(). Can you use this method to control the accessible focus order for your app? Alternatively you could put the obscured components in a container component and call setEnabled (false) on that when the overlay is displayed. Or, like @kamedin mentioned, you could use enterModalState() to make the overlay modal - this will prevent the accessibility focus from moving outside of the modal component.

Would something like a setToggleable() method in Button work for your use-case? By default this would be false, but true for ToggleButtons, buttons that are a part of a radio button group, and buttons for which setClickingTogglesState (true) has been called. You could then call this on Button instances to indicate that they have a toggleable state and should be presented as a toggle to accessibility clients with an accessible “toggle” action that invokes setToggleState().

1 Like

So on setToggleable the new flag would be set with toggleable = shouldToggle, and on setClickingTogglesState with toggleable |= shouldToggle, right?

I made a test on Demo Rummer and I can’t reproduce this issue.
In my project I have added some textButton with addAndMakeVisible(button); and then depending on case, they are visible or not with setVisible().
I realized that if I navigate with VoiceOver with ctrl+alt+arrow everything works fine, instead if I navigate with tab sometimes the focus goes to these hidden buttons.
I need more time to investigate, keep you updated if I can reproduce the problem on a simple project. Thanks for your test and your time!

Yes, that’s how I think it should work since setClickingTogglesState (false); shouldn’t disable the “toggleable” behaviour if it has been explicitly set.

1 Like

This sounds like a good solution to me, satisfying our needs, thanks!

Great, I’ll put something on develop soon.

I’ve tried this on an iPhone 12 and it won’t read out the value as I move the slider. I’ve tried adjusting verbosity in the Voiceover settings, but no change