1Title: GTK Accessibility
2Slug: gtk-accessibility
3
4## The standard accessibility interface
5
6The `GtkAccessible` interface provides the accessibility information about
7an application's user interface elements. Assistive technology (AT)
8applications, like Orca, convey this information to users with disabilities,
9or reduced abilities, to help them use the application.
10
11Standard GTK controls implement the `GtkAccessible` interface and are thus
12accessible to ATs by default. This means that if you use GTK controls such
13as `GtkButton`, `GtkEntry`, or `GtkListView`, you only need to supply
14application-specific details when the defaults values are incomplete. You
15can do this by setting the appropriate properties in your `GtkBuilder`
16template and UI definition files, or by setting the properties defined by
17the `GtkAccessible` interface.
18
19If you are implementing your own `GtkWidget` derived type, you will need to
20set the `GtkAccessible` properties yourself, and provide an implementation
21of the `GtkAccessible` virtual functions.
22
23## Accessible roles and attributes
24
25The fundamental concepts of an accessible widget are *roles* and
26*attributes*; each GTK control has a role, while its functionality is
27described by a set of *attributes*.
28
29### Roles
30
31Roles define the taxonomy and semantics of a UI control to any assistive
32technology application; for instance, a button will have a role of
33`GTK_ACCESSIBLE_ROLE_BUTTON`; an entry will have a role of
34`GTK_ACCESSIBLE_ROLE_TEXTBOX`; a toggle button will have a role of
35`GTK_ACCESSIBLE_ROLE_CHECKBOX`; etc.
36
37Each role is part of the widget's instance, and **cannot** be changed over
38time or as the result of a user action. Roles allows assistive technology
39applications to identify a UI control and decide how to present it to a
40user; if a part of the application's UI changes role, the control needs to
41be removed and replaced with another one with the appropriate role.
42
43#### List of accessible roles
44
45Each role name is part of the #GtkAccessibleRole enumeration.
46
47| Role name | Description | Related GTK widget |
48|-----------|-------------|--------------------|
49| `BUTTON` | A control that performs an action when pressed | [class@Gtk.Button], [class@Gtk.LinkButton], [class@Gtk.Expander] |
50| `CHECKBOX` | A control that has three possible value: `true`, `false`, or `undefined` | [class@Gtk.CheckButton] |
51| `COMBOBOX` | A control that can be expanded to show a list of possible values to select | [class@Gtk.ComboBox] |
52| `COLUMN_HEADER` | A header in a columned list | [class@Gtk.ColumnView] |
53| `DIALOG` | A dialog that prompts the user to enter information or require a response | [class@Gtk.Dialog] and subclasses |
54| `GRID` | A grid of items | [class@Gtk.FlowBox], [class@Gtk.GridView] |
55| `GRID_CELL` | An item in a grid | [class@Gtk.FlowBoxChild], [class@Gtk.GridView], [class@Gtk.ColumnView] |
56| `IMG` | An image | [class@Gtk.Image], [class@Gtk.Picture] |
57| `LABEL` | A visible name or caption for a user interface component | [class@Gtk.Label] |
58| `LINK` | A clickable hyperlink | [class@Gtk.LinkButton] |
59| `LIST` | A list of items | [class@Gtk.ListBox] |
60| `LIST_ITEM` | An item in a list | [class@Gtk.ListBoxRow] |
61| `MENU` | A menu | [class@Gtk.PopoverMenu] |
62| `MENU_BAR` | A menubar | [class@Gtk.PopoverMenuBar] |
63| `MENU_ITEM` | A menu item | Items in [class@Gtk.PopoverMenu] |
64| `MENU_ITEM_CHECKBOX` | Check menu item | Items in [class@Gtk.PopoverMenu] |
65| `MENU_ITEM_RADIO` | Radio menu item | Items in [class@Gtk.PopoverMenu] |
66| `METER` | Represents a value within a known range | [class@Gtk.LevelBar] |
67| `NONE` | Not represented in the accessibility tree | the slider of a [class@Gtk.Scale] |
68| `PROGRESS_BAR` | An element that display progress | [class@Gtk.ProgressBar] |
69| `RADIO` | A checkable input in a group of radio roles | [class@Gtk.CheckButton] |
70| `ROW` | A row in a columned list | [class@Gtk.ColumnView] |
71| `SCROLLBAR` | A graphical object controlling the scrolling of content | [class@Gtk.Scrollbar] |
72| `SEARCH_BOX` | A text box for entering search criteria | [class@Gtk.SearchEntry] |
73| `SEPARATOR` | A divider that separates sections of content or groups of items | [class@Gtk.Separator] |
74| `SPIN_BUTTON` | A range control that allows seelcting among discrete choices | [class@Gtk.SpinButton] |
75| `SWITCH` | A control that represents on/off values | [class@Gtk.Switch] |
76| `TAB` | A tab in a list of tabs for switching pages | [class@Gtk.StackSwitcher], [class@Gtk.Notebook] |
77| `TAB_LIST` | A list of tabs for switching pages | [class@Gtk.StackSwitcher], [class@Gtk.Notebook] |
78| `TAB_PANEL` | A page in a notebook or stack | [class@Gtk.Stack] |
79| `TEXT_BOX` | A type of input that allows free-form text as its value. | [class@Gtk.Entry], [class@Gtk.PasswordEntry], [class@Gtk.TextView] |
80| `TREE_GRID` | A treeview-like columned list | [class@Gtk.ColumnView] |
81| `WINDOW` | An application window | [class@Gtk.Window] |
82| `...` | … |
83
84See the [WAI-ARIA](https://www.w3.org/WAI/PF/aria/appendices#quickref) list
85of roles for additional information.
86
87### Attributes
88
89Attributes provide specific information about an accessible UI
90control, and describe it for the assistive technology applications. GTK
91divides the accessible attributes into three categories:
92
93 - *properties*, described by the values of the `GtkAccessibleProperty`
94   enumeration
95 - *relations*, described by the values of the `GtkAccessibleRelation`
96   enumeration
97 - *states*, described by the values of the `GtkAccessibleState` enumeration
98
99Each attribute accepts a value of a specific type.
100
101Unlike roles, attributes may change over time, or in response to user action;
102for instance:
103
104 - a toggle button will change its %GTK_ACCESSIBLE_STATE_CHECKED state every
105   time it is toggled, either by the user or programmatically
106 - setting the mnemonic widget on a `GtkLabel` will update the
107   %GTK_ACCESSIBLE_RELATION_LABELLED_BY relation on the widget with a
108   reference to the label
109 - changing the `GtkAdjustment` instance on a `GtkScrollbar` will change the
110   %GTK_ACCESSIBLE_PROPERTY_VALUE_MAX, %GTK_ACCESSIBLE_PROPERTY_VALUE_MIN,
111   and %GTK_ACCESSIBLE_PROPERTY_VALUE_NOW properties with the upper, lower,
112   and value properties of the `GtkAdjustment`
113
114See the [WAI-ARIA](https://www.w3.org/WAI/PF/aria/appendices#quickref) list
115of attributes for additional information.
116
117#### List of accessible states
118
119Each state name is part of the `GtkAccessibleState` enumeration.
120
121| State name | ARIA attribute | Value type | Notes |
122|------------|----------------|------------|-------|
123| %GTK_ACCESSIBLE_STATE_BUSY | “aria-busy” | boolean |
124| %GTK_ACCESSIBLE_STATE_CHECKED | “aria-checked” | `GtkAccessibleTristate` | Indicates the current state of a [class@Gtk.CheckButton] |
125| %GTK_ACCESSIBLE_STATE_DISABLED | “aria-disabled” | boolean | Corresponds to the [property@Gtk.Widget:sensitive] property on [class@Gtk.Widget] |
126| %GTK_ACCESSIBLE_STATE_EXPANDED | “aria-expanded” | boolean or undefined | Corresponds to the  [property@Gtk.Expander:expanded] property on [class@Gtk.Expander] |
127| %GTK_ACCESSIBLE_STATE_HIDDEN | “aria-hidden” | boolean | Corresponds to the [property@Gtk.Widget:visible] property on [class@Gtk.Widget] |
128| %GTK_ACCESSIBLE_STATE_INVALID | “aria-invalid” | `GtkAccessibleInvalidState` | Set when a widget is showing an error |
129| %GTK_ACCESSIBLE_STATE_PRESSED | “aria-pressed” | `GtkAccessibleTristate` | Indicates the current state of a [class@Gtk.ToggleButton] |
130| %GTK_ACCESSIBLE_STATE_SELECTED | “aria-selected” | boolean or undefined | Set when a widget is selected |
131
132#### List of accessible properties
133
134Each property name is part of the `GtkAccessibleProperty` enumeration.
135
136| State name | ARIA attribute | Value type |
137|------------|----------------|------------|
138| %GTK_ACCESSIBLE_PROPERTY_AUTOCOMPLETE | “aria-autocomplete” | `GtkAccessibleAutocomplete` |
139| %GTK_ACCESSIBLE_PROPERTY_DESCRIPTION | “aria-description” | translatable string |
140| %GTK_ACCESSIBLE_PROPERTY_HAS_POPUP | “aria-haspopup” | boolean |
141| %GTK_ACCESSIBLE_PROPERTY_KEY_SHORTCUTS | “aria-keyshortcuts” | string |
142| %GTK_ACCESSIBLE_PROPERTY_LABEL | “aria-label” | translatable string |
143| %GTK_ACCESSIBLE_PROPERTY_LEVEL | “aria-level” | integer |
144| %GTK_ACCESSIBLE_PROPERTY_MODAL | “aria-modal” | boolean |
145| %GTK_ACCESSIBLE_PROPERTY_MULTI_LINE | “aria-multiline” | boolean |
146| %GTK_ACCESSIBLE_PROPERTY_MULTI_SELECTABLE | “aria-multiselectable” | boolean |
147| %GTK_ACCESSIBLE_PROPERTY_ORIENTATION | “aria-orientation” | `GtkOrientation` |
148| %GTK_ACCESSIBLE_PROPERTY_PLACEHOLDER | “aria-placeholder” | translatable string |
149| %GTK_ACCESSIBLE_PROPERTY_READ_ONLY | “aria-readonly” | boolean |
150| %GTK_ACCESSIBLE_PROPERTY_REQUIRED | “aria-required” | boolean |
151| %GTK_ACCESSIBLE_PROPERTY_ROLE_DESCRIPTION | “aria-roledescription” | translatable string |
152| %GTK_ACCESSIBLE_PROPERTY_SORT | “aria-sort” | `GtkAccessibleSort` |
153| %GTK_ACCESSIBLE_PROPERTY_VALUE_MAX | “aria-valuemax” | double |
154| %GTK_ACCESSIBLE_PROPERTY_VALUE_MIN | “aria-valuemin” | double |
155| %GTK_ACCESSIBLE_PROPERTY_VALUE_NOW | “aria-valuenow” | double |
156| %GTK_ACCESSIBLE_PROPERTY_VALUE_TEXT | “aria-valuetext” | translatable string |
157
158#### List of accessible relations
159
160Each relation name is part of the `GtkAccessibleRelation` enumeration.
161
162| State name | ARIA attribute | Value type |
163|------------|----------------|------------|
164| %GTK_ACCESSIBLE_RELATION_ACTIVE_DESCENDANT | “aria-activedescendant” | `GtkAccessible` |
165| %GTK_ACCESSIBLE_RELATION_COL_COUNT | “aria-colcount” | integer |
166| %GTK_ACCESSIBLE_RELATION_COL_INDEX | “aria-colindex” | integer |
167| %GTK_ACCESSIBLE_RELATION_COL_INDEX_TEXT | “aria-colindextext” | translatable string |
168| %GTK_ACCESSIBLE_RELATION_COL_SPAN | “aria-colspan” | integer |
169| %GTK_ACCESSIBLE_RELATION_CONTROLS | “aria-controls” | a list of `GtkAccessible` |
170| %GTK_ACCESSIBLE_RELATION_DESCRIBED_BY | “aria-describedby” | a list of `GtkAccessible` |
171| %GTK_ACCESSIBLE_RELATION_DETAILS | “aria-details” | a list of `GtkAccessible` |
172| %GTK_ACCESSIBLE_RELATION_ERROR_MESSAGE | “aria-errormessage” | `GtkAccessible` |
173| %GTK_ACCESSIBLE_RELATION_FLOW_TO | “aria-flowto” | a list of `GtkAccessible` |
174| %GTK_ACCESSIBLE_RELATION_LABELLED_BY | “aria-labelledby” | a list of `GtkAccessible` |
175| %GTK_ACCESSIBLE_RELATION_OWNS | “aria-owns” | a list of `GtkAccessible` |
176| %GTK_ACCESSIBLE_RELATION_POS_IN_SET | “aria-posinset” | integer |
177| %GTK_ACCESSIBLE_RELATION_ROW_COUNT | “aria-rowcount” | integer |
178| %GTK_ACCESSIBLE_RELATION_ROW_INDEX | “aria-rowindex” | integer |
179| %GTK_ACCESSIBLE_RELATION_ROW_INDEX_TEXT | “aria-rowindextext” | translatable string |
180| %GTK_ACCESSIBLE_RELATION_ROW_SPAN | “aria-rowspan” | integer |
181| %GTK_ACCESSIBLE_RELATION_SET_SIZE | “aria-setsize” | integer |
182
183*Note*: When using gtk_accessible_update_relation() with a relation that
184requires a list of `GtkAccessible` instances, you should pass every
185accessible object separately, followed by %NULL.
186
187## Application development rules
188
189Even if standard UI controls provided by GTK have accessibility information
190out of the box, there are some additional properties and considerations for
191application developers. For instance, if your application presents the user
192with a form to fill out, you should ensure that:
193
194 * the container of the form has a `GTK_ACCESSIBLE_ROLE_FORM` role
195 * each text entry widget in the form has the `GTK_ACCESSIBLE_RELATION_LABELLED_BY`
196   relation pointing to the label widget that describes it
197
198Another example: if you create a toolbar containing buttons with only icons,
199you should ensure that:
200
201 * the container has a `GTK_ACCESSIBLE_ROLE_TOOLBAR` role
202 * each button has a `GTK_ACCESSIBLE_PROPERTY_LABEL` property set with the user
203   readable and localised action performed when pressed; for instance "Copy",
204   "Paste", "Add layer", or "Remove"
205
206GTK will try to fill in some information by using ancillary UI control
207properties, for instance the accessible label will be taken from the label or
208placeholder text used by the UI control, or from its tooltip, if the
209`GTK_ACCESSIBLE_PROPERTY_LABEL` property or the `GTK_ACCESSIBLE_RELATION_LABELLED_BY`
210relation are unset. Nevertheless, it is good practice and project hygiene
211to explicitly specify the accessible properties, just like it's good practice
212to specify tooltips and style classes.
213
214Application developers using GTK **should** ensure that their UI controls
215are accessible as part of the development process. When using `GtkBuilder`
216templates and UI definition files, GTK provides a validation tool that
217verifies that each UI element has a valid role and properties; this tool can
218be used as part of the application's test suite to avoid regressions.
219
220## Implementations
221
222Each UI control implements the `GtkAccessible` interface to allow widget and
223application developers to specify the roles, state, and relations between UI
224controls. This API is purely descriptive.
225
226Each `GtkAccessible` implementation must provide a `GtkATContext` instance,
227which acts as a proxy to the specific platform's accessibility API:
228
229 * AT-SPI on Linux/BSD
230 * NSAccessibility on macOS
231 * Active Accessibility on Windows
232
233Additionally, an ad hoc accessibility backend is available for the GTK
234testsuite, to ensure reproducibility of issues in the CI pipeline.
235
236## Authoring practices
237
238The authoring practices are aimed at application developers, as well as
239developers of GUI elements based on GTK.
240
241Functionally, `GtkAccessible` roles, states, properties, and relations are
242analogous to a CSS for assistive technologies. For screen reader users, for
243instance, the various accessible attributes control the rendering of their
244non-visual experience. Incorrect roles and attributes may result in a
245completely inaccessible user interface.
246
247### A role is a promise
248
249The following code:
250
251```c
252gtk_widget_class_set_accessible_role (widget_class, GTK_ACCESSIBLE_ROLE_BUTTON);
253```
254
255is a promise that the widget being created will provide the same keyboard
256interactions expected for a button. An accessible role of a button will not
257turn automatically any widget into a `GtkButton`; but if your widget behaves
258like a button, using the %GTK_ACCESSIBLE_ROLE_BUTTON will allow any
259assistive technology to handle it like they would a `GtkButton`.
260
261### Attributes can both hide and enhance
262
263Accessible attributes can be used to override the content of a UI element,
264for instance:
265
266```c
267gtk_label_set_text (GTK_LABEL (label), "Some text");
268gtk_accessible_update_property (GTK_ACCESSIBLE (label),
269				GTK_ACCESSIBLE_PROPERTY_LABEL,
270				"Assistive technologies users will perceive "
271				"this text, not the contents of the label",
272				-1);
273```
274
275In the example above, the "label" property will override the contents of the
276label widget.
277
278The attributes can also enhance the UI:
279
280```c
281gtk_button_set_label (GTK_BUTTON (button), "Download");
282gtk_box_append (GTK_BOX (button), button);
283
284gtk_label_set_text (GTK_LABEL (label), "Final report.pdf");
285gtk_box_append (GTK_BOX (box), label);
286
287gtk_accessible_update_relation (GTK_ACCESSIBLE (button),
288				GTK_ACCESSIBLE_RELATION_LABELLED_BY,
289				g_list_append (NULL, label),
290				-1);
291```
292
293In the example above, an assistive technology will read the button's
294accessible label as "Download Final report.pdf".
295
296The power of hiding and enhancing can be a double-edged sword, as it can
297lead to inadvertently overriding the accessible semantics of existing
298widgets.
299
300## Hiding UI elements from the accessible tree
301
302The accessibility API is mainly used to express semantics useful for
303assistive technologies, but it can also be used to hide elements. The
304canonical way to do so is to use the %GTK_ACCESSIBLE_ROLE_PRESENTATION,
305which declares that a UI element is purely meant for presentation purposes,
306and as such it has no meaningful impact on the accessibility of the
307interface.
308
309A "presentation" role should not be confused with the
310%GTK_ACCESSIBLE_STATE_HIDDEN state; the "hidden" state is transient, and is
311typically controlled by showing and hiding a widget using the `GtkWidget`
312API.
313
314## Design patterns and custom widgets
315
316When creating custom widgets, following established patterns can help
317ensuring that the widgets work well for users of accessible technologies
318as well.
319
320### Buttons
321
322A button is a widget that enables users to trigger an action. While it is
323recommended you use `GtkButton` for anything that looks and behaves like a
324button, it is possible to apply a button behavior to UI elements like images
325by using a `GtkGestureClick` gesture. When doing so, you should:
326
327  - Give your widget the role %GTK_ACCESSIBLE_ROLE_BUTTON
328  - Install an action with no parameters, which will activate the widget
329
330### Custom entries
331
332For custom entries, it is highly recommended that you implement the
333`GtkEditable` interface by using a `GtkText` widget as delegate. If you
334do this, GTK will make your widgets text editing functionality accessible
335in the same way as a `GtkSpinButton` or `GtkSearchEntry`.
336
337### Tab-based UI
338
339If you make a tab-based interface, you should consider using `GtkStack`
340as the core, and just make a custom tab widget to control the active
341stack page. When doing so, the following extra steps will ensure that
342your tabs are accessible in the same way as `GtkStackSwitcher` or `GtkNotebook`:
343
344- Give your tab container the role %GTK_ACCESSIBLE_ROLE_TAB_LIST
345- Give your tab widgets the role %GTK_ACCESSIBLE_ROLE_TAB
346- Set up the %GTK_ACCESSIBLE_RELATION_CONTROLS relation between each
347  tab and the `GtkStackPage` object for its page
348- Set the %GTK_ACCESSIBLE_PROPERTY_SELECTED property on each tab, with
349  the active tab getting the value %TRUE, all others %FALSE
350
351To allow changing the active tab via accessible technologies, you can
352export actions. Since the accessibility interfaces only support actions
353without parameters, you can either provide `previous-tab` and `next-tab`
354actions on the tab container that let users step through the tabs one-by-one,
355or add a `activate-tab` action on each tab.
356
357### Value controls
358
359A value control (ie a widget that controls a one-dimensional quantity
360that can be represented by a `GtkAdjustment`) can be represented to
361accessible technologies by setting the %GTK_ACCESSIBLE_PROPERTY_VALUE_MIN,
362%GTK_ACCESSIBLE_PROPERTY_VALUE_MAX, and %GTK_ACCESSIBLE_PROPERTY_VALUE_NOW
363properties.
364
365To allow changing the value via accessible technologies, you can export
366actions.  Since the accessibility interfaces only support actions
367without parameters, you should provide actions such as `increase-value`
368and `decrease-value`.
369