-
Bug
-
Resolution: Fixed
-
Not Evaluated
-
6.11.0 FF
-
None
-
Debian trixie, qtbase self-compiled from git dev as of commit 6f353fc17a3a6f1786359df36db209d6c5b0fa42
-
-
980d8ee59 (dev), 7a478ff96 (dev)
Qt currently does not support the AT-SPI Collection interface that can be used to efficiently search for accessible objects in an application's accessibility (sub)tree.
Recently, browse mode in the Orca screen reader was made available for non-browser applications, but it depends on the AT-SPI Collection interface, meaning it doesn't work for Qt applications.
The Orca developer even suggested that implementing the Collection interface in the libatspi client library for toolkits not implementing itself might be a workaround that is at least better than nothing.
Corresponding issue: https://gitlab.gnome.org/GNOME/at-spi2-core/-/issues/139
However, that would be very inefficient, because libatspi would still need to iterate over the children in the a11y tree, and that would require multiple AT-SPI and therefore DBus calls for every single child being inspected (to retrieve the next child from Qt via DBus, to get the relevant attributes to compare to the search criteria,...).
In particular for applications with larger/non-trivial accessibility trees, having an implementation inside Qt itself seems to be the only viable option (since then all of the iteration over the a11y tree can happen inside Qt/C++, without involving any DBus overhead except for receiving the initial request and sending the final response).
Sample steps to reproduce:
- run the qtbase spinboxes example on Linux: qt5/qtbase/examples/widgets/widgets/spinboxes/spinboxes
- start Accerciser Accessibility Explorer
- select the Qt application's accessible root object in Accerciser's treeview of the application's accessibility tree
- in Accerciser's IPython console, check which AT-SPI interfaces are supported
In [94]: acc.get_interfaces() Out[94]: ['Accessible', 'Application']
-> This unfortunately does not include the "Collection" interface.
As expected (due to the previous step), trying to query for the interface fails, which is unfortunate:
In [95]: acc.queryCollection() --------------------------------------------------------------------------- NotImplementedError Traceback (most recent call last) Cell In[95], line 1 ----> 1 acc.queryCollection()File /usr/lib/python3/dist-packages/pyatspi/Accessibility.py:144, in <lambda>(x) 141 Atspi.Accessible.atspiVersion = property(fget=Atspi.Accessible.get_atspi_version) 143 Atspi.Accessible.queryAction = lambda x: Action(getInterface(Atspi.Accessible.get_action_iface, x)) --> 144 Atspi.Accessible.queryCollection = lambda x: Collection(getInterface(Atspi.Accessible.get_collection_iface, x)) 145 Atspi.Accessible.queryComponent = lambda x: Component(getInterface(Atspi.Accessible.get_component_iface, x)) 146 Atspi.Accessible.queryDocument = lambda x: Document(getInterface(Atspi.Accessible.get_document_iface, x))File /usr/lib/python3/dist-packages/pyatspi/Accessibility.py:68, in getInterface(func, obj) 66 if ret: 67 return ret ---> 68 raise
In comparison: GTK 3 example where it works:
- start gtk3-demo
- start Accerciser Accessibility Explorer
- select the application's root object in Accerciser's treeview of the application's accessibility tree
- start the "Spin Buttons" example
- in Accerciser's IPython console, check which AT-SPI interfaces are supported:
In [92]: acc.get_interfaces() Out[92]: ['Accessible', 'Application', 'Collection']
Using the AT-SPI Collection interface, successfully retrieve the first 3 descendants that are visible and have an AT-SPI SPIN_BUTTON role and implement the Accessible and Action interfaces:
In [97]: collection = acc.queryCollection() rule = collection.createMatchRule(Atspi.StateSet(Atspi.StateType.VISIBLE), Atspi.CollectionMatchType.ALL, [], Atspi.CollectionMatchType.ALL, [Atspi.Role.SPIN_BUTTON], Atspi.CollectionMatchType.ALL, ["Action", "Accessible"], Atspi.CollectionMatchType.ALL, False) collection.getMatches(rule, Atspi.CollectionSortOrder.CANONICAL, 3, True) Out[97]: [<Atspi.Accessible object at 0x7fc6553fe900 (AtspiAccessible at 0x37c56f50)>, <Atspi.Accessible object at 0x7fc655b1a040 (AtspiAccessible at 0x37bd19e0)>, <Atspi.Accessible object at 0x7fc6552afa80 (AtspiAccessible at 0x373d5810)>]
Many more queries are possible.