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 | |
55 | G_DEFINE_INTERFACE (GtkAccessible, gtk_accessible, G_TYPE_OBJECT) |
56 | |
57 | static void |
58 | gtk_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 | */ |
87 | GtkATContext * |
88 | gtk_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 | */ |
103 | GtkAccessibleRole |
104 | gtk_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 | */ |
139 | void |
140 | gtk_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 | |
183 | out: |
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 | */ |
201 | void |
202 | gtk_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 | */ |
247 | void |
248 | gtk_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 | */ |
286 | void |
287 | gtk_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 | |
330 | out: |
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 | */ |
348 | void |
349 | gtk_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 | */ |
394 | void |
395 | gtk_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 | */ |
433 | void |
434 | gtk_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 | |
477 | out: |
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 | */ |
495 | void |
496 | gtk_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 | */ |
543 | void |
544 | gtk_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 | |
559 | static 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 | */ |
651 | const char * |
652 | gtk_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 | */ |
676 | void |
677 | gtk_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 | */ |
714 | gboolean |
715 | gtk_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 | */ |
732 | void |
733 | gtk_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 | */ |
761 | gboolean |
762 | gtk_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 | |
792 | void |
793 | gtk_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 | |