Setup a11y programmatically in Python

Hi,

In the official doc, there is a section explaining how to make a tab-based UI accessible: Gtk – 4.0: GTK Accessibility

Here is my attempt in Python:

import sys
import gi
gi.require_version('Gtk', '4.0')
from gi.repository import GObject, Gtk

class MyApp(Gtk.Application):

    def __init__(self):
        Gtk.Application.__init__(self)
        self.connect('activate', self.on_activate)

    def on_activate(self, app):
        self.add_window(MyAppWindow())

class MyAppWindow(Gtk.ApplicationWindow):

    def __init__(self):
        Gtk.ApplicationWindow.__init__(self, default_width=600, default_height=400)
        # Create widgets
        notebook = Gtk.Box(orientation='vertical')
        header = Gtk.Box(orientation='horizontal', accessible_role='tab-list')
        tab = Gtk.Label(label="Title", accessible_role='tab')
        container = Gtk.Stack(vexpand=True)
        page = container.add_child(Gtk.Label(label="Hello World!"))
        # Accessibility
        tab.update_state([Gtk.AccessibleState.SELECTED], [True])
        tab.update_relation([Gtk.AccessibleRelation.CONTROLS], [page])
        # Packing
        header.append(tab)
        notebook.append(header)
        notebook.append(container)
        self.set_child(notebook)
        self.present()

if __name__ == '__main__':
    sys.exit(MyApp().run(sys.argv))

But that doesn’t work, I get these errors:

test_a11y.py:31: Warning: g_value_get_int: assertion 'G_VALUE_HOLDS_INT (value)' failed
  tab.update_state([Gtk.AccessibleState.SELECTED], [True])
test_a11y.py:32: Warning: g_value_get_pointer: assertion 'G_VALUE_HOLDS_POINTER (value)' failed
  tab.update_relation([Gtk.AccessibleRelation.CONTROLS], [page])

For the SELECTED state, the warning disappears if I use integers like 0 or 1 instead of True/False. Looks weird, the doc says the expected type is “boolean or undefined”…

Regarding the CONTROLS relation, I’m unable to pass a correct value… I tried lots of things, like page, page.__gpointer__, or even GObject.Value(GObject.TYPE_POINTER, page.__gpointer__), without success.

Am I on the right path?

You cannot use Python’s boolean objects True or False if an accessible properties expects a boolean or undefined. You need to use 1, for true; 0, for false; or Gtk.ACCESSIBLE_VALUE_UNDEFINED, for undefined.

You need to create a Gtk.AccessibleList, e.g.

rel = Gtk.AccessibleList.new_from_list([page])
tab.update_relation([Gtk.AccessibleRelation.CONTROLS], [rel])
1 Like

And in addition to that, you’ll need to make the labels focusable, which they’re not by default, so gtk_widget_set_can_focus and gtk_widget_set_focusable is your friend (I don’t remember exactly whether you’ll need both in the label case).

1 Like

Thanks, I indeed missed the AccessibleList stuff.
Seems to work now!

Yeah, good point!
And probably “actionable” too.

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.