1/* gtkaccessible.c: Accessible interface
2 *
3 * Copyright 2020 GNOME Foundation
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20
21/**
22 * GtkAccessible:
23 *
24 * `GtkAccessible` is an interface for describing UI elements for
25 * Assistive Technologies.
26 *
27 * Every accessible implementation has:
28 *
29 * - a “role”, represented by a value of the [enum@Gtk.AccessibleRole] enumeration
30 * - an “attribute”, represented by a set of [enum@Gtk.AccessibleState],
31 * [enum@Gtk.AccessibleProperty] and [enum@Gtk.AccessibleRelation] values
32 *
33 * The role cannot be changed after instantiating a `GtkAccessible`
34 * implementation.
35 *
36 * The attributes are updated every time a UI element's state changes in
37 * a way that should be reflected by assistive technologies. For instance,
38 * if a `GtkWidget` visibility changes, the %GTK_ACCESSIBLE_STATE_HIDDEN
39 * state will also change to reflect the [property@Gtk.Widget:visible] property.
40 */
41
42#include "config.h"
43
44#include "gtkaccessibleprivate.h"
45
46#include "gtkatcontextprivate.h"
47#include "gtkenums.h"
48#include "gtktypebuiltins.h"
49#include "gtkwidget.h"
50
51#include <glib/gi18n-lib.h>
52
53#include <stdarg.h>
54
55G_DEFINE_INTERFACE (GtkAccessible, gtk_accessible, G_TYPE_OBJECT)
56
57static void
58gtk_accessible_default_init (GtkAccessibleInterface *iface)
59{
60 /**
61 * GtkAccessible:accessible-role: (attributes org.gtk.Property.get=gtk_accessible_get_accessible_role)
62 *
63 * The accessible role of the given `GtkAccessible` implementation.
64 *
65 * The accessible role cannot be changed once set.
66 */
67 GParamSpec *pspec =
68 g_param_spec_enum (name: "accessible-role",
69 nick: "Accessible Role",
70 blurb: "The role of the accessible object",
71 enum_type: GTK_TYPE_ACCESSIBLE_ROLE,
72 default_value: GTK_ACCESSIBLE_ROLE_NONE,
73 flags: G_PARAM_READWRITE |
74 G_PARAM_STATIC_STRINGS);
75
76 g_object_interface_install_property (g_iface: iface, pspec);
77}
78
79/*< private >
80 * gtk_accessible_get_at_context:
81 * @self: a `GtkAccessible`
82 *
83 * Retrieves the `GtkATContext` for the given `GtkAccessible`.
84 *
85 * Returns: (transfer none): the `GtkATContext`
86 */
87GtkATContext *
88gtk_accessible_get_at_context (GtkAccessible *self)
89{
90 g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), NULL);
91
92 return GTK_ACCESSIBLE_GET_IFACE (ptr: self)->get_at_context (self);
93}
94
95/**
96 * gtk_accessible_get_accessible_role: (attributes org.gtk.Method.get_property=accessible-role)
97 * @self: a `GtkAccessible`
98 *
99 * Retrieves the `GtkAccessibleRole` for the given `GtkAccessible`.
100 *
101 * Returns: a `GtkAccessibleRole`
102 */
103GtkAccessibleRole
104gtk_accessible_get_accessible_role (GtkAccessible *self)
105{
106 GtkAccessibleRole role;
107
108 g_return_val_if_fail (GTK_IS_ACCESSIBLE (self), GTK_ACCESSIBLE_ROLE_NONE);
109
110 GtkATContext *context = gtk_accessible_get_at_context (self);
111 if (context != NULL && gtk_at_context_is_realized (self: context))
112 return gtk_at_context_get_accessible_role (self: context);
113
114 g_object_get (G_OBJECT (self), first_property_name: "accessible-role", &role, NULL);
115
116 return role;
117}
118
119/**
120 * gtk_accessible_update_state:
121 * @self: a `GtkAccessible`
122 * @first_state: the first `GtkAccessibleState`
123 * @...: a list of state and value pairs, terminated by -1
124 *
125 * Updates a list of accessible states. See the [enum@Gtk.AccessibleState]
126 * documentation for the value types of accessible states.
127 *
128 * This function should be called by `GtkWidget` types whenever an accessible
129 * state change must be communicated to assistive technologies.
130 *
131 * Example:
132 * ```c
133 * value = GTK_ACCESSIBLE_TRISTATE_MIXED;
134 * gtk_accessible_update_state (GTK_ACCESSIBLE (check_button),
135 * GTK_ACCESSIBLE_STATE_CHECKED, value,
136 * -1);
137 * ```
138 */
139void
140gtk_accessible_update_state (GtkAccessible *self,
141 GtkAccessibleState first_state,
142 ...)
143{
144 GtkAccessibleState state;
145 GtkATContext *context;
146 va_list args;
147
148 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
149
150 context = gtk_accessible_get_at_context (self);
151 if (context == NULL)
152 return;
153
154 va_start (args, first_state);
155
156 state = first_state;
157
158 while (state != -1)
159 {
160 GError *error = NULL;
161 GtkAccessibleValue *value =
162 gtk_accessible_value_collect_for_state (state, error: &error, args: &args);
163
164 if (error != NULL)
165 {
166 g_critical ("Unable to collect value for state “%s”: %s",
167 gtk_accessible_state_get_attribute_name (state),
168 error->message);
169 g_error_free (error);
170 goto out;
171 }
172
173 gtk_at_context_set_accessible_state (self: context, state, value);
174
175 if (value != NULL)
176 gtk_accessible_value_unref (self: value);
177
178 state = va_arg (args, int);
179 }
180
181 gtk_at_context_update (self: context);
182
183out:
184 va_end (args);
185}
186
187/**
188 * gtk_accessible_update_state_value: (rename-to gtk_accessible_update_state)
189 * @self: a `GtkAccessible`
190 * @n_states: the number of accessible states to set
191 * @states: (array length=n_states): an array of `GtkAccessibleState`
192 * @values: (array length=n_states): an array of `GValues`, one for each state
193 *
194 * Updates an array of accessible states.
195 *
196 * This function should be called by `GtkWidget` types whenever an accessible
197 * state change must be communicated to assistive technologies.
198 *
199 * This function is meant to be used by language bindings.
200 */
201void
202gtk_accessible_update_state_value (GtkAccessible *self,
203 int n_states,
204 GtkAccessibleState states[],
205 const GValue values[])
206{
207 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
208 g_return_if_fail (n_states > 0);
209
210 GtkATContext *context = gtk_accessible_get_at_context (self);
211 if (context == NULL)
212 return;
213
214 for (int i = 0; i < n_states; i++)
215 {
216 GtkAccessibleState state = states[i];
217 const GValue *value = &(values[i]);
218 GError *error = NULL;
219 GtkAccessibleValue *real_value =
220 gtk_accessible_value_collect_for_state_value (state, value, error: &error);
221
222 if (error != NULL)
223 {
224 g_critical ("Unable to collect the value for state “%s”: %s",
225 gtk_accessible_state_get_attribute_name (state),
226 error->message);
227 g_error_free (error);
228 break;
229 }
230
231 gtk_at_context_set_accessible_state (self: context, state, value: real_value);
232
233 if (real_value != NULL)
234 gtk_accessible_value_unref (self: real_value);
235 }
236
237 gtk_at_context_update (self: context);
238}
239
240/**
241 * gtk_accessible_reset_state:
242 * @self: a `GtkAccessible`
243 * @state: a `GtkAccessibleState`
244 *
245 * Resets the accessible @state to its default value.
246 */
247void
248gtk_accessible_reset_state (GtkAccessible *self,
249 GtkAccessibleState state)
250{
251 GtkATContext *context;
252
253 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
254
255 context = gtk_accessible_get_at_context (self);
256 if (context == NULL)
257 return;
258
259 gtk_at_context_set_accessible_state (self: context, state, NULL);
260 gtk_at_context_update (self: context);
261}
262
263/**
264 * gtk_accessible_update_property:
265 * @self: a `GtkAccessible`
266 * @first_property: the first `GtkAccessibleProperty`
267 * @...: a list of property and value pairs, terminated by -1
268 *
269 * Updates a list of accessible properties.
270 *
271 * See the [enum@Gtk.AccessibleProperty] documentation for the
272 * value types of accessible properties.
273 *
274 * This function should be called by `GtkWidget` types whenever
275 * an accessible property change must be communicated to assistive
276 * technologies.
277 *
278 * Example:
279 * ```c
280 * value = gtk_adjustment_get_value (adjustment);
281 * gtk_accessible_update_property (GTK_ACCESSIBLE (spin_button),
282 GTK_ACCESSIBLE_PROPERTY_VALUE_NOW, value,
283 -1);
284 * ```
285 */
286void
287gtk_accessible_update_property (GtkAccessible *self,
288 GtkAccessibleProperty first_property,
289 ...)
290{
291 GtkAccessibleProperty property;
292 GtkATContext *context;
293 va_list args;
294
295 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
296
297 context = gtk_accessible_get_at_context (self);
298 if (context == NULL)
299 return;
300
301 va_start (args, first_property);
302
303 property = first_property;
304
305 while (property != -1)
306 {
307 GError *error = NULL;
308 GtkAccessibleValue *value =
309 gtk_accessible_value_collect_for_property (property, error: &error, args: &args);
310
311 if (error != NULL)
312 {
313 g_critical ("Unable to collect the value for property “%s”: %s",
314 gtk_accessible_property_get_attribute_name (property),
315 error->message);
316 g_error_free (error);
317 goto out;
318 }
319
320 gtk_at_context_set_accessible_property (self: context, property, value);
321
322 if (value != NULL)
323 gtk_accessible_value_unref (self: value);
324
325 property = va_arg (args, int);
326 }
327
328 gtk_at_context_update (self: context);
329
330out:
331 va_end (args);
332}
333
334/**
335 * gtk_accessible_update_property_value: (rename-to gtk_accessible_update_property)
336 * @self: a `GtkAccessible`
337 * @n_properties: the number of accessible properties to set
338 * @properties: (array length=n_properties): an array of `GtkAccessibleProperty`
339 * @values: (array length=n_properties): an array of `GValues`, one for each property
340 *
341 * Updates an array of accessible properties.
342 *
343 * This function should be called by `GtkWidget` types whenever an accessible
344 * property change must be communicated to assistive technologies.
345 *
346 * This function is meant to be used by language bindings.
347 */
348void
349gtk_accessible_update_property_value (GtkAccessible *self,
350 int n_properties,
351 GtkAccessibleProperty properties[],
352 const GValue values[])
353{
354 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
355 g_return_if_fail (n_properties > 0);
356
357 GtkATContext *context = gtk_accessible_get_at_context (self);
358 if (context == NULL)
359 return;
360
361 for (int i = 0; i < n_properties; i++)
362 {
363 GtkAccessibleProperty property = properties[i];
364 const GValue *value = &(values[i]);
365 GError *error = NULL;
366 GtkAccessibleValue *real_value =
367 gtk_accessible_value_collect_for_property_value (property, value, error: &error);
368
369 if (error != NULL)
370 {
371 g_critical ("Unable to collect the value for property “%s”: %s",
372 gtk_accessible_property_get_attribute_name (property),
373 error->message);
374 g_error_free (error);
375 break;
376 }
377
378 gtk_at_context_set_accessible_property (self: context, property, value: real_value);
379
380 if (real_value != NULL)
381 gtk_accessible_value_unref (self: real_value);
382 }
383
384 gtk_at_context_update (self: context);
385}
386
387/**
388 * gtk_accessible_reset_property:
389 * @self: a `GtkAccessible`
390 * @property: a `GtkAccessibleProperty`
391 *
392 * Resets the accessible @property to its default value.
393 */
394void
395gtk_accessible_reset_property (GtkAccessible *self,
396 GtkAccessibleProperty property)
397{
398 GtkATContext *context;
399
400 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
401
402 context = gtk_accessible_get_at_context (self);
403 if (context == NULL)
404 return;
405
406 gtk_at_context_set_accessible_property (self: context, property, NULL);
407 gtk_at_context_update (self: context);
408}
409
410/**
411 * gtk_accessible_update_relation:
412 * @self: a `GtkAccessible`
413 * @first_relation: the first `GtkAccessibleRelation`
414 * @...: a list of relation and value pairs, terminated by -1
415 *
416 * Updates a list of accessible relations.
417 *
418 * This function should be called by `GtkWidget` types whenever an accessible
419 * relation change must be communicated to assistive technologies.
420 *
421 * If the [enum@Gtk.AccessibleRelation] requires a list of references,
422 * you should pass each reference individually, followed by %NULL, e.g.
423 *
424 * ```c
425 * gtk_accessible_update_relation (accessible,
426 * GTK_ACCESSIBLE_RELATION_CONTROLS,
427 * ref1, NULL,
428 * GTK_ACCESSIBLE_RELATION_LABELLED_BY,
429 * ref1, ref2, ref3, NULL,
430 * -1);
431 * ```
432 */
433void
434gtk_accessible_update_relation (GtkAccessible *self,
435 GtkAccessibleRelation first_relation,
436 ...)
437{
438 GtkAccessibleRelation relation;
439 GtkATContext *context;
440 va_list args;
441
442 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
443
444 context = gtk_accessible_get_at_context (self);
445 if (context == NULL)
446 return;
447
448 va_start (args, first_relation);
449
450 relation = first_relation;
451
452 while (relation != -1)
453 {
454 GError *error = NULL;
455 GtkAccessibleValue *value =
456 gtk_accessible_value_collect_for_relation (relation, error: &error, args: &args);
457
458 if (error != NULL)
459 {
460 g_critical ("Unable to collect the value for relation “%s”: %s",
461 gtk_accessible_relation_get_attribute_name (relation),
462 error->message);
463 g_error_free (error);
464 goto out;
465 }
466
467 gtk_at_context_set_accessible_relation (self: context, property: relation, value);
468
469 if (value != NULL)
470 gtk_accessible_value_unref (self: value);
471
472 relation = va_arg (args, int);
473 }
474
475 gtk_at_context_update (self: context);
476
477out:
478 va_end (args);
479}
480
481/**
482 * gtk_accessible_update_relation_value: (rename-to gtk_accessible_update_relation)
483 * @self: a `GtkAccessible`
484 * @n_relations: the number of accessible relations to set
485 * @relations: (array length=n_relations): an array of `GtkAccessibleRelation`
486 * @values: (array length=n_relations): an array of `GValues`, one for each relation
487 *
488 * Updates an array of accessible relations.
489 *
490 * This function should be called by `GtkWidget` types whenever an accessible
491 * relation change must be communicated to assistive technologies.
492 *
493 * This function is meant to be used by language bindings.
494 */
495void
496gtk_accessible_update_relation_value (GtkAccessible *self,
497 int n_relations,
498 GtkAccessibleRelation relations[],
499 const GValue values[])
500{
501 GtkATContext *context;
502
503 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
504 g_return_if_fail (n_relations > 0);
505
506 context = gtk_accessible_get_at_context (self);
507
508 for (int i = 0; i < n_relations; i++)
509 {
510 GtkAccessibleRelation relation = relations[i];
511 const GValue *value = &(values[i]);
512 GError *error = NULL;
513 GtkAccessibleValue *real_value =
514 gtk_accessible_value_collect_for_relation_value (relation, value, error: &error);
515
516 if (error != NULL)
517 {
518 g_critical ("Unable to collect the value for relation “%s”: %s",
519 gtk_accessible_relation_get_attribute_name (relation),
520 error->message);
521 g_error_free (error);
522 break;
523 }
524
525 if (context)
526 gtk_at_context_set_accessible_relation (self: context, property: relation, value: real_value);
527
528 if (real_value != NULL)
529 gtk_accessible_value_unref (self: real_value);
530 }
531
532 if (context)
533 gtk_at_context_update (self: context);
534}
535
536/**
537 * gtk_accessible_reset_relation:
538 * @self: a `GtkAccessible`
539 * @relation: a `GtkAccessibleRelation`
540 *
541 * Resets the accessible @relation to its default value.
542 */
543void
544gtk_accessible_reset_relation (GtkAccessible *self,
545 GtkAccessibleRelation relation)
546{
547 GtkATContext *context;
548
549 g_return_if_fail (GTK_IS_ACCESSIBLE (self));
550
551 context = gtk_accessible_get_at_context (self);
552 if (context == NULL)
553 return;
554
555 gtk_at_context_set_accessible_relation (self: context, property: relation, NULL);
556 gtk_at_context_update (self: context);
557}
558
559static const char *role_names[] = {
560 [GTK_ACCESSIBLE_ROLE_ALERT] = NC_("accessibility", "alert"),
561 [GTK_ACCESSIBLE_ROLE_ALERT_DIALOG] = NC_("accessibility", "alert dialog"),
562 [GTK_ACCESSIBLE_ROLE_BANNER] = NC_("accessibility", "banner"),
563 [GTK_ACCESSIBLE_ROLE_BUTTON] = NC_("accessibility", "button"),
564 [GTK_ACCESSIBLE_ROLE_CAPTION] = NC_("accessibility", "caption"),
565 [GTK_ACCESSIBLE_ROLE_CELL] = NC_("accessibility", "cell"),
566 [GTK_ACCESSIBLE_ROLE_CHECKBOX] = NC_("accessibility", "checkbox"),
567 [GTK_ACCESSIBLE_ROLE_COLUMN_HEADER] = NC_("accessibility", "column header"),
568 [GTK_ACCESSIBLE_ROLE_COMBO_BOX] = NC_("accessibility", "combo box"),
569 [GTK_ACCESSIBLE_ROLE_COMMAND] = NC_("accessibility", "command"),
570 [GTK_ACCESSIBLE_ROLE_COMPOSITE] = NC_("accessibility", "composite"),
571 [GTK_ACCESSIBLE_ROLE_DIALOG] = NC_("accessibility", "dialog"),
572 [GTK_ACCESSIBLE_ROLE_DOCUMENT] = NC_("accessibility", "document"),
573 [GTK_ACCESSIBLE_ROLE_FEED] = NC_("accessibility", "feed"),
574 [GTK_ACCESSIBLE_ROLE_FORM] = NC_("accessibility", "form"),
575 [GTK_ACCESSIBLE_ROLE_GENERIC] = NC_("accessibility", "generic"),
576 [GTK_ACCESSIBLE_ROLE_GRID] = NC_("accessibility", "grid"),
577 [GTK_ACCESSIBLE_ROLE_GRID_CELL] = NC_("accessibility", "grid cell"),
578 [GTK_ACCESSIBLE_ROLE_GROUP] = NC_("accessibility", "group"),
579 [GTK_ACCESSIBLE_ROLE_HEADING] = NC_("accessibility", "heading"),
580 [GTK_ACCESSIBLE_ROLE_IMG] = NC_("accessibility", "image"),
581 [GTK_ACCESSIBLE_ROLE_INPUT] = NC_("accessibility", "input"),
582 [GTK_ACCESSIBLE_ROLE_LABEL] = NC_("accessibility", "label"),
583 [GTK_ACCESSIBLE_ROLE_LANDMARK] = NC_("accessibility", "landmark"),
584 [GTK_ACCESSIBLE_ROLE_LEGEND] = NC_("accessibility", "legend"),
585 [GTK_ACCESSIBLE_ROLE_LINK] = NC_("accessibility", "link"),
586 [GTK_ACCESSIBLE_ROLE_LIST] = NC_("accessibility", "list"),
587 [GTK_ACCESSIBLE_ROLE_LIST_BOX] = NC_("accessibility", "list box"),
588 [GTK_ACCESSIBLE_ROLE_LIST_ITEM] = NC_("accessibility", "list item"),
589 [GTK_ACCESSIBLE_ROLE_LOG] = NC_("accessibility", "log"),
590 [GTK_ACCESSIBLE_ROLE_MAIN] = NC_("accessibility", "main"),
591 [GTK_ACCESSIBLE_ROLE_MARQUEE] = NC_("accessibility", "marquee"),
592 [GTK_ACCESSIBLE_ROLE_MATH] = NC_("accessibility", "math"),
593 [GTK_ACCESSIBLE_ROLE_METER] = NC_("accessibility", "meter"),
594 [GTK_ACCESSIBLE_ROLE_MENU] = NC_("accessibility", "menu"),
595 [GTK_ACCESSIBLE_ROLE_MENU_BAR] = NC_("accessibility", "menu bar"),
596 [GTK_ACCESSIBLE_ROLE_MENU_ITEM] = NC_("accessibility", "menu item"),
597 [GTK_ACCESSIBLE_ROLE_MENU_ITEM_CHECKBOX] = NC_("accessibility", "menu item checkbox"),
598 [GTK_ACCESSIBLE_ROLE_MENU_ITEM_RADIO] = NC_("accessibility", "menu item radio"),
599 [GTK_ACCESSIBLE_ROLE_NAVIGATION] = NC_("accessibility", "navigation"),
600 [GTK_ACCESSIBLE_ROLE_NONE] = NC_("accessibility", "none"),
601 [GTK_ACCESSIBLE_ROLE_NOTE] = NC_("accessibility", "note"),
602 [GTK_ACCESSIBLE_ROLE_OPTION] = NC_("accessibility", "option"),
603 [GTK_ACCESSIBLE_ROLE_PRESENTATION] = NC_("accessibility", "presentation"),
604 [GTK_ACCESSIBLE_ROLE_PROGRESS_BAR] = NC_("accessibility", "progress bar"),
605 [GTK_ACCESSIBLE_ROLE_RADIO] = NC_("accessibility", "radio"),
606 [GTK_ACCESSIBLE_ROLE_RADIO_GROUP] = NC_("accessibility", "radio group"),
607 [GTK_ACCESSIBLE_ROLE_RANGE] = NC_("accessibility", "range"),
608 [GTK_ACCESSIBLE_ROLE_REGION] = NC_("accessibility", "region"),
609 [GTK_ACCESSIBLE_ROLE_ROW] = NC_("accessibility", "row"),
610 [GTK_ACCESSIBLE_ROLE_ROW_GROUP] = NC_("accessibility", "row group"),
611 [GTK_ACCESSIBLE_ROLE_ROW_HEADER] = NC_("accessibility", "row header"),
612 [GTK_ACCESSIBLE_ROLE_SCROLLBAR] = NC_("accessibility", "scroll bar"),
613 [GTK_ACCESSIBLE_ROLE_SEARCH] = NC_("accessibility", "search"),
614 [GTK_ACCESSIBLE_ROLE_SEARCH_BOX] = NC_("accessibility", "search box"),
615 [GTK_ACCESSIBLE_ROLE_SECTION] = NC_("accessibility", "section"),
616 [GTK_ACCESSIBLE_ROLE_SECTION_HEAD] = NC_("accessibility", "section head"),
617 [GTK_ACCESSIBLE_ROLE_SELECT] = NC_("accessibility", "select"),
618 [GTK_ACCESSIBLE_ROLE_SEPARATOR] = NC_("accessibility", "separator"),
619 [GTK_ACCESSIBLE_ROLE_SLIDER] = NC_("accessibility", "slider"),
620 [GTK_ACCESSIBLE_ROLE_SPIN_BUTTON] = NC_("accessibility", "spin button"),
621 [GTK_ACCESSIBLE_ROLE_STATUS] = NC_("accessibility", "status"),
622 [GTK_ACCESSIBLE_ROLE_STRUCTURE] = NC_("accessibility", "structure"),
623 [GTK_ACCESSIBLE_ROLE_SWITCH] = NC_("accessibility", "switch"),
624 [GTK_ACCESSIBLE_ROLE_TAB] = NC_("accessibility", "tab"),
625 [GTK_ACCESSIBLE_ROLE_TABLE] = NC_("accessibility", "table"),
626 [GTK_ACCESSIBLE_ROLE_TAB_LIST] = NC_("accessibility", "tab list"),
627 [GTK_ACCESSIBLE_ROLE_TAB_PANEL] = NC_("accessibility", "tab panel"),
628 [GTK_ACCESSIBLE_ROLE_TEXT_BOX] = NC_("accessibility", "text box"),
629 [GTK_ACCESSIBLE_ROLE_TIME] = NC_("accessibility", "time"),
630 [GTK_ACCESSIBLE_ROLE_TIMER] = NC_("accessibility", "timer"),
631 [GTK_ACCESSIBLE_ROLE_TOOLBAR] = NC_("accessibility", "tool bar"),
632 [GTK_ACCESSIBLE_ROLE_TOOLTIP] = NC_("accessibility", "tool tip"),
633 [GTK_ACCESSIBLE_ROLE_TREE] = NC_("accessibility", "tree"),
634 [GTK_ACCESSIBLE_ROLE_TREE_GRID] = NC_("accessibility", "tree grid"),
635 [GTK_ACCESSIBLE_ROLE_TREE_ITEM] = NC_("accessibility", "tree item"),
636 [GTK_ACCESSIBLE_ROLE_WIDGET] = NC_("accessibility", "widget"),
637 [GTK_ACCESSIBLE_ROLE_WINDOW] = NC_("accessibility", "window"),
638};
639
640/*< private >
641 * gtk_accessible_role_to_name:
642 * @role: a `GtkAccessibleRole`
643 * @domain: (nullable): the translation domain
644 *
645 * Converts a `GtkAccessibleRole` value to the equivalent role name.
646 *
647 * If @domain is not %NULL, the returned string will be localized.
648 *
649 * Returns: (transfer none): the name of the role
650 */
651const char *
652gtk_accessible_role_to_name (GtkAccessibleRole role,
653 const char *domain)
654{
655 if (domain != NULL)
656 return g_dpgettext2 (domain, context: "accessibility", msgid: role_names[role]);
657
658 return role_names[role];
659}
660
661/*<private>
662 * gtk_accessible_platform_changed:
663 * @self: a `GtkAccessible`
664 * @change: the platform state change to report
665 *
666 * Notify accessible technologies that a platform value has changed.
667 *
668 * ARIA discriminates between author-controlled states and 'platform'
669 * states, which are not. This function can be used by widgets to
670 * inform ATs that a platform state, such as focus, has changed.
671 *
672 * Note that the state itself is not included in this API.
673 * AT backends should use [method@Gtk.Accessible.get_platform_state]
674 * to obtain the actual state.
675 */
676void
677gtk_accessible_platform_changed (GtkAccessible *self,
678 GtkAccessiblePlatformChange change)
679{
680 GtkATContext *context;
681
682 if (GTK_IS_WIDGET (self) &&
683 gtk_widget_get_root (GTK_WIDGET (self)) == NULL)
684 return;
685
686 context = gtk_accessible_get_at_context (self);
687
688 /* propagate changes up from ignored widgets */
689 if (gtk_accessible_get_accessible_role (self) == GTK_ACCESSIBLE_ROLE_NONE)
690 context = gtk_accessible_get_at_context (self: GTK_ACCESSIBLE (ptr: gtk_widget_get_parent (GTK_WIDGET (self))));
691
692 if (context == NULL)
693 return;
694
695 gtk_at_context_platform_changed (self: context, change);
696 gtk_at_context_update (self: context);
697}
698
699/*<private>
700 * gtk_accessible_get_platform_state:
701 * @self: a `GtkAccessible`
702 * @state: platform state to query
703 *
704 * Query a platform state, such as focus.
705 *
706 * See gtk_accessible_platform_changed().
707 *
708 * This functionality can be overridden by `GtkAccessible`
709 * implementations, e.g. to get platform state from an ignored
710 * child widget, as is the case for `GtkText` wrappers.
711 *
712 * Returns: the value of @state for the accessible
713 */
714gboolean
715gtk_accessible_get_platform_state (GtkAccessible *self,
716 GtkAccessiblePlatformState state)
717{
718 return GTK_ACCESSIBLE_GET_IFACE (ptr: self)->get_platform_state (self, state);
719}
720
721/*<private>
722 * gtk_accessible_bounds_changed:
723 * @self: a `GtkAccessible`
724 *
725 * This function can be used to inform ATs that an
726 * accessibles bounds (ie its screen extents) have
727 * changed.
728 *
729 * Note that the bounds are not included in this API.
730 * AT backends should use widget API to obtain them.
731 */
732void
733gtk_accessible_bounds_changed (GtkAccessible *self)
734{
735 GtkATContext *context;
736
737 if (GTK_IS_WIDGET (self) &&
738 gtk_widget_get_root (GTK_WIDGET (self)) == NULL)
739 return;
740
741 context = gtk_accessible_get_at_context (self);
742 if (context == NULL)
743 return;
744
745 gtk_at_context_bounds_changed (self: context);
746}
747
748/*<private>
749 * gtk_accessible_should_present:
750 * @self: a `GtkAccessible`
751 *
752 * Returns whether this accessible should be represented to ATs.
753 *
754 * By default, hidden widgets are are among these, but there can
755 * be other reasons to return %FALSE, e.g. for widgets that are
756 * purely presentations, or for widgets whose functionality is
757 * represented elsewhere, as is the case for `GtkText` widgets.
758 *
759 * Returns: %TRUE if the widget should be represented
760 */
761gboolean
762gtk_accessible_should_present (GtkAccessible *self)
763{
764 GtkAccessibleRole role;
765 GtkATContext *context;
766
767 if (GTK_IS_WIDGET (self) &&
768 !gtk_widget_get_visible (GTK_WIDGET (self)))
769 return FALSE;
770
771 role = gtk_accessible_get_accessible_role (self);
772 if (role == GTK_ACCESSIBLE_ROLE_NONE ||
773 role == GTK_ACCESSIBLE_ROLE_PRESENTATION)
774 return FALSE;
775
776 context = gtk_accessible_get_at_context (self);
777 if (context == NULL)
778 return FALSE;
779
780 if (gtk_at_context_has_accessible_state (self: context, state: GTK_ACCESSIBLE_STATE_HIDDEN))
781 {
782 GtkAccessibleValue *value;
783
784 value = gtk_at_context_get_accessible_state (self: context, state: GTK_ACCESSIBLE_STATE_HIDDEN);
785 if (gtk_boolean_accessible_value_get (value))
786 return FALSE;
787 }
788
789 return TRUE;
790}
791
792void
793gtk_accessible_update_children (GtkAccessible *self,
794 GtkAccessible *child,
795 GtkAccessibleChildState state)
796{
797 GtkATContext *context;
798
799 if (GTK_IS_WIDGET (self) &&
800 gtk_widget_get_root (GTK_WIDGET (self)) == NULL)
801 return;
802
803 context = gtk_accessible_get_at_context (self);
804
805 /* propagate changes up from ignored widgets */
806 if (gtk_accessible_get_accessible_role (self) == GTK_ACCESSIBLE_ROLE_NONE)
807 context = gtk_accessible_get_at_context (self: GTK_ACCESSIBLE (ptr: gtk_widget_get_parent (GTK_WIDGET (self))));
808
809 if (context == NULL)
810 return;
811
812 gtk_at_context_child_changed (self: context, change: 1 << state, child);
813 gtk_at_context_update (self: context);
814}
815

source code of gtk/gtk/gtkaccessible.c