1 | /* gtkatspiutils.c: Shared utilities for ATSPI |
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 | #include "config.h" |
22 | |
23 | #include "gtkatspiutilsprivate.h" |
24 | |
25 | #include "gtkenums.h" |
26 | #include "gtkpasswordentry.h" |
27 | #include "gtkscrolledwindow.h" |
28 | |
29 | /*< private > |
30 | * gtk_accessible_role_to_atspi_role: |
31 | * @role: a `GtkAccessibleRole` |
32 | * |
33 | * Converts a `GtkAccessibleRole` value to the equivalent ATSPI role. |
34 | * |
35 | * Returns: an #AtspiRole |
36 | */ |
37 | static AtspiRole |
38 | gtk_accessible_role_to_atspi_role (GtkAccessibleRole role) |
39 | { |
40 | switch (role) |
41 | { |
42 | case GTK_ACCESSIBLE_ROLE_ALERT: |
43 | return ATSPI_ROLE_ALERT; |
44 | |
45 | case GTK_ACCESSIBLE_ROLE_ALERT_DIALOG: |
46 | return ATSPI_ROLE_DIALOG; |
47 | |
48 | case GTK_ACCESSIBLE_ROLE_BANNER: |
49 | break; |
50 | |
51 | case GTK_ACCESSIBLE_ROLE_BUTTON: |
52 | return ATSPI_ROLE_PUSH_BUTTON; |
53 | |
54 | case GTK_ACCESSIBLE_ROLE_CAPTION: |
55 | return ATSPI_ROLE_CAPTION; |
56 | |
57 | case GTK_ACCESSIBLE_ROLE_CELL: |
58 | return ATSPI_ROLE_TABLE_CELL; |
59 | |
60 | case GTK_ACCESSIBLE_ROLE_CHECKBOX: |
61 | return ATSPI_ROLE_CHECK_BOX; |
62 | |
63 | case GTK_ACCESSIBLE_ROLE_COLUMN_HEADER: |
64 | break; |
65 | |
66 | case GTK_ACCESSIBLE_ROLE_COMBO_BOX: |
67 | return ATSPI_ROLE_COMBO_BOX; |
68 | |
69 | case GTK_ACCESSIBLE_ROLE_COMMAND: |
70 | break; |
71 | |
72 | case GTK_ACCESSIBLE_ROLE_COMPOSITE: |
73 | break; |
74 | |
75 | case GTK_ACCESSIBLE_ROLE_DIALOG: |
76 | return ATSPI_ROLE_DIALOG; |
77 | |
78 | case GTK_ACCESSIBLE_ROLE_DOCUMENT: |
79 | return ATSPI_ROLE_DOCUMENT_TEXT; |
80 | |
81 | case GTK_ACCESSIBLE_ROLE_FEED: |
82 | break; |
83 | |
84 | case GTK_ACCESSIBLE_ROLE_FORM: |
85 | return ATSPI_ROLE_FORM; |
86 | |
87 | case GTK_ACCESSIBLE_ROLE_GENERIC: |
88 | break; |
89 | |
90 | case GTK_ACCESSIBLE_ROLE_GRID: |
91 | return ATSPI_ROLE_TABLE; |
92 | |
93 | case GTK_ACCESSIBLE_ROLE_GRID_CELL: |
94 | return ATSPI_ROLE_TABLE_CELL; |
95 | |
96 | case GTK_ACCESSIBLE_ROLE_GROUP: |
97 | return ATSPI_ROLE_PANEL; |
98 | |
99 | case GTK_ACCESSIBLE_ROLE_HEADING: |
100 | return ATSPI_ROLE_HEADING; |
101 | |
102 | case GTK_ACCESSIBLE_ROLE_IMG: |
103 | return ATSPI_ROLE_IMAGE; |
104 | |
105 | case GTK_ACCESSIBLE_ROLE_INPUT: |
106 | return ATSPI_ROLE_ENTRY; |
107 | |
108 | case GTK_ACCESSIBLE_ROLE_LABEL: |
109 | return ATSPI_ROLE_LABEL; |
110 | |
111 | case GTK_ACCESSIBLE_ROLE_LANDMARK: |
112 | break; |
113 | |
114 | case GTK_ACCESSIBLE_ROLE_LEGEND: |
115 | return ATSPI_ROLE_LABEL; |
116 | |
117 | case GTK_ACCESSIBLE_ROLE_LINK: |
118 | return ATSPI_ROLE_LINK; |
119 | |
120 | case GTK_ACCESSIBLE_ROLE_LIST: |
121 | return ATSPI_ROLE_LIST; |
122 | |
123 | case GTK_ACCESSIBLE_ROLE_LIST_BOX: |
124 | return ATSPI_ROLE_LIST_BOX; |
125 | |
126 | case GTK_ACCESSIBLE_ROLE_LIST_ITEM: |
127 | return ATSPI_ROLE_LIST_ITEM; |
128 | |
129 | case GTK_ACCESSIBLE_ROLE_LOG: |
130 | return ATSPI_ROLE_LOG; |
131 | |
132 | case GTK_ACCESSIBLE_ROLE_MAIN: |
133 | break; |
134 | |
135 | case GTK_ACCESSIBLE_ROLE_MARQUEE: |
136 | return ATSPI_ROLE_MARQUEE; |
137 | |
138 | case GTK_ACCESSIBLE_ROLE_MATH: |
139 | return ATSPI_ROLE_MATH; |
140 | |
141 | case GTK_ACCESSIBLE_ROLE_METER: |
142 | return ATSPI_ROLE_LEVEL_BAR; |
143 | |
144 | case GTK_ACCESSIBLE_ROLE_MENU: |
145 | return ATSPI_ROLE_MENU; |
146 | |
147 | case GTK_ACCESSIBLE_ROLE_MENU_BAR: |
148 | return ATSPI_ROLE_MENU_BAR; |
149 | |
150 | case GTK_ACCESSIBLE_ROLE_MENU_ITEM: |
151 | return ATSPI_ROLE_MENU_ITEM; |
152 | |
153 | case GTK_ACCESSIBLE_ROLE_MENU_ITEM_CHECKBOX: |
154 | return ATSPI_ROLE_CHECK_MENU_ITEM; |
155 | |
156 | case GTK_ACCESSIBLE_ROLE_MENU_ITEM_RADIO: |
157 | return ATSPI_ROLE_RADIO_MENU_ITEM; |
158 | |
159 | case GTK_ACCESSIBLE_ROLE_NAVIGATION: |
160 | return ATSPI_ROLE_FILLER; |
161 | |
162 | case GTK_ACCESSIBLE_ROLE_NONE: |
163 | return ATSPI_ROLE_INVALID; |
164 | |
165 | case GTK_ACCESSIBLE_ROLE_NOTE: |
166 | return ATSPI_ROLE_FOOTNOTE; |
167 | |
168 | case GTK_ACCESSIBLE_ROLE_OPTION: |
169 | return ATSPI_ROLE_OPTION_PANE; |
170 | |
171 | case GTK_ACCESSIBLE_ROLE_PRESENTATION: |
172 | return ATSPI_ROLE_SECTION; |
173 | |
174 | case GTK_ACCESSIBLE_ROLE_PROGRESS_BAR: |
175 | return ATSPI_ROLE_PROGRESS_BAR; |
176 | |
177 | case GTK_ACCESSIBLE_ROLE_RADIO: |
178 | return ATSPI_ROLE_RADIO_BUTTON; |
179 | |
180 | case GTK_ACCESSIBLE_ROLE_RADIO_GROUP: |
181 | return ATSPI_ROLE_GROUPING; |
182 | |
183 | case GTK_ACCESSIBLE_ROLE_RANGE: |
184 | break; |
185 | |
186 | case GTK_ACCESSIBLE_ROLE_REGION: |
187 | return ATSPI_ROLE_FILLER; |
188 | |
189 | case GTK_ACCESSIBLE_ROLE_ROW: |
190 | return ATSPI_ROLE_TABLE_ROW; |
191 | |
192 | case GTK_ACCESSIBLE_ROLE_ROW_GROUP: |
193 | return ATSPI_ROLE_GROUPING; |
194 | |
195 | case GTK_ACCESSIBLE_ROLE_ROW_HEADER: |
196 | return ATSPI_ROLE_ROW_HEADER; |
197 | |
198 | case GTK_ACCESSIBLE_ROLE_SCROLLBAR: |
199 | return ATSPI_ROLE_SCROLL_BAR; |
200 | |
201 | case GTK_ACCESSIBLE_ROLE_SEARCH: |
202 | return ATSPI_ROLE_FORM; |
203 | |
204 | case GTK_ACCESSIBLE_ROLE_SEARCH_BOX: |
205 | return ATSPI_ROLE_ENTRY; |
206 | |
207 | case GTK_ACCESSIBLE_ROLE_SECTION: |
208 | return ATSPI_ROLE_FILLER; |
209 | |
210 | case GTK_ACCESSIBLE_ROLE_SECTION_HEAD: |
211 | return ATSPI_ROLE_FILLER; |
212 | |
213 | case GTK_ACCESSIBLE_ROLE_SELECT: |
214 | return ATSPI_ROLE_FILLER; |
215 | |
216 | case GTK_ACCESSIBLE_ROLE_SEPARATOR: |
217 | return ATSPI_ROLE_SEPARATOR; |
218 | |
219 | case GTK_ACCESSIBLE_ROLE_SLIDER: |
220 | return ATSPI_ROLE_SLIDER; |
221 | |
222 | case GTK_ACCESSIBLE_ROLE_SPIN_BUTTON: |
223 | return ATSPI_ROLE_SPIN_BUTTON; |
224 | |
225 | case GTK_ACCESSIBLE_ROLE_STATUS: |
226 | return ATSPI_ROLE_STATUS_BAR; |
227 | |
228 | case GTK_ACCESSIBLE_ROLE_STRUCTURE: |
229 | return ATSPI_ROLE_FILLER; |
230 | |
231 | case GTK_ACCESSIBLE_ROLE_SWITCH: |
232 | return ATSPI_ROLE_CHECK_BOX; |
233 | |
234 | case GTK_ACCESSIBLE_ROLE_TAB: |
235 | return ATSPI_ROLE_PAGE_TAB; |
236 | |
237 | case GTK_ACCESSIBLE_ROLE_TABLE: |
238 | return ATSPI_ROLE_TABLE; |
239 | |
240 | case GTK_ACCESSIBLE_ROLE_TAB_LIST: |
241 | return ATSPI_ROLE_PAGE_TAB_LIST; |
242 | |
243 | case GTK_ACCESSIBLE_ROLE_TAB_PANEL: |
244 | return ATSPI_ROLE_PANEL; |
245 | |
246 | case GTK_ACCESSIBLE_ROLE_TEXT_BOX: |
247 | return ATSPI_ROLE_TEXT; |
248 | |
249 | case GTK_ACCESSIBLE_ROLE_TIME: |
250 | return ATSPI_ROLE_TEXT; |
251 | |
252 | case GTK_ACCESSIBLE_ROLE_TIMER: |
253 | return ATSPI_ROLE_TIMER; |
254 | |
255 | case GTK_ACCESSIBLE_ROLE_TOOLBAR: |
256 | return ATSPI_ROLE_TOOL_BAR; |
257 | |
258 | case GTK_ACCESSIBLE_ROLE_TOOLTIP: |
259 | return ATSPI_ROLE_TOOL_TIP; |
260 | |
261 | case GTK_ACCESSIBLE_ROLE_TREE: |
262 | return ATSPI_ROLE_TREE; |
263 | |
264 | case GTK_ACCESSIBLE_ROLE_TREE_GRID: |
265 | return ATSPI_ROLE_TREE_TABLE; |
266 | |
267 | case GTK_ACCESSIBLE_ROLE_TREE_ITEM: |
268 | return ATSPI_ROLE_TREE_ITEM; |
269 | |
270 | case GTK_ACCESSIBLE_ROLE_WIDGET: |
271 | return ATSPI_ROLE_FILLER; |
272 | |
273 | case GTK_ACCESSIBLE_ROLE_WINDOW: |
274 | return ATSPI_ROLE_FRAME; |
275 | |
276 | default: |
277 | break; |
278 | } |
279 | |
280 | return ATSPI_ROLE_FILLER; |
281 | } |
282 | |
283 | /*<private> |
284 | * gtk_atspi_role_for_context: |
285 | * @context: a `GtkATContext` |
286 | * |
287 | * Returns a suitable ATSPI role for a context, taking into account |
288 | * both the `GtkAccessibleRole` set on the context and the type |
289 | * of accessible. |
290 | * |
291 | * Returns: an #AtspiRole |
292 | */ |
293 | AtspiRole |
294 | gtk_atspi_role_for_context (GtkATContext *context) |
295 | { |
296 | GtkAccessible *accessible = gtk_at_context_get_accessible (self: context); |
297 | GtkAccessibleRole role = gtk_at_context_get_accessible_role (self: context); |
298 | |
299 | /* ARIA does not have a "password entry" role, so we need to fudge it here */ |
300 | if (GTK_IS_PASSWORD_ENTRY (accessible)) |
301 | return ATSPI_ROLE_PASSWORD_TEXT; |
302 | |
303 | /* ARIA does not have a "scroll area" role */ |
304 | if (GTK_IS_SCROLLED_WINDOW (accessible)) |
305 | return ATSPI_ROLE_SCROLL_PANE; |
306 | |
307 | return gtk_accessible_role_to_atspi_role (role); |
308 | } |
309 | |
310 | GVariant * |
311 | gtk_at_spi_null_ref (void) |
312 | { |
313 | return g_variant_new (format_string: "(so)" , "" , "/org/a11y/atspi/null" ); |
314 | } |
315 | |
316 | void |
317 | gtk_at_spi_emit_children_changed (GDBusConnection *connection, |
318 | const char *path, |
319 | GtkAccessibleChildState state, |
320 | int idx, |
321 | GVariant *child_ref, |
322 | GVariant *sender_ref) |
323 | { |
324 | const char *change; |
325 | |
326 | switch (state) |
327 | { |
328 | case GTK_ACCESSIBLE_CHILD_STATE_ADDED: |
329 | change = "add" ; |
330 | break; |
331 | |
332 | case GTK_ACCESSIBLE_CHILD_STATE_REMOVED: |
333 | change = "remove" ; |
334 | break; |
335 | |
336 | default: |
337 | g_assert_not_reached (); |
338 | return; |
339 | } |
340 | |
341 | g_dbus_connection_emit_signal (connection, |
342 | NULL, |
343 | object_path: path, |
344 | interface_name: "org.a11y.atspi.Event.Object" , |
345 | signal_name: "ChildrenChanged" , |
346 | parameters: g_variant_new (format_string: "(siiv@(so))" , change, idx, 0, child_ref, sender_ref), |
347 | NULL); |
348 | } |
349 | |