Being a visually impaired person poses many challenges. You not only need special software, like, for example, the Linux screen reader Orca, but you more than often find out about a redesign in a desktop application because suddenly, something breaks. And, if the redesign affects not only the application, but the library used for creating them, you can be almost sure that something slips through the cracks. And, unfortunately, the redesign of the accessibility infrastructure in GTK 4 was no exception.
So, that’s the reason why I am now working at Red Hat and trying to fix these issues.
The need for a change
But, first, why break something which was working pretty well in GTK 3?
I was not part of these discussions, so I can provide only a limited answer to that question, but one of the reasons was to remove a dependency on the ATK library, which complicated building, was an additional dependency, and it imposed restrictions on how the accessibility subsystem looks like.
Another reason was to make the APIs used by application developers much more similar to the VAI-ARIA ones, which should allow pushing accessibility much more easily than before.
Actually, many of these goals were indeet fulfilled. The build was simplified, and the APIs began looking sane. And the APIs actually had some documentation, so that was good as well.
Unfortunately, how the visually impaired people perceive an application is not only dependent on the toolkit, but on the screen reader as well. And, that started to pose a number of issues. Some of them were fixed quickly, some of them were fixed after a long time, and some of these aren’t fixed even today.
And it does not help that the community of people which would notice these issues is so small. So, what was wrong?
The missing value change notifications
Let’s start with something simple. Imagine a slider, like, for example, a volume slider in a music player. When you somehow change its value, you would expect that you actually know about such an event. In GTK 3, you did. But in GTK 4, until GTK 4.10, you did not.
The reason for that behavior is actually quite simple in this case. For a screen reader to know that a value of a control changed, it needs to receive a notification about that fact, because the screen reader is not constantly checking the entire tree of accessibility objects for a modification, that would be way too inefficient. Unfortunately, the notification was not dispatched in this particular case.
But, getting this particular issue fixed was not hard, actually, much more time took before anyone noticed it.
The cases of missing information
Another group of issues, whose fix was relatively simple, could be in general summarized as missing information. There was quite some of these, but their solution was relatively simple.
In the first group of issues, a semantic property of a GTK control, for example the indication that a control is required, or has additional details associated with it, could be set by the programmer of a GTK application (not that many did that), but the fact was not communicated to the API which a screen reader uses to get this kind of information. Fortunately, AT-SPI2, the software communicating the accessibility information under Linux, already had all the needed concepts, so it was just a simple matter of returning the correct value when translating the GTK properties.
The second group of issues was the same, so, there were semantic definitions missing, but now, they did not have GTK equivalents at all. Fortunately, it was not too complicated to add them to GTK and them bridge them to AT-SPI2. This was, for example, the case of the visited state for a link, or a link button.
The VAI-ARIA world is too ideal
As previously mentioned, one of the reasons why rewrite the entire accessibility subsystem of GTK was to make it much more similar to the VAI-ARIA model. In that model, you have elements with a role, and some properties, which can hold a value. Because GTK wanted to be similar, it adopted a similar model with roles (like a button), properties (like a detailed description of the control) and states (like the checked state for a button). And, not to deviate from VAI-ARIA too much, both states and properties could hold a value. Unfortunately, the, much older, AT-SPI2 architecture counts with the same basic building blocks, however, AT-SPI2 states are either present, or not, e. g. are just a set of binary flags. That is the reason, for example, why you need both a checked and checkable state in AT-SPI2. If you did not have them, you could not on that layer tell, for example, whether a list item is not checked, but can be (that would be aria-checked="false" in ARIA), or is not meant to be checked at all (that would be a missing aria-checked attribute).
This difference in representations of course caused issues for the translation from the GTK accessibility information to AT-SPI2. Sometimes, it was enough only to add the second state, like when representing the checked state, in other cases, like, for example, in the case of toggle buttons, it was necessary to add an additionall special role for them, so the screen reading software could report them as not pressed toggles, and not just as plain buttons, which sometimes get pressed.
The accessible tree is not always your widget tree
Maybe because there was not enough time when implementing the accessibility subsystem for the first time, it turned out rather tangled with the rest of the library. For example, even that there exists a GtkAccessible interface in GTK, which should represent an accessible object, the backend assumed that nothing else than a widget will ever be an accessible, and used the widget APIs. That worked, but at a cost. Most of the time, the widget tree was exactly the same as the tree of the accessible objects, ignoring children which were ignored in the accessibility tree, but they don’t cause any trouble, so this is not the issue. But, when implementing the GtkStack widget (a container containing a number of widgets which could be switched on demand), it was decided that the pages will be accessible objects as well.
But, because the GtkStack pages did not implement the GtkAccessible interface, the implementation of the AT-SPI2 backend had to special case them everywhere. The pages unfortunately implemented not only the Accessible interface from AT-SPI2, but a bunch of others as well.
To fix this, it was necessary to extend the G_tkAccessible interface, so you could, for example, ask for the boundaries of the object in terms of its parent coordinate system. Then, it was just a question of rewriting everything related to the core accessibility concepts in terms of the GtkAccessible interface, a few times changing its methods, so they resemble the GTK interfaces rather than the interfaces from AT-SPI2 (mainly the methods for enumerating the children of an accessible object), waiting for a review, which was not short, because the change was quite substantial, and then, in GTK 4.10, the work was merged.
The way ahead
Of course, the previously mentioned issues are not the end of the story, we’ve just started. For example, a lot of the GTK’s accessibility subsystem still assumes that accessible objects are specific widgets, for example, the implementation of the AT-SPI2 AccessibleText interface does it, as, unfortunately, not everything in GTK implements GtkEditable, so we can’t use just that.
But, having the accessibility support in the toolkit is a good beginning, however, it is still necessary to make the applications use the tools. Many of the fixes will be simple, but many will require more work, or changes in GTK itself.
So, now you know something about how the accessibility in GTK fares, what needed to be changed, and what are the plans. I hope you learned something interesting, and if you want to help, I’d be glad to answer any questions.