Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-139334

a11y: Qt doesn't support the AT-SPI Collection interface

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Not Evaluated Not Evaluated
    • 6.11.0 FF
    • 6.11.0 FF
    • None
    • Debian trixie, qtbase self-compiled from git dev as of commit 6f353fc17a3a6f1786359df36db209d6c5b0fa42
    • Linux/Wayland, Linux/X11
    • 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:

      1. run the qtbase spinboxes example on Linux: qt5/qtbase/examples/widgets/widgets/spinboxes/spinboxes
      2. start Accerciser Accessibility Explorer
      3. select the Qt application's accessible root object in Accerciser's treeview of the application's accessibility tree
      4. 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:

      1. start gtk3-demo
      2. start Accerciser Accessibility Explorer
      3. select the application's root object in Accerciser's treeview of the application's accessibility tree
      4. start the "Spin Buttons" example
      5. 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.

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            qt.team.quick.subscriptions Qt Quick and Widgets Team
            michaelweghorn Michael Weghorn
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:

                There is 1 open Gerrit change