Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/drivers/accesskit/accessibility_driver_accesskit.cpp
21072 views
1
/**************************************************************************/
2
/* accessibility_driver_accesskit.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#ifdef ACCESSKIT_ENABLED
32
33
#include "accessibility_driver_accesskit.h"
34
35
#include "core/config/project_settings.h"
36
#include "core/io/file_access.h"
37
#include "core/version.h"
38
39
#include "servers/text/text_server.h"
40
41
AccessibilityDriverAccessKit *AccessibilityDriverAccessKit::singleton = nullptr;
42
43
_FORCE_INLINE_ accesskit_role AccessibilityDriverAccessKit::_accessibility_role(DisplayServer::AccessibilityRole p_role) const {
44
if (role_map.has(p_role)) {
45
return role_map[p_role];
46
}
47
return ACCESSKIT_ROLE_UNKNOWN;
48
}
49
50
_FORCE_INLINE_ accesskit_action AccessibilityDriverAccessKit::_accessibility_action(DisplayServer::AccessibilityAction p_action) const {
51
if (action_map.has(p_action)) {
52
return action_map[p_action];
53
}
54
return ACCESSKIT_ACTION_CLICK;
55
}
56
57
bool AccessibilityDriverAccessKit::window_create(DisplayServer::WindowID p_window_id, void *p_handle) {
58
ERR_FAIL_COND_V(windows.has(p_window_id), false);
59
60
WindowData &wd = windows[p_window_id];
61
62
AccessibilityElement *ae = memnew(AccessibilityElement);
63
ae->role = ACCESSKIT_ROLE_WINDOW;
64
ae->window_id = p_window_id;
65
wd.root_id = rid_owner.make_rid(ae);
66
67
#ifdef WINDOWS_ENABLED
68
wd.adapter = accesskit_windows_subclassing_adapter_new(static_cast<HWND>(p_handle), &_accessibility_initial_tree_update_callback, (void *)(size_t)p_window_id, &_accessibility_action_callback, (void *)(size_t)p_window_id);
69
#endif
70
#ifdef MACOS_ENABLED
71
wd.adapter = accesskit_macos_subclassing_adapter_for_window(p_handle, &_accessibility_initial_tree_update_callback, (void *)(size_t)p_window_id, &_accessibility_action_callback, (void *)(size_t)p_window_id);
72
#endif
73
#ifdef LINUXBSD_ENABLED
74
wd.adapter = accesskit_unix_adapter_new(&_accessibility_initial_tree_update_callback, (void *)(size_t)p_window_id, &_accessibility_action_callback, (void *)(size_t)p_window_id, &_accessibility_deactivation_callback, (void *)(size_t)p_window_id);
75
#endif
76
77
if (wd.adapter == nullptr) {
78
memdelete(ae);
79
rid_owner.free(wd.root_id);
80
windows.erase(p_window_id);
81
82
return false;
83
} else {
84
return true;
85
}
86
}
87
88
void AccessibilityDriverAccessKit::window_destroy(DisplayServer::WindowID p_window_id) {
89
WindowData *wd = windows.getptr(p_window_id);
90
ERR_FAIL_NULL(wd);
91
92
#ifdef WINDOWS_ENABLED
93
accesskit_windows_subclassing_adapter_free(wd->adapter);
94
#endif
95
#ifdef MACOS_ENABLED
96
accesskit_macos_subclassing_adapter_free(wd->adapter);
97
#endif
98
#ifdef LINUXBSD_ENABLED
99
accesskit_unix_adapter_free(wd->adapter);
100
#endif
101
accessibility_free_element(wd->root_id);
102
103
windows.erase(p_window_id);
104
}
105
106
void AccessibilityDriverAccessKit::_accessibility_deactivation_callback(void *p_user_data) {
107
// NOP
108
}
109
110
void AccessibilityDriverAccessKit::_accessibility_action_callback(struct accesskit_action_request *p_request, void *p_user_data) {
111
DisplayServer::WindowID window_id = (DisplayServer::WindowID)(size_t)p_user_data;
112
ERR_FAIL_COND(!singleton->windows.has(window_id));
113
114
RID rid = RID::from_uint64(p_request->target);
115
AccessibilityElement *ae = singleton->rid_owner.get_or_null(rid);
116
ERR_FAIL_NULL(ae);
117
118
Variant rq_data;
119
if (!ae->actions.has(p_request->action) && ae->role == ACCESSKIT_ROLE_TEXT_RUN && p_request->action == ACCESSKIT_ACTION_SCROLL_INTO_VIEW) {
120
AccessibilityElement *root_ae = singleton->rid_owner.get_or_null(ae->parent);
121
ERR_FAIL_NULL(root_ae);
122
ae = root_ae;
123
rq_data = ae->run;
124
}
125
126
if (ae->actions.has(p_request->action)) {
127
Callable &cb = ae->actions[p_request->action];
128
if (cb.is_valid()) {
129
if (p_request->data.has_value) {
130
switch (p_request->data.value.tag) {
131
case ACCESSKIT_ACTION_DATA_CUSTOM_ACTION: {
132
rq_data = p_request->data.value.custom_action;
133
} break;
134
case ACCESSKIT_ACTION_DATA_VALUE: {
135
rq_data = String::utf8(p_request->data.value.value);
136
} break;
137
case ACCESSKIT_ACTION_DATA_NUMERIC_VALUE: {
138
rq_data = p_request->data.value.numeric_value;
139
} break;
140
case ACCESSKIT_ACTION_DATA_SCROLL_HINT: {
141
switch (p_request->data.value.scroll_hint) {
142
case ACCESSKIT_SCROLL_HINT_TOP_LEFT: {
143
rq_data = DisplayServer::SCROLL_HINT_TOP_LEFT;
144
} break;
145
case ACCESSKIT_SCROLL_HINT_BOTTOM_RIGHT: {
146
rq_data = DisplayServer::SCROLL_HINT_BOTTOM_RIGHT;
147
} break;
148
case ACCESSKIT_SCROLL_HINT_TOP_EDGE: {
149
rq_data = DisplayServer::SCROLL_HINT_TOP_EDGE;
150
} break;
151
case ACCESSKIT_SCROLL_HINT_BOTTOM_EDGE: {
152
rq_data = DisplayServer::SCROLL_HINT_BOTTOM_EDGE;
153
} break;
154
case ACCESSKIT_SCROLL_HINT_LEFT_EDGE: {
155
rq_data = DisplayServer::SCROLL_HINT_LEFT_EDGE;
156
} break;
157
case ACCESSKIT_SCROLL_HINT_RIGHT_EDGE: {
158
rq_data = DisplayServer::SCROLL_HINT_RIGHT_EDGE;
159
} break;
160
default:
161
break;
162
}
163
} break;
164
case ACCESSKIT_ACTION_DATA_SCROLL_UNIT: {
165
if (p_request->data.value.scroll_unit == ACCESSKIT_SCROLL_UNIT_ITEM) {
166
rq_data = DisplayServer::SCROLL_UNIT_ITEM;
167
} else if (p_request->data.value.scroll_unit == ACCESSKIT_SCROLL_UNIT_PAGE) {
168
rq_data = DisplayServer::SCROLL_UNIT_PAGE;
169
}
170
} break;
171
case ACCESSKIT_ACTION_DATA_SCROLL_TO_POINT: {
172
rq_data = Point2(p_request->data.value.scroll_to_point.x, p_request->data.value.scroll_to_point.y);
173
} break;
174
case ACCESSKIT_ACTION_DATA_SET_SCROLL_OFFSET: {
175
rq_data = Point2(p_request->data.value.set_scroll_offset.x, p_request->data.value.set_scroll_offset.y);
176
} break;
177
case ACCESSKIT_ACTION_DATA_SET_TEXT_SELECTION: {
178
Dictionary sel;
179
180
RID start_rid = RID::from_uint64(p_request->data.value.set_text_selection.anchor.node);
181
AccessibilityElement *start_ae = singleton->rid_owner.get_or_null(start_rid);
182
ERR_FAIL_NULL(start_ae);
183
184
RID end_rid = RID::from_uint64(p_request->data.value.set_text_selection.focus.node);
185
AccessibilityElement *end_ae = singleton->rid_owner.get_or_null(end_rid);
186
ERR_FAIL_NULL(end_ae);
187
188
sel["start_element"] = start_ae->parent;
189
sel["start_char"] = (int64_t)p_request->data.value.set_text_selection.anchor.character_index + start_ae->run.x;
190
sel["end_element"] = end_ae->parent;
191
sel["end_char"] = (int64_t)p_request->data.value.set_text_selection.focus.character_index + end_ae->run.x;
192
rq_data = sel;
193
} break;
194
}
195
}
196
197
cb.call_deferred(rq_data);
198
}
199
}
200
}
201
202
accesskit_tree_update *AccessibilityDriverAccessKit::_accessibility_initial_tree_update_callback(void *p_user_data) {
203
DisplayServer::WindowID window_id = (DisplayServer::WindowID)(size_t)p_user_data;
204
WindowData *wd = singleton->windows.getptr(window_id);
205
ERR_FAIL_NULL_V(wd, nullptr);
206
207
accesskit_node *win_node = accesskit_node_new(ACCESSKIT_ROLE_WINDOW);
208
accesskit_node_set_label(win_node, "Godot Engine");
209
accesskit_node_set_busy(win_node);
210
211
accesskit_node_id win_id = (accesskit_node_id)wd->root_id.get_id();
212
213
accesskit_tree_update *tree_update = accesskit_tree_update_with_capacity_and_focus(1, win_id);
214
215
accesskit_tree_update_set_tree(tree_update, accesskit_tree_new(win_id));
216
accesskit_tree_update_push_node(tree_update, win_id, win_node);
217
218
return tree_update;
219
}
220
221
RID AccessibilityDriverAccessKit::accessibility_create_element(DisplayServer::WindowID p_window_id, DisplayServer::AccessibilityRole p_role) {
222
AccessibilityElement *ae = memnew(AccessibilityElement);
223
ae->role = _accessibility_role(p_role);
224
ae->window_id = p_window_id;
225
RID rid = rid_owner.make_rid(ae);
226
227
return rid;
228
}
229
230
RID AccessibilityDriverAccessKit::accessibility_create_sub_element(const RID &p_parent_rid, DisplayServer::AccessibilityRole p_role, int p_insert_pos) {
231
AccessibilityElement *parent_ae = rid_owner.get_or_null(p_parent_rid);
232
ERR_FAIL_NULL_V(parent_ae, RID());
233
234
WindowData *wd = windows.getptr(parent_ae->window_id);
235
ERR_FAIL_NULL_V(wd, RID());
236
237
AccessibilityElement *ae = memnew(AccessibilityElement);
238
ae->role = _accessibility_role(p_role);
239
ae->window_id = parent_ae->window_id;
240
ae->parent = p_parent_rid;
241
ae->node = accesskit_node_new(ae->role);
242
RID rid = rid_owner.make_rid(ae);
243
if (p_insert_pos == -1) {
244
parent_ae->children.push_back(rid);
245
} else {
246
parent_ae->children.insert(p_insert_pos, rid);
247
}
248
wd->update.insert(rid);
249
250
return rid;
251
}
252
253
RID AccessibilityDriverAccessKit::accessibility_create_sub_text_edit_elements(const RID &p_parent_rid, const RID &p_shaped_text, float p_min_height, int p_insert_pos, bool p_is_last_line) {
254
AccessibilityElement *parent_ae = rid_owner.get_or_null(p_parent_rid);
255
ERR_FAIL_NULL_V(parent_ae, RID());
256
257
WindowData *wd = windows.getptr(parent_ae->window_id);
258
ERR_FAIL_NULL_V(wd, RID());
259
260
AccessibilityElement *root_ae = memnew(AccessibilityElement);
261
root_ae->role = ACCESSKIT_ROLE_GENERIC_CONTAINER;
262
root_ae->window_id = parent_ae->window_id;
263
root_ae->parent = p_parent_rid;
264
root_ae->node = accesskit_node_new(root_ae->role);
265
RID root_rid = rid_owner.make_rid(root_ae);
266
if (p_insert_pos == -1) {
267
parent_ae->children.push_back(root_rid);
268
} else {
269
parent_ae->children.insert(p_insert_pos, root_rid);
270
}
271
wd->update.insert(root_rid);
272
273
float text_width = 0;
274
float text_height = p_min_height;
275
Vector<int32_t> words;
276
int64_t run_count = 0; // Note: runs in visual order.
277
const Glyph *gl = nullptr;
278
int64_t gl_count = 0;
279
int64_t gl_index = 0;
280
float run_off_x = 0.0;
281
Vector2i full_range;
282
283
if (p_shaped_text.is_valid()) {
284
text_width = TS->shaped_text_get_size(p_shaped_text).x;
285
text_height = MAX(text_height, TS->shaped_text_get_size(p_shaped_text).y);
286
words = TS->shaped_text_get_word_breaks(p_shaped_text);
287
run_count = TS->shaped_get_run_count(p_shaped_text);
288
gl = TS->shaped_text_get_glyphs(p_shaped_text);
289
gl_count = TS->shaped_text_get_glyph_count(p_shaped_text);
290
full_range = TS->shaped_text_get_range(p_shaped_text);
291
}
292
293
accesskit_rect root_rect;
294
root_rect.x0 = 0;
295
root_rect.y0 = 0;
296
root_rect.x1 = text_width;
297
root_rect.y1 = MAX(p_min_height, text_height);
298
accesskit_node_set_bounds(root_ae->node, root_rect);
299
300
// Create text element for each run.
301
Vector<AccessibilityElement *> text_elements;
302
for (int64_t i = 0; i < run_count; i++) {
303
const Vector2i range = TS->shaped_get_run_range(p_shaped_text, i);
304
String t = TS->shaped_get_run_text(p_shaped_text, i);
305
306
if (t.is_empty()) {
307
continue;
308
}
309
310
AccessibilityElement *ae = memnew(AccessibilityElement);
311
ae->role = ACCESSKIT_ROLE_TEXT_RUN;
312
ae->window_id = parent_ae->window_id;
313
ae->parent = root_rid;
314
ae->run = Vector3i(range.x, range.y, i);
315
ae->node = accesskit_node_new(ae->role);
316
317
text_elements.push_back(ae);
318
319
// UTF-8 text and char lengths.
320
Vector<uint8_t> char_lengths;
321
CharString text = t.utf8(&char_lengths);
322
323
accesskit_node_set_value(ae->node, text.ptr());
324
accesskit_node_set_character_lengths(ae->node, char_lengths.size(), char_lengths.ptr());
325
326
// Word sizes.
327
Vector<uint8_t> word_lengths;
328
329
int32_t prev = ae->run.x;
330
int32_t total = 0;
331
for (int j = 0; j < words.size(); j += 2) {
332
if (words[j] < ae->run.x) {
333
continue;
334
}
335
if (words[j] >= ae->run.y) {
336
break;
337
}
338
int32_t wlen = words[j] - prev;
339
while (wlen > 255) {
340
word_lengths.push_back(255);
341
wlen -= 255;
342
total += 255;
343
}
344
if (wlen > 0) {
345
word_lengths.push_back(wlen);
346
total += wlen;
347
}
348
prev = words[j];
349
}
350
if (total < t.length()) {
351
word_lengths.push_back(t.length() - total);
352
}
353
accesskit_node_set_word_lengths(ae->node, word_lengths.size(), word_lengths.ptr());
354
355
// Char widths and positions.
356
Vector<float> char_positions;
357
Vector<float> char_widths;
358
359
char_positions.resize_initialized(t.length());
360
float *positions_ptr = char_positions.ptrw();
361
362
char_widths.resize_initialized(t.length());
363
float *widths_ptr = char_widths.ptrw();
364
365
float size_x = 0.0;
366
for (int j = gl_index; j < gl_count; j += gl[j].count) {
367
if (gl[j].start >= ae->run.y) {
368
gl_index = j;
369
break;
370
}
371
372
float advance = 0.0; // Graphame advance.
373
for (int k = 0; k < gl[j].count; k++) {
374
advance += gl[j + k].advance;
375
}
376
int chars = gl[j].end - gl[j].start;
377
float adv_per_char = advance / (float)chars;
378
379
for (int k = 0; k < chars; k++) {
380
int index = gl[j].start + k - ae->run.x;
381
ERR_CONTINUE(index < 0 || index >= t.length());
382
positions_ptr[index] = size_x + adv_per_char * k;
383
widths_ptr[index] = adv_per_char;
384
}
385
size_x += advance * gl[j].repeat;
386
}
387
positions_ptr[t.length() - 1] = size_x;
388
widths_ptr[t.length() - 1] = 1.0;
389
390
accesskit_node_set_character_positions(ae->node, char_positions.size(), char_positions.ptr());
391
accesskit_node_set_character_widths(ae->node, char_widths.size(), char_widths.ptr());
392
393
RID font_rid = TS->shaped_get_run_font_rid(p_shaped_text, i);
394
if (font_rid != RID()) {
395
CharString font_name = TS->font_get_name(font_rid).utf8();
396
if (font_name.length() > 0) {
397
accesskit_node_set_font_family(ae->node, font_name.ptr());
398
}
399
if (TS->font_get_style(font_rid).has_flag(TextServer::FONT_BOLD)) {
400
accesskit_node_set_bold(ae->node);
401
}
402
if (TS->font_get_style(font_rid).has_flag(TextServer::FONT_ITALIC)) {
403
accesskit_node_set_italic(ae->node);
404
}
405
accesskit_node_set_font_weight(ae->node, TS->font_get_weight(font_rid));
406
}
407
accesskit_node_set_font_size(ae->node, TS->shaped_get_run_font_size(p_shaped_text, i));
408
CharString language = TS->shaped_get_run_language(p_shaped_text, i).utf8();
409
if (language.length() > 0) {
410
accesskit_node_set_language(ae->node, language.ptr());
411
}
412
accesskit_node_set_text_direction(ae->node, ACCESSKIT_TEXT_DIRECTION_LEFT_TO_RIGHT);
413
414
accesskit_rect rect;
415
rect.x0 = run_off_x;
416
rect.y0 = 0;
417
rect.x1 = run_off_x + size_x;
418
rect.y1 = text_height;
419
accesskit_node_set_bounds(ae->node, rect);
420
accesskit_node_add_action(ae->node, ACCESSKIT_ACTION_SCROLL_INTO_VIEW);
421
422
run_off_x += size_x;
423
}
424
if (!p_is_last_line || text_elements.is_empty()) {
425
// Add "\n" at the end.
426
AccessibilityElement *ae = memnew(AccessibilityElement);
427
ae->role = ACCESSKIT_ROLE_TEXT_RUN;
428
ae->window_id = parent_ae->window_id;
429
ae->parent = root_rid;
430
ae->run = Vector3i(full_range.y, full_range.y, run_count);
431
ae->node = accesskit_node_new(ae->role);
432
433
text_elements.push_back(ae);
434
435
if (!p_is_last_line) {
436
accesskit_node_set_value(ae->node, "\n");
437
438
Vector<uint8_t> char_lengths;
439
Vector<float> char_positions;
440
Vector<float> char_widths;
441
char_lengths.push_back(1);
442
char_positions.push_back(0.0);
443
char_widths.push_back(1.0);
444
445
accesskit_node_set_character_lengths(ae->node, char_lengths.size(), char_lengths.ptr());
446
accesskit_node_set_character_positions(ae->node, char_positions.size(), char_positions.ptr());
447
accesskit_node_set_character_widths(ae->node, char_widths.size(), char_widths.ptr());
448
} else {
449
accesskit_node_set_value(ae->node, "");
450
}
451
accesskit_node_set_text_direction(ae->node, ACCESSKIT_TEXT_DIRECTION_LEFT_TO_RIGHT);
452
453
accesskit_rect rect;
454
rect.x0 = run_off_x;
455
rect.y0 = 0;
456
rect.x1 = run_off_x + 1;
457
rect.y1 = text_height;
458
accesskit_node_set_bounds(ae->node, rect);
459
}
460
461
// Sort runs in logical order.
462
struct RunCompare {
463
_FORCE_INLINE_ bool operator()(const AccessibilityElement *l, const AccessibilityElement *r) const {
464
return l->run.x < r->run.x;
465
}
466
};
467
text_elements.sort_custom<RunCompare>();
468
for (int i = 0; i < text_elements.size(); i++) {
469
RID rid = rid_owner.make_rid(text_elements[i]);
470
root_ae->children.push_back(rid);
471
wd->update.insert(rid);
472
473
// Link adjacent TextRuns on the same line.
474
if (i > 0) {
475
RID prev_rid = root_ae->children[i - 1];
476
AccessibilityElement *prev_ae = rid_owner.get_or_null(prev_rid);
477
accesskit_node_set_previous_on_line(text_elements[i]->node, (accesskit_node_id)prev_rid.get_id());
478
accesskit_node_set_next_on_line(prev_ae->node, (accesskit_node_id)rid.get_id());
479
}
480
}
481
482
return root_rid;
483
}
484
485
bool AccessibilityDriverAccessKit::accessibility_has_element(const RID &p_id) const {
486
return rid_owner.owns(p_id);
487
}
488
489
void AccessibilityDriverAccessKit::_free_recursive(WindowData *p_wd, const RID &p_id) {
490
if (p_wd && p_wd->update.has(p_id)) {
491
p_wd->update.erase(p_id);
492
}
493
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
494
for (const RID &rid : ae->children) {
495
_free_recursive(p_wd, rid);
496
}
497
if (ae->node) {
498
accesskit_node_free(ae->node);
499
}
500
memdelete(ae);
501
rid_owner.free(p_id);
502
}
503
504
void AccessibilityDriverAccessKit::accessibility_free_element(const RID &p_id) {
505
ERR_FAIL_COND_MSG(in_accessibility_update, "Element can't be removed inside NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
506
507
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
508
if (ae) {
509
WindowData *wd = windows.getptr(ae->window_id);
510
AccessibilityElement *parent_ae = rid_owner.get_or_null(ae->parent);
511
if (parent_ae) {
512
parent_ae->children.erase(p_id);
513
}
514
_free_recursive(wd, p_id);
515
}
516
}
517
518
void AccessibilityDriverAccessKit::accessibility_element_set_meta(const RID &p_id, const Variant &p_meta) {
519
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
520
521
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
522
ERR_FAIL_NULL(ae);
523
ae->meta = p_meta;
524
}
525
526
Variant AccessibilityDriverAccessKit::accessibility_element_get_meta(const RID &p_id) const {
527
const AccessibilityElement *ae = rid_owner.get_or_null(p_id);
528
ERR_FAIL_NULL_V(ae, Variant());
529
return ae->meta;
530
}
531
532
void AccessibilityDriverAccessKit::accessibility_update_set_focus(const RID &p_id) {
533
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
534
535
if (p_id.is_valid() && rid_owner.owns(p_id)) {
536
focus = p_id;
537
} else {
538
focus = RID();
539
}
540
}
541
542
RID AccessibilityDriverAccessKit::accessibility_get_window_root(DisplayServer::WindowID p_window_id) const {
543
const WindowData *wd = windows.getptr(p_window_id);
544
ERR_FAIL_NULL_V(wd, RID());
545
546
return wd->root_id;
547
}
548
549
accesskit_tree_update *AccessibilityDriverAccessKit::_accessibility_build_tree_update(void *p_user_data) {
550
DisplayServer::WindowID window_id = (DisplayServer::WindowID)(size_t)p_user_data;
551
552
ERR_FAIL_COND_V(!singleton->windows.has(window_id), nullptr);
553
WindowData &wd = singleton->windows[window_id];
554
555
singleton->in_accessibility_update = true;
556
if (singleton->update_cb.is_valid()) {
557
singleton->update_cb.call(window_id);
558
}
559
singleton->in_accessibility_update = false;
560
561
AccessibilityElement *focus_ae = singleton->rid_owner.get_or_null(singleton->focus);
562
uint32_t update_size = wd.update.size();
563
564
accesskit_node_id ac_focus = (accesskit_node_id)wd.root_id.get_id();
565
if (focus_ae && focus_ae->window_id == window_id) {
566
ac_focus = (accesskit_node_id)singleton->focus.get_id();
567
}
568
569
accesskit_tree_update *tree_update = (update_size > 0) ? accesskit_tree_update_with_capacity_and_focus(update_size, ac_focus) : accesskit_tree_update_with_focus(ac_focus);
570
for (const RID &rid : wd.update) {
571
AccessibilityElement *ae = singleton->rid_owner.get_or_null(rid);
572
if (ae && ae->node) {
573
for (const RID &child_rid : ae->children) {
574
accesskit_node_push_child(ae->node, (accesskit_node_id)child_rid.get_id());
575
}
576
accesskit_tree_update_push_node(tree_update, (accesskit_node_id)rid.get_id(), ae->node);
577
ae->node = nullptr;
578
}
579
}
580
wd.update.clear();
581
582
return tree_update;
583
}
584
585
void AccessibilityDriverAccessKit::accessibility_update_if_active(const Callable &p_callable) {
586
ERR_FAIL_COND(!p_callable.is_valid());
587
update_cb = p_callable;
588
for (KeyValue<DisplayServer::WindowID, WindowData> &window : windows) {
589
#ifdef WINDOWS_ENABLED
590
accesskit_windows_queued_events *events = accesskit_windows_subclassing_adapter_update_if_active(window.value.adapter, _accessibility_build_tree_update, (void *)(size_t)window.key);
591
if (events) {
592
accesskit_windows_queued_events_raise(events);
593
}
594
#endif
595
#ifdef MACOS_ENABLED
596
accesskit_macos_queued_events *events = accesskit_macos_subclassing_adapter_update_if_active(window.value.adapter, _accessibility_build_tree_update, (void *)(size_t)window.key);
597
if (events) {
598
accesskit_macos_queued_events_raise(events);
599
}
600
#endif
601
#ifdef LINUXBSD_ENABLED
602
accesskit_unix_adapter_update_if_active(window.value.adapter, _accessibility_build_tree_update, (void *)(size_t)window.key);
603
#endif
604
}
605
update_cb = Callable();
606
}
607
608
_FORCE_INLINE_ void AccessibilityDriverAccessKit::_ensure_node(const RID &p_id, AccessibilityElement *p_ae) {
609
if (unlikely(!p_ae->node)) {
610
WindowData *wd = windows.getptr(p_ae->window_id);
611
ERR_FAIL_NULL(wd);
612
613
wd->update.insert(p_id);
614
p_ae->node = accesskit_node_new(p_ae->role);
615
616
// Re-apply stored name if any, so nodes recreated by _ensure_node
617
// retain their label even if the caller doesn't re-set all properties.
618
if (!p_ae->name.is_empty() || !p_ae->name_extra_info.is_empty()) {
619
String full_name = p_ae->name + " " + p_ae->name_extra_info;
620
accesskit_node_set_label(p_ae->node, full_name.utf8().ptr());
621
}
622
}
623
}
624
625
void AccessibilityDriverAccessKit::accessibility_set_window_rect(DisplayServer::WindowID p_window_id, const Rect2 &p_rect_out, const Rect2 &p_rect_in) {
626
#ifdef LINUXBSD_ENABLED
627
const WindowData *wd = windows.getptr(p_window_id);
628
ERR_FAIL_NULL(wd);
629
630
accesskit_rect outer_bounds = { p_rect_out.position.x, p_rect_out.position.y, p_rect_out.position.x + p_rect_out.size.width, p_rect_out.position.y + p_rect_out.size.height };
631
accesskit_rect inner_bounds = { p_rect_in.position.x, p_rect_in.position.y, p_rect_in.position.x + p_rect_in.size.width, p_rect_in.position.y + p_rect_in.size.height };
632
accesskit_unix_adapter_set_root_window_bounds(wd->adapter, outer_bounds, inner_bounds);
633
#endif
634
}
635
636
void AccessibilityDriverAccessKit::accessibility_set_window_focused(DisplayServer::WindowID p_window_id, bool p_focused) {
637
const WindowData *wd = windows.getptr(p_window_id);
638
ERR_FAIL_NULL(wd);
639
640
#ifdef LINUXBSD_ENABLED
641
accesskit_unix_adapter_update_window_focus_state(wd->adapter, p_focused);
642
#endif
643
#ifdef MACOS_ENABLED
644
accesskit_macos_queued_events *events = accesskit_macos_subclassing_adapter_update_view_focus_state(wd->adapter, p_focused);
645
if (events != nullptr) {
646
accesskit_macos_queued_events_raise(events);
647
}
648
#endif
649
// Note: On Windows, the subclassing adapter takes care of this.
650
}
651
652
void AccessibilityDriverAccessKit::accessibility_update_set_role(const RID &p_id, DisplayServer::AccessibilityRole p_role) {
653
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
654
655
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
656
ERR_FAIL_NULL(ae);
657
if (ae->role == _accessibility_role(p_role)) {
658
return;
659
}
660
ae->role = _accessibility_role(p_role);
661
_ensure_node(p_id, ae);
662
663
accesskit_node_set_role(ae->node, ae->role);
664
}
665
666
void AccessibilityDriverAccessKit::accessibility_update_set_name(const RID &p_id, const String &p_name) {
667
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
668
669
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
670
ERR_FAIL_NULL(ae);
671
_ensure_node(p_id, ae);
672
673
ae->name = p_name;
674
String full_name = ae->name + " " + ae->name_extra_info;
675
if (!full_name.is_empty()) {
676
accesskit_node_set_label(ae->node, full_name.utf8().ptr());
677
} else {
678
accesskit_node_clear_label(ae->node);
679
}
680
}
681
682
void AccessibilityDriverAccessKit::accessibility_update_set_extra_info(const RID &p_id, const String &p_name_extra_info) {
683
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
684
685
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
686
ERR_FAIL_NULL(ae);
687
_ensure_node(p_id, ae);
688
689
ae->name_extra_info = p_name_extra_info;
690
String full_name = ae->name + " " + ae->name_extra_info;
691
if (!full_name.is_empty()) {
692
accesskit_node_set_label(ae->node, full_name.utf8().ptr());
693
} else {
694
accesskit_node_clear_label(ae->node);
695
}
696
}
697
698
void AccessibilityDriverAccessKit::accessibility_update_set_description(const RID &p_id, const String &p_description) {
699
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
700
701
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
702
ERR_FAIL_NULL(ae);
703
_ensure_node(p_id, ae);
704
705
if (!p_description.is_empty()) {
706
accesskit_node_set_description(ae->node, p_description.utf8().ptr());
707
} else {
708
accesskit_node_clear_description(ae->node);
709
}
710
}
711
712
void AccessibilityDriverAccessKit::accessibility_update_set_value(const RID &p_id, const String &p_value) {
713
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
714
715
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
716
ERR_FAIL_NULL(ae);
717
_ensure_node(p_id, ae);
718
719
if (!p_value.is_empty()) {
720
Vector<uint8_t> ch_length;
721
accesskit_node_set_value(ae->node, p_value.utf8(&ch_length).ptr());
722
accesskit_node_set_character_lengths(ae->node, ch_length.size(), ch_length.ptr());
723
} else {
724
accesskit_node_clear_value(ae->node);
725
accesskit_node_clear_character_lengths(ae->node);
726
}
727
}
728
729
void AccessibilityDriverAccessKit::accessibility_update_set_tooltip(const RID &p_id, const String &p_tooltip) {
730
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
731
732
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
733
ERR_FAIL_NULL(ae);
734
_ensure_node(p_id, ae);
735
736
if (!p_tooltip.is_empty()) {
737
accesskit_node_set_tooltip(ae->node, p_tooltip.utf8().ptr());
738
} else {
739
accesskit_node_clear_tooltip(ae->node);
740
}
741
}
742
743
void AccessibilityDriverAccessKit::accessibility_update_set_bounds(const RID &p_id, const Rect2 &p_rect) {
744
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
745
746
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
747
ERR_FAIL_NULL(ae);
748
_ensure_node(p_id, ae);
749
750
accesskit_rect rect;
751
rect.x0 = p_rect.position.x;
752
rect.y0 = p_rect.position.y;
753
rect.x1 = p_rect.position.x + p_rect.size.x;
754
rect.y1 = p_rect.position.y + p_rect.size.y;
755
accesskit_node_set_bounds(ae->node, rect);
756
}
757
758
void AccessibilityDriverAccessKit::accessibility_update_set_transform(const RID &p_id, const Transform2D &p_transform) {
759
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
760
761
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
762
ERR_FAIL_NULL(ae);
763
_ensure_node(p_id, ae);
764
765
accesskit_affine transform = { p_transform.columns[0][0], p_transform.columns[0][1], p_transform.columns[1][0], p_transform.columns[1][1], p_transform.columns[2][0], p_transform.columns[2][1] };
766
accesskit_node_set_transform(ae->node, transform);
767
}
768
769
void AccessibilityDriverAccessKit::accessibility_update_add_child(const RID &p_id, const RID &p_child_id) {
770
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
771
772
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
773
ERR_FAIL_NULL(ae);
774
AccessibilityElement *other_ae = rid_owner.get_or_null(p_child_id);
775
ERR_FAIL_NULL(other_ae);
776
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
777
_ensure_node(p_id, ae);
778
779
accesskit_node_push_child(ae->node, (accesskit_node_id)p_child_id.get_id());
780
}
781
782
void AccessibilityDriverAccessKit::accessibility_update_add_related_controls(const RID &p_id, const RID &p_related_id) {
783
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
784
785
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
786
ERR_FAIL_NULL(ae);
787
AccessibilityElement *other_ae = rid_owner.get_or_null(p_related_id);
788
ERR_FAIL_NULL(other_ae);
789
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
790
_ensure_node(p_id, ae);
791
792
accesskit_node_push_controlled(ae->node, (accesskit_node_id)p_related_id.get_id());
793
}
794
795
void AccessibilityDriverAccessKit::accessibility_update_add_related_details(const RID &p_id, const RID &p_related_id) {
796
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
797
798
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
799
ERR_FAIL_NULL(ae);
800
AccessibilityElement *other_ae = rid_owner.get_or_null(p_related_id);
801
ERR_FAIL_NULL(other_ae);
802
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
803
_ensure_node(p_id, ae);
804
805
accesskit_node_push_detail(ae->node, (accesskit_node_id)p_related_id.get_id());
806
}
807
808
void AccessibilityDriverAccessKit::accessibility_update_add_related_described_by(const RID &p_id, const RID &p_related_id) {
809
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
810
811
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
812
ERR_FAIL_NULL(ae);
813
AccessibilityElement *other_ae = rid_owner.get_or_null(p_related_id);
814
ERR_FAIL_NULL(other_ae);
815
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
816
_ensure_node(p_id, ae);
817
818
accesskit_node_push_described_by(ae->node, (accesskit_node_id)p_related_id.get_id());
819
}
820
821
void AccessibilityDriverAccessKit::accessibility_update_add_related_flow_to(const RID &p_id, const RID &p_related_id) {
822
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
823
824
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
825
ERR_FAIL_NULL(ae);
826
AccessibilityElement *other_ae = rid_owner.get_or_null(p_related_id);
827
ERR_FAIL_NULL(other_ae);
828
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
829
_ensure_node(p_id, ae);
830
831
accesskit_node_push_flow_to(ae->node, (accesskit_node_id)p_related_id.get_id());
832
}
833
834
void AccessibilityDriverAccessKit::accessibility_update_add_related_labeled_by(const RID &p_id, const RID &p_related_id) {
835
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
836
837
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
838
ERR_FAIL_NULL(ae);
839
AccessibilityElement *other_ae = rid_owner.get_or_null(p_related_id);
840
ERR_FAIL_NULL(other_ae);
841
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
842
_ensure_node(p_id, ae);
843
844
accesskit_node_push_labelled_by(ae->node, (accesskit_node_id)p_related_id.get_id());
845
}
846
847
void AccessibilityDriverAccessKit::accessibility_update_add_related_radio_group(const RID &p_id, const RID &p_related_id) {
848
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
849
850
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
851
ERR_FAIL_NULL(ae);
852
AccessibilityElement *other_ae = rid_owner.get_or_null(p_related_id);
853
ERR_FAIL_NULL(other_ae);
854
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
855
_ensure_node(p_id, ae);
856
857
accesskit_node_push_to_radio_group(ae->node, (accesskit_node_id)p_related_id.get_id());
858
}
859
860
void AccessibilityDriverAccessKit::accessibility_update_set_active_descendant(const RID &p_id, const RID &p_other_id) {
861
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
862
863
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
864
ERR_FAIL_NULL(ae);
865
AccessibilityElement *other_ae = rid_owner.get_or_null(p_other_id);
866
ERR_FAIL_NULL(other_ae);
867
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
868
_ensure_node(p_id, ae);
869
870
accesskit_node_set_active_descendant(ae->node, (accesskit_node_id)p_other_id.get_id());
871
}
872
873
void AccessibilityDriverAccessKit::accessibility_update_set_next_on_line(const RID &p_id, const RID &p_other_id) {
874
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
875
876
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
877
ERR_FAIL_NULL(ae);
878
AccessibilityElement *other_ae = rid_owner.get_or_null(p_other_id);
879
ERR_FAIL_NULL(other_ae);
880
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
881
_ensure_node(p_id, ae);
882
883
accesskit_node_set_next_on_line(ae->node, (accesskit_node_id)p_other_id.get_id());
884
}
885
886
void AccessibilityDriverAccessKit::accessibility_update_set_previous_on_line(const RID &p_id, const RID &p_other_id) {
887
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
888
889
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
890
ERR_FAIL_NULL(ae);
891
AccessibilityElement *other_ae = rid_owner.get_or_null(p_other_id);
892
ERR_FAIL_NULL(other_ae);
893
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
894
_ensure_node(p_id, ae);
895
896
accesskit_node_set_previous_on_line(ae->node, (accesskit_node_id)p_other_id.get_id());
897
}
898
899
void AccessibilityDriverAccessKit::accessibility_update_set_member_of(const RID &p_id, const RID &p_group_id) {
900
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
901
902
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
903
ERR_FAIL_NULL(ae);
904
AccessibilityElement *other_ae = rid_owner.get_or_null(p_group_id);
905
ERR_FAIL_NULL(other_ae);
906
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
907
_ensure_node(p_id, ae);
908
909
accesskit_node_set_member_of(ae->node, (accesskit_node_id)p_group_id.get_id());
910
}
911
912
void AccessibilityDriverAccessKit::accessibility_update_set_in_page_link_target(const RID &p_id, const RID &p_other_id) {
913
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
914
915
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
916
ERR_FAIL_NULL(ae);
917
AccessibilityElement *other_ae = rid_owner.get_or_null(p_other_id);
918
ERR_FAIL_NULL(other_ae);
919
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
920
_ensure_node(p_id, ae);
921
922
accesskit_node_set_in_page_link_target(ae->node, (accesskit_node_id)p_other_id.get_id());
923
}
924
925
void AccessibilityDriverAccessKit::accessibility_update_set_error_message(const RID &p_id, const RID &p_other_id) {
926
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
927
928
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
929
ERR_FAIL_NULL(ae);
930
AccessibilityElement *other_ae = rid_owner.get_or_null(p_other_id);
931
ERR_FAIL_NULL(other_ae);
932
ERR_FAIL_COND(other_ae->window_id != ae->window_id);
933
_ensure_node(p_id, ae);
934
935
accesskit_node_set_error_message(ae->node, (accesskit_node_id)p_other_id.get_id());
936
}
937
938
void AccessibilityDriverAccessKit::accessibility_update_set_live(const RID &p_id, DisplayServer::AccessibilityLiveMode p_live) {
939
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
940
941
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
942
ERR_FAIL_NULL(ae);
943
_ensure_node(p_id, ae);
944
945
switch (p_live) {
946
case DisplayServer::AccessibilityLiveMode::LIVE_OFF: {
947
accesskit_node_set_live(ae->node, ACCESSKIT_LIVE_OFF);
948
} break;
949
case DisplayServer::AccessibilityLiveMode::LIVE_POLITE: {
950
accesskit_node_set_live(ae->node, ACCESSKIT_LIVE_POLITE);
951
} break;
952
case DisplayServer::AccessibilityLiveMode::LIVE_ASSERTIVE: {
953
accesskit_node_set_live(ae->node, ACCESSKIT_LIVE_ASSERTIVE);
954
} break;
955
}
956
}
957
958
void AccessibilityDriverAccessKit::accessibility_update_add_action(const RID &p_id, DisplayServer::AccessibilityAction p_action, const Callable &p_callable) {
959
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
960
961
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
962
ERR_FAIL_NULL(ae);
963
_ensure_node(p_id, ae);
964
965
ae->actions[_accessibility_action(p_action)] = p_callable;
966
967
accesskit_node_add_action(ae->node, _accessibility_action(p_action));
968
}
969
970
void AccessibilityDriverAccessKit::accessibility_update_add_custom_action(const RID &p_id, int p_action_id, const String &p_action_description) {
971
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
972
973
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
974
ERR_FAIL_NULL(ae);
975
_ensure_node(p_id, ae);
976
977
if (!p_action_description.is_empty()) {
978
accesskit_custom_action *ca = accesskit_custom_action_new(p_action_id);
979
accesskit_custom_action_set_description(ca, p_action_description.utf8().ptr());
980
accesskit_node_push_custom_action(ae->node, ca);
981
} else {
982
String cs_name = vformat("Custom Action %d", p_action_id);
983
accesskit_custom_action *ca = accesskit_custom_action_new(p_action_id);
984
accesskit_custom_action_set_description(ca, cs_name.utf8().ptr());
985
accesskit_node_push_custom_action(ae->node, ca);
986
}
987
}
988
989
void AccessibilityDriverAccessKit::accessibility_update_set_table_row_count(const RID &p_id, int p_count) {
990
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
991
992
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
993
ERR_FAIL_NULL(ae);
994
_ensure_node(p_id, ae);
995
996
accesskit_node_set_row_count(ae->node, p_count);
997
}
998
999
void AccessibilityDriverAccessKit::accessibility_update_set_table_column_count(const RID &p_id, int p_count) {
1000
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1001
1002
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1003
ERR_FAIL_NULL(ae);
1004
_ensure_node(p_id, ae);
1005
1006
accesskit_node_set_column_count(ae->node, p_count);
1007
}
1008
1009
void AccessibilityDriverAccessKit::accessibility_update_set_table_row_index(const RID &p_id, int p_index) {
1010
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1011
1012
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1013
ERR_FAIL_NULL(ae);
1014
_ensure_node(p_id, ae);
1015
1016
accesskit_node_set_row_index(ae->node, p_index);
1017
}
1018
1019
void AccessibilityDriverAccessKit::accessibility_update_set_table_column_index(const RID &p_id, int p_index) {
1020
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1021
1022
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1023
ERR_FAIL_NULL(ae);
1024
_ensure_node(p_id, ae);
1025
1026
accesskit_node_set_column_index(ae->node, p_index);
1027
}
1028
1029
void AccessibilityDriverAccessKit::accessibility_update_set_table_cell_position(const RID &p_id, int p_row_index, int p_column_index) {
1030
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1031
1032
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1033
ERR_FAIL_NULL(ae);
1034
_ensure_node(p_id, ae);
1035
1036
accesskit_node_set_row_index(ae->node, p_row_index);
1037
accesskit_node_set_column_index(ae->node, p_column_index);
1038
}
1039
1040
void AccessibilityDriverAccessKit::accessibility_update_set_table_cell_span(const RID &p_id, int p_row_span, int p_column_span) {
1041
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1042
1043
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1044
ERR_FAIL_NULL(ae);
1045
_ensure_node(p_id, ae);
1046
1047
accesskit_node_set_row_span(ae->node, p_row_span);
1048
accesskit_node_set_column_span(ae->node, p_column_span);
1049
}
1050
1051
void AccessibilityDriverAccessKit::accessibility_update_set_list_item_count(const RID &p_id, int p_size) {
1052
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1053
1054
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1055
ERR_FAIL_NULL(ae);
1056
_ensure_node(p_id, ae);
1057
1058
accesskit_node_set_size_of_set(ae->node, p_size);
1059
}
1060
1061
void AccessibilityDriverAccessKit::accessibility_update_set_list_item_index(const RID &p_id, int p_index) {
1062
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1063
1064
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1065
ERR_FAIL_NULL(ae);
1066
_ensure_node(p_id, ae);
1067
1068
accesskit_node_set_position_in_set(ae->node, p_index);
1069
}
1070
1071
void AccessibilityDriverAccessKit::accessibility_update_set_list_item_level(const RID &p_id, int p_level) {
1072
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1073
1074
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1075
ERR_FAIL_NULL(ae);
1076
_ensure_node(p_id, ae);
1077
1078
accesskit_node_set_level(ae->node, p_level);
1079
}
1080
1081
void AccessibilityDriverAccessKit::accessibility_update_set_list_item_selected(const RID &p_id, bool p_selected) {
1082
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1083
1084
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1085
ERR_FAIL_NULL(ae);
1086
_ensure_node(p_id, ae);
1087
1088
accesskit_node_set_selected(ae->node, p_selected);
1089
}
1090
1091
void AccessibilityDriverAccessKit::accessibility_update_set_list_item_expanded(const RID &p_id, bool p_expanded) {
1092
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1093
1094
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1095
ERR_FAIL_NULL(ae);
1096
_ensure_node(p_id, ae);
1097
1098
accesskit_node_set_expanded(ae->node, p_expanded);
1099
}
1100
1101
void AccessibilityDriverAccessKit::accessibility_update_set_popup_type(const RID &p_id, DisplayServer::AccessibilityPopupType p_popup) {
1102
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1103
1104
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1105
ERR_FAIL_NULL(ae);
1106
_ensure_node(p_id, ae);
1107
1108
switch (p_popup) {
1109
case DisplayServer::AccessibilityPopupType::POPUP_MENU: {
1110
accesskit_node_set_has_popup(ae->node, ACCESSKIT_HAS_POPUP_MENU);
1111
} break;
1112
case DisplayServer::AccessibilityPopupType::POPUP_LIST: {
1113
accesskit_node_set_has_popup(ae->node, ACCESSKIT_HAS_POPUP_LISTBOX);
1114
} break;
1115
case DisplayServer::AccessibilityPopupType::POPUP_TREE: {
1116
accesskit_node_set_has_popup(ae->node, ACCESSKIT_HAS_POPUP_TREE);
1117
} break;
1118
case DisplayServer::AccessibilityPopupType::POPUP_DIALOG: {
1119
accesskit_node_set_has_popup(ae->node, ACCESSKIT_HAS_POPUP_DIALOG);
1120
} break;
1121
}
1122
}
1123
1124
void AccessibilityDriverAccessKit::accessibility_update_set_checked(const RID &p_id, bool p_checekd) {
1125
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1126
1127
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1128
ERR_FAIL_NULL(ae);
1129
_ensure_node(p_id, ae);
1130
1131
if (p_checekd) {
1132
accesskit_node_set_toggled(ae->node, ACCESSKIT_TOGGLED_TRUE);
1133
} else {
1134
accesskit_node_set_toggled(ae->node, ACCESSKIT_TOGGLED_FALSE);
1135
}
1136
}
1137
1138
void AccessibilityDriverAccessKit::accessibility_update_set_num_value(const RID &p_id, double p_position) {
1139
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1140
1141
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1142
ERR_FAIL_NULL(ae);
1143
_ensure_node(p_id, ae);
1144
1145
accesskit_node_set_numeric_value(ae->node, p_position);
1146
}
1147
1148
void AccessibilityDriverAccessKit::accessibility_update_set_num_range(const RID &p_id, double p_min, double p_max) {
1149
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1150
1151
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1152
ERR_FAIL_NULL(ae);
1153
_ensure_node(p_id, ae);
1154
1155
accesskit_node_set_min_numeric_value(ae->node, p_min);
1156
accesskit_node_set_max_numeric_value(ae->node, p_max);
1157
}
1158
1159
void AccessibilityDriverAccessKit::accessibility_update_set_num_step(const RID &p_id, double p_step) {
1160
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1161
1162
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1163
ERR_FAIL_NULL(ae);
1164
_ensure_node(p_id, ae);
1165
1166
accesskit_node_set_numeric_value_step(ae->node, p_step);
1167
}
1168
1169
void AccessibilityDriverAccessKit::accessibility_update_set_num_jump(const RID &p_id, double p_jump) {
1170
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1171
1172
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1173
ERR_FAIL_NULL(ae);
1174
_ensure_node(p_id, ae);
1175
1176
accesskit_node_set_numeric_value_jump(ae->node, p_jump);
1177
}
1178
1179
void AccessibilityDriverAccessKit::accessibility_update_set_scroll_x(const RID &p_id, double p_position) {
1180
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1181
1182
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1183
ERR_FAIL_NULL(ae);
1184
_ensure_node(p_id, ae);
1185
1186
accesskit_node_set_scroll_x(ae->node, p_position);
1187
}
1188
1189
void AccessibilityDriverAccessKit::accessibility_update_set_scroll_x_range(const RID &p_id, double p_min, double p_max) {
1190
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1191
1192
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1193
ERR_FAIL_NULL(ae);
1194
_ensure_node(p_id, ae);
1195
1196
accesskit_node_set_scroll_x_min(ae->node, p_min);
1197
accesskit_node_set_scroll_x_max(ae->node, p_max);
1198
}
1199
1200
void AccessibilityDriverAccessKit::accessibility_update_set_scroll_y(const RID &p_id, double p_position) {
1201
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1202
1203
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1204
ERR_FAIL_NULL(ae);
1205
_ensure_node(p_id, ae);
1206
1207
accesskit_node_set_scroll_y(ae->node, p_position);
1208
}
1209
1210
void AccessibilityDriverAccessKit::accessibility_update_set_scroll_y_range(const RID &p_id, double p_min, double p_max) {
1211
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1212
1213
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1214
ERR_FAIL_NULL(ae);
1215
_ensure_node(p_id, ae);
1216
1217
accesskit_node_set_scroll_y_min(ae->node, p_min);
1218
accesskit_node_set_scroll_y_max(ae->node, p_max);
1219
}
1220
1221
void AccessibilityDriverAccessKit::accessibility_update_set_text_decorations(const RID &p_id, bool p_underline, bool p_strikethrough, bool p_overline) {
1222
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1223
1224
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1225
ERR_FAIL_NULL(ae);
1226
_ensure_node(p_id, ae);
1227
1228
if (p_underline) {
1229
accesskit_node_set_underline(ae->node, ACCESSKIT_TEXT_DECORATION_SOLID);
1230
} else {
1231
accesskit_node_clear_underline(ae->node);
1232
}
1233
if (p_overline) {
1234
accesskit_node_set_overline(ae->node, ACCESSKIT_TEXT_DECORATION_SOLID);
1235
} else {
1236
accesskit_node_clear_overline(ae->node);
1237
}
1238
if (p_strikethrough) {
1239
accesskit_node_set_strikethrough(ae->node, ACCESSKIT_TEXT_DECORATION_SOLID);
1240
} else {
1241
accesskit_node_clear_strikethrough(ae->node);
1242
}
1243
}
1244
1245
void AccessibilityDriverAccessKit::accessibility_update_set_text_align(const RID &p_id, HorizontalAlignment p_align) {
1246
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1247
1248
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1249
ERR_FAIL_NULL(ae);
1250
_ensure_node(p_id, ae);
1251
1252
switch (p_align) {
1253
case HORIZONTAL_ALIGNMENT_LEFT: {
1254
accesskit_node_set_text_align(ae->node, ACCESSKIT_TEXT_ALIGN_LEFT);
1255
} break;
1256
case HORIZONTAL_ALIGNMENT_CENTER: {
1257
accesskit_node_set_text_align(ae->node, ACCESSKIT_TEXT_ALIGN_RIGHT);
1258
} break;
1259
case HORIZONTAL_ALIGNMENT_RIGHT: {
1260
accesskit_node_set_text_align(ae->node, ACCESSKIT_TEXT_ALIGN_CENTER);
1261
} break;
1262
case HORIZONTAL_ALIGNMENT_FILL: {
1263
accesskit_node_set_text_align(ae->node, ACCESSKIT_TEXT_ALIGN_JUSTIFY);
1264
} break;
1265
}
1266
}
1267
1268
void AccessibilityDriverAccessKit::accessibility_update_set_text_selection(const RID &p_id, const RID &p_text_start_id, int p_start_char, const RID &p_text_end_id, int p_end_char) {
1269
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1270
1271
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1272
ERR_FAIL_NULL(ae);
1273
AccessibilityElement *start_ae = rid_owner.get_or_null(p_text_start_id);
1274
ERR_FAIL_NULL(start_ae);
1275
ERR_FAIL_COND(start_ae->window_id != ae->window_id);
1276
AccessibilityElement *end_ae = rid_owner.get_or_null(p_text_end_id);
1277
ERR_FAIL_NULL(end_ae);
1278
ERR_FAIL_COND(end_ae->window_id != ae->window_id);
1279
1280
int start_pos = p_start_char;
1281
int end_pos = p_end_char;
1282
RID start_rid;
1283
RID end_rid;
1284
for (const RID &rid : start_ae->children) {
1285
const AccessibilityElement *child_ae = rid_owner.get_or_null(rid);
1286
if (child_ae && child_ae->role == ACCESSKIT_ROLE_TEXT_RUN) {
1287
if (p_start_char >= child_ae->run.x && p_start_char <= child_ae->run.y) {
1288
start_rid = rid;
1289
start_pos = p_start_char - child_ae->run.x;
1290
break;
1291
}
1292
}
1293
}
1294
for (const RID &rid : end_ae->children) {
1295
const AccessibilityElement *child_ae = rid_owner.get_or_null(rid);
1296
if (child_ae && child_ae->role == ACCESSKIT_ROLE_TEXT_RUN) {
1297
if (p_end_char >= child_ae->run.x && p_end_char <= child_ae->run.y) {
1298
end_rid = rid;
1299
end_pos = p_end_char - child_ae->run.x;
1300
break;
1301
}
1302
}
1303
}
1304
ERR_FAIL_COND(start_rid.is_null() && end_rid.is_null());
1305
_ensure_node(p_id, ae);
1306
1307
accesskit_text_selection sel;
1308
sel.anchor.node = (accesskit_node_id)start_rid.get_id();
1309
sel.anchor.character_index = start_pos;
1310
sel.focus.node = (accesskit_node_id)end_rid.get_id();
1311
sel.focus.character_index = end_pos;
1312
accesskit_node_set_text_selection(ae->node, sel);
1313
}
1314
1315
void AccessibilityDriverAccessKit::accessibility_update_set_flag(const RID &p_id, DisplayServer::AccessibilityFlags p_flag, bool p_value) {
1316
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1317
1318
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1319
ERR_FAIL_NULL(ae);
1320
_ensure_node(p_id, ae);
1321
1322
switch (p_flag) {
1323
case DisplayServer::AccessibilityFlags::FLAG_HIDDEN: {
1324
if (p_value) {
1325
accesskit_node_set_hidden(ae->node);
1326
} else {
1327
accesskit_node_clear_hidden(ae->node);
1328
}
1329
} break;
1330
case DisplayServer::AccessibilityFlags::FLAG_MULTISELECTABLE: {
1331
if (p_value) {
1332
accesskit_node_set_multiselectable(ae->node);
1333
} else {
1334
accesskit_node_clear_multiselectable(ae->node);
1335
}
1336
} break;
1337
case DisplayServer::AccessibilityFlags::FLAG_REQUIRED: {
1338
if (p_value) {
1339
accesskit_node_set_required(ae->node);
1340
} else {
1341
accesskit_node_clear_required(ae->node);
1342
}
1343
} break;
1344
case DisplayServer::AccessibilityFlags::FLAG_VISITED: {
1345
if (p_value) {
1346
accesskit_node_set_visited(ae->node);
1347
} else {
1348
accesskit_node_clear_visited(ae->node);
1349
}
1350
} break;
1351
case DisplayServer::AccessibilityFlags::FLAG_BUSY: {
1352
if (p_value) {
1353
accesskit_node_set_busy(ae->node);
1354
} else {
1355
accesskit_node_clear_busy(ae->node);
1356
}
1357
} break;
1358
case DisplayServer::AccessibilityFlags::FLAG_MODAL: {
1359
if (p_value) {
1360
accesskit_node_set_modal(ae->node);
1361
} else {
1362
accesskit_node_clear_modal(ae->node);
1363
}
1364
} break;
1365
case DisplayServer::AccessibilityFlags::FLAG_TOUCH_PASSTHROUGH: {
1366
if (p_value) {
1367
accesskit_node_set_touch_transparent(ae->node);
1368
} else {
1369
accesskit_node_clear_touch_transparent(ae->node);
1370
}
1371
} break;
1372
case DisplayServer::AccessibilityFlags::FLAG_READONLY: {
1373
if (p_value) {
1374
accesskit_node_set_read_only(ae->node);
1375
} else {
1376
accesskit_node_clear_read_only(ae->node);
1377
}
1378
} break;
1379
case DisplayServer::AccessibilityFlags::FLAG_DISABLED: {
1380
if (p_value) {
1381
accesskit_node_set_disabled(ae->node);
1382
} else {
1383
accesskit_node_clear_disabled(ae->node);
1384
}
1385
} break;
1386
case DisplayServer::AccessibilityFlags::FLAG_CLIPS_CHILDREN: {
1387
if (p_value) {
1388
accesskit_node_set_clips_children(ae->node);
1389
} else {
1390
accesskit_node_clear_clips_children(ae->node);
1391
}
1392
} break;
1393
}
1394
}
1395
1396
void AccessibilityDriverAccessKit::accessibility_update_set_classname(const RID &p_id, const String &p_classname) {
1397
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1398
1399
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1400
ERR_FAIL_NULL(ae);
1401
_ensure_node(p_id, ae);
1402
1403
if (!p_classname.is_empty()) {
1404
accesskit_node_set_class_name(ae->node, p_classname.utf8().ptr());
1405
} else {
1406
accesskit_node_clear_class_name(ae->node);
1407
}
1408
}
1409
1410
void AccessibilityDriverAccessKit::accessibility_update_set_placeholder(const RID &p_id, const String &p_placeholder) {
1411
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1412
1413
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1414
ERR_FAIL_NULL(ae);
1415
_ensure_node(p_id, ae);
1416
1417
if (!p_placeholder.is_empty()) {
1418
accesskit_node_set_placeholder(ae->node, p_placeholder.utf8().ptr());
1419
} else {
1420
accesskit_node_clear_placeholder(ae->node);
1421
}
1422
}
1423
1424
void AccessibilityDriverAccessKit::accessibility_update_set_language(const RID &p_id, const String &p_language) {
1425
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1426
1427
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1428
ERR_FAIL_NULL(ae);
1429
_ensure_node(p_id, ae);
1430
1431
accesskit_node_set_language(ae->node, p_language.utf8().ptr());
1432
}
1433
1434
void AccessibilityDriverAccessKit::accessibility_update_set_text_orientation(const RID &p_id, bool p_vertical) {
1435
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1436
1437
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1438
ERR_FAIL_NULL(ae);
1439
_ensure_node(p_id, ae);
1440
1441
if (p_vertical) {
1442
accesskit_node_set_text_direction(ae->node, ACCESSKIT_TEXT_DIRECTION_TOP_TO_BOTTOM);
1443
} else {
1444
accesskit_node_set_text_direction(ae->node, ACCESSKIT_TEXT_DIRECTION_LEFT_TO_RIGHT);
1445
}
1446
}
1447
1448
void AccessibilityDriverAccessKit::accessibility_update_set_list_orientation(const RID &p_id, bool p_vertical) {
1449
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1450
1451
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1452
ERR_FAIL_NULL(ae);
1453
_ensure_node(p_id, ae);
1454
1455
if (p_vertical) {
1456
accesskit_node_set_orientation(ae->node, ACCESSKIT_ORIENTATION_VERTICAL);
1457
} else {
1458
accesskit_node_set_orientation(ae->node, ACCESSKIT_ORIENTATION_HORIZONTAL);
1459
}
1460
}
1461
1462
void AccessibilityDriverAccessKit::accessibility_update_set_shortcut(const RID &p_id, const String &p_shortcut) {
1463
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1464
1465
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1466
ERR_FAIL_NULL(ae);
1467
_ensure_node(p_id, ae);
1468
1469
if (!p_shortcut.is_empty()) {
1470
accesskit_node_set_keyboard_shortcut(ae->node, p_shortcut.utf8().ptr());
1471
} else {
1472
accesskit_node_clear_keyboard_shortcut(ae->node);
1473
}
1474
}
1475
1476
void AccessibilityDriverAccessKit::accessibility_update_set_url(const RID &p_id, const String &p_url) {
1477
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1478
1479
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1480
ERR_FAIL_NULL(ae);
1481
_ensure_node(p_id, ae);
1482
1483
if (!p_url.is_empty()) {
1484
accesskit_node_set_url(ae->node, p_url.utf8().ptr());
1485
} else {
1486
accesskit_node_clear_url(ae->node);
1487
}
1488
}
1489
1490
void AccessibilityDriverAccessKit::accessibility_update_set_role_description(const RID &p_id, const String &p_description) {
1491
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1492
1493
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1494
ERR_FAIL_NULL(ae);
1495
_ensure_node(p_id, ae);
1496
1497
if (!p_description.is_empty()) {
1498
accesskit_node_set_role_description(ae->node, p_description.utf8().ptr());
1499
} else {
1500
accesskit_node_clear_role_description(ae->node);
1501
}
1502
}
1503
1504
void AccessibilityDriverAccessKit::accessibility_update_set_state_description(const RID &p_id, const String &p_description) {
1505
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1506
1507
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1508
ERR_FAIL_NULL(ae);
1509
_ensure_node(p_id, ae);
1510
1511
if (!p_description.is_empty()) {
1512
accesskit_node_set_state_description(ae->node, p_description.utf8().ptr());
1513
} else {
1514
accesskit_node_clear_state_description(ae->node);
1515
}
1516
}
1517
1518
void AccessibilityDriverAccessKit::accessibility_update_set_color_value(const RID &p_id, const Color &p_color) {
1519
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1520
1521
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1522
ERR_FAIL_NULL(ae);
1523
_ensure_node(p_id, ae);
1524
1525
accesskit_node_set_color_value(ae->node, p_color.to_rgba32());
1526
}
1527
1528
void AccessibilityDriverAccessKit::accessibility_update_set_background_color(const RID &p_id, const Color &p_color) {
1529
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1530
1531
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1532
ERR_FAIL_NULL(ae);
1533
_ensure_node(p_id, ae);
1534
1535
accesskit_node_set_background_color(ae->node, p_color.to_rgba32());
1536
}
1537
1538
void AccessibilityDriverAccessKit::accessibility_update_set_foreground_color(const RID &p_id, const Color &p_color) {
1539
ERR_FAIL_COND_MSG(!in_accessibility_update, "Accessibility updates are only allowed inside the NOTIFICATION_ACCESSIBILITY_UPDATE notification.");
1540
1541
AccessibilityElement *ae = rid_owner.get_or_null(p_id);
1542
ERR_FAIL_NULL(ae);
1543
_ensure_node(p_id, ae);
1544
1545
accesskit_node_set_foreground_color(ae->node, p_color.to_rgba32());
1546
}
1547
1548
Error AccessibilityDriverAccessKit::init() {
1549
#ifdef ACCESSKIT_DYNAMIC
1550
#ifdef DEBUG_ENABLED
1551
int dylibloader_verbose = 1;
1552
#else
1553
int dylibloader_verbose = 0;
1554
#endif
1555
void *library_handle = nullptr;
1556
String path;
1557
String arch = Engine::get_singleton()->get_architecture_name();
1558
#ifdef LINUXBSD_ENABLED
1559
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("libaccesskit." + arch + ".so");
1560
if (!FileAccess::exists(path)) {
1561
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("../lib").path_join("libaccesskit." + arch + ".so");
1562
}
1563
if (!FileAccess::exists(path)) {
1564
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("libaccesskit.so");
1565
}
1566
if (!FileAccess::exists(path)) {
1567
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("../lib").path_join("libaccesskit.so");
1568
}
1569
if (!FileAccess::exists(path)) {
1570
return ERR_CANT_CREATE;
1571
}
1572
#endif
1573
#ifdef MACOS_ENABLED
1574
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("libaccesskit." + arch + ".dylib");
1575
if (!FileAccess::exists(path)) {
1576
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("../Frameworks").path_join("libaccesskit." + arch + ".dylib");
1577
}
1578
if (!FileAccess::exists(path)) {
1579
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("libaccesskit.dylib");
1580
}
1581
if (!FileAccess::exists(path)) {
1582
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("../Frameworks").path_join("libaccesskit.dylib");
1583
}
1584
if (!FileAccess::exists(path)) {
1585
return ERR_CANT_CREATE;
1586
}
1587
#endif
1588
#ifdef WINDOWS_ENABLED
1589
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("accesskit." + arch + ".dll");
1590
if (!FileAccess::exists(path)) {
1591
path = OS::get_singleton()->get_executable_path().get_base_dir().path_join("accesskit.dll");
1592
}
1593
if (!FileAccess::exists(path)) {
1594
return ERR_CANT_CREATE;
1595
}
1596
#endif
1597
1598
Error err = OS::get_singleton()->open_dynamic_library(path, library_handle);
1599
if (err == OK && initialize_libaccesskit(dylibloader_verbose, library_handle) == 0) {
1600
print_verbose("AccessKit loaded.");
1601
} else {
1602
return ERR_CANT_CREATE;
1603
}
1604
#endif
1605
#ifdef MACOS_ENABLED
1606
//accesskit_macos_add_focus_forwarder_to_window_class("GodotWindow");
1607
#endif
1608
return OK;
1609
}
1610
1611
AccessibilityDriverAccessKit::AccessibilityDriverAccessKit() {
1612
singleton = this;
1613
1614
role_map[DisplayServer::AccessibilityRole::ROLE_UNKNOWN] = ACCESSKIT_ROLE_UNKNOWN;
1615
role_map[DisplayServer::AccessibilityRole::ROLE_DEFAULT_BUTTON] = ACCESSKIT_ROLE_DEFAULT_BUTTON;
1616
role_map[DisplayServer::AccessibilityRole::ROLE_AUDIO] = ACCESSKIT_ROLE_AUDIO;
1617
role_map[DisplayServer::AccessibilityRole::ROLE_VIDEO] = ACCESSKIT_ROLE_VIDEO;
1618
role_map[DisplayServer::AccessibilityRole::ROLE_STATIC_TEXT] = ACCESSKIT_ROLE_LABEL;
1619
role_map[DisplayServer::AccessibilityRole::ROLE_CONTAINER] = ACCESSKIT_ROLE_GENERIC_CONTAINER;
1620
role_map[DisplayServer::AccessibilityRole::ROLE_PANEL] = ACCESSKIT_ROLE_PANE;
1621
role_map[DisplayServer::AccessibilityRole::ROLE_BUTTON] = ACCESSKIT_ROLE_BUTTON;
1622
role_map[DisplayServer::AccessibilityRole::ROLE_LINK] = ACCESSKIT_ROLE_LINK;
1623
role_map[DisplayServer::AccessibilityRole::ROLE_CHECK_BOX] = ACCESSKIT_ROLE_CHECK_BOX;
1624
role_map[DisplayServer::AccessibilityRole::ROLE_RADIO_BUTTON] = ACCESSKIT_ROLE_RADIO_BUTTON;
1625
role_map[DisplayServer::AccessibilityRole::ROLE_CHECK_BUTTON] = ACCESSKIT_ROLE_SWITCH;
1626
role_map[DisplayServer::AccessibilityRole::ROLE_SCROLL_BAR] = ACCESSKIT_ROLE_SCROLL_BAR;
1627
role_map[DisplayServer::AccessibilityRole::ROLE_SCROLL_VIEW] = ACCESSKIT_ROLE_SCROLL_VIEW;
1628
role_map[DisplayServer::AccessibilityRole::ROLE_SPLITTER] = ACCESSKIT_ROLE_SPLITTER;
1629
role_map[DisplayServer::AccessibilityRole::ROLE_SLIDER] = ACCESSKIT_ROLE_SLIDER;
1630
role_map[DisplayServer::AccessibilityRole::ROLE_SPIN_BUTTON] = ACCESSKIT_ROLE_SPIN_BUTTON;
1631
role_map[DisplayServer::AccessibilityRole::ROLE_PROGRESS_INDICATOR] = ACCESSKIT_ROLE_PROGRESS_INDICATOR;
1632
role_map[DisplayServer::AccessibilityRole::ROLE_TEXT_FIELD] = ACCESSKIT_ROLE_TEXT_INPUT;
1633
role_map[DisplayServer::AccessibilityRole::ROLE_MULTILINE_TEXT_FIELD] = ACCESSKIT_ROLE_MULTILINE_TEXT_INPUT;
1634
role_map[DisplayServer::AccessibilityRole::ROLE_COLOR_PICKER] = ACCESSKIT_ROLE_COLOR_WELL;
1635
role_map[DisplayServer::AccessibilityRole::ROLE_TABLE] = ACCESSKIT_ROLE_TABLE;
1636
role_map[DisplayServer::AccessibilityRole::ROLE_CELL] = ACCESSKIT_ROLE_CELL;
1637
role_map[DisplayServer::AccessibilityRole::ROLE_ROW] = ACCESSKIT_ROLE_ROW;
1638
role_map[DisplayServer::AccessibilityRole::ROLE_ROW_GROUP] = ACCESSKIT_ROLE_ROW_GROUP;
1639
role_map[DisplayServer::AccessibilityRole::ROLE_ROW_HEADER] = ACCESSKIT_ROLE_ROW_HEADER;
1640
role_map[DisplayServer::AccessibilityRole::ROLE_COLUMN_HEADER] = ACCESSKIT_ROLE_COLUMN_HEADER;
1641
role_map[DisplayServer::AccessibilityRole::ROLE_TREE] = ACCESSKIT_ROLE_TREE;
1642
role_map[DisplayServer::AccessibilityRole::ROLE_TREE_ITEM] = ACCESSKIT_ROLE_TREE_ITEM;
1643
role_map[DisplayServer::AccessibilityRole::ROLE_LIST] = ACCESSKIT_ROLE_LIST;
1644
role_map[DisplayServer::AccessibilityRole::ROLE_LIST_ITEM] = ACCESSKIT_ROLE_LIST_ITEM;
1645
role_map[DisplayServer::AccessibilityRole::ROLE_LIST_BOX] = ACCESSKIT_ROLE_LIST_BOX;
1646
role_map[DisplayServer::AccessibilityRole::ROLE_LIST_BOX_OPTION] = ACCESSKIT_ROLE_LIST_BOX_OPTION;
1647
role_map[DisplayServer::AccessibilityRole::ROLE_TAB_BAR] = ACCESSKIT_ROLE_TAB_LIST;
1648
role_map[DisplayServer::AccessibilityRole::ROLE_TAB] = ACCESSKIT_ROLE_TAB;
1649
role_map[DisplayServer::AccessibilityRole::ROLE_TAB_PANEL] = ACCESSKIT_ROLE_TAB_PANEL;
1650
role_map[DisplayServer::AccessibilityRole::ROLE_MENU_BAR] = ACCESSKIT_ROLE_MENU_BAR;
1651
role_map[DisplayServer::AccessibilityRole::ROLE_MENU] = ACCESSKIT_ROLE_MENU;
1652
role_map[DisplayServer::AccessibilityRole::ROLE_MENU_ITEM] = ACCESSKIT_ROLE_MENU_ITEM;
1653
role_map[DisplayServer::AccessibilityRole::ROLE_MENU_ITEM_CHECK_BOX] = ACCESSKIT_ROLE_MENU_ITEM_CHECK_BOX;
1654
role_map[DisplayServer::AccessibilityRole::ROLE_MENU_ITEM_RADIO] = ACCESSKIT_ROLE_MENU_ITEM_RADIO;
1655
role_map[DisplayServer::AccessibilityRole::ROLE_IMAGE] = ACCESSKIT_ROLE_IMAGE;
1656
role_map[DisplayServer::AccessibilityRole::ROLE_WINDOW] = ACCESSKIT_ROLE_WINDOW;
1657
role_map[DisplayServer::AccessibilityRole::ROLE_TITLE_BAR] = ACCESSKIT_ROLE_TITLE_BAR;
1658
role_map[DisplayServer::AccessibilityRole::ROLE_DIALOG] = ACCESSKIT_ROLE_DIALOG;
1659
role_map[DisplayServer::AccessibilityRole::ROLE_TOOLTIP] = ACCESSKIT_ROLE_TOOLTIP;
1660
role_map[DisplayServer::AccessibilityRole::ROLE_REGION] = ACCESSKIT_ROLE_REGION;
1661
1662
action_map[DisplayServer::AccessibilityAction::ACTION_CLICK] = ACCESSKIT_ACTION_CLICK;
1663
action_map[DisplayServer::AccessibilityAction::ACTION_FOCUS] = ACCESSKIT_ACTION_FOCUS;
1664
action_map[DisplayServer::AccessibilityAction::ACTION_BLUR] = ACCESSKIT_ACTION_BLUR;
1665
action_map[DisplayServer::AccessibilityAction::ACTION_COLLAPSE] = ACCESSKIT_ACTION_COLLAPSE;
1666
action_map[DisplayServer::AccessibilityAction::ACTION_EXPAND] = ACCESSKIT_ACTION_EXPAND;
1667
action_map[DisplayServer::AccessibilityAction::ACTION_DECREMENT] = ACCESSKIT_ACTION_DECREMENT;
1668
action_map[DisplayServer::AccessibilityAction::ACTION_INCREMENT] = ACCESSKIT_ACTION_INCREMENT;
1669
action_map[DisplayServer::AccessibilityAction::ACTION_HIDE_TOOLTIP] = ACCESSKIT_ACTION_HIDE_TOOLTIP;
1670
action_map[DisplayServer::AccessibilityAction::ACTION_SHOW_TOOLTIP] = ACCESSKIT_ACTION_SHOW_TOOLTIP;
1671
//action_map[DisplayServer::AccessibilityAction::ACTION_INVALIDATE_TREE] = ACCESSKIT_ACTION_INVALIDATE_TREE;
1672
//action_map[DisplayServer::AccessibilityAction::ACTION_LOAD_INLINE_TEXT_BOXES] = ACCESSKIT_ACTION_LOAD_INLINE_TEXT_BOXES;
1673
action_map[DisplayServer::AccessibilityAction::ACTION_SET_TEXT_SELECTION] = ACCESSKIT_ACTION_SET_TEXT_SELECTION;
1674
action_map[DisplayServer::AccessibilityAction::ACTION_REPLACE_SELECTED_TEXT] = ACCESSKIT_ACTION_REPLACE_SELECTED_TEXT;
1675
action_map[DisplayServer::AccessibilityAction::ACTION_SCROLL_BACKWARD] = ACCESSKIT_ACTION_SCROLL_UP;
1676
action_map[DisplayServer::AccessibilityAction::ACTION_SCROLL_DOWN] = ACCESSKIT_ACTION_SCROLL_DOWN;
1677
action_map[DisplayServer::AccessibilityAction::ACTION_SCROLL_FORWARD] = ACCESSKIT_ACTION_SCROLL_DOWN;
1678
action_map[DisplayServer::AccessibilityAction::ACTION_SCROLL_LEFT] = ACCESSKIT_ACTION_SCROLL_LEFT;
1679
action_map[DisplayServer::AccessibilityAction::ACTION_SCROLL_RIGHT] = ACCESSKIT_ACTION_SCROLL_RIGHT;
1680
action_map[DisplayServer::AccessibilityAction::ACTION_SCROLL_UP] = ACCESSKIT_ACTION_SCROLL_UP;
1681
action_map[DisplayServer::AccessibilityAction::ACTION_SCROLL_INTO_VIEW] = ACCESSKIT_ACTION_SCROLL_INTO_VIEW;
1682
action_map[DisplayServer::AccessibilityAction::ACTION_SCROLL_TO_POINT] = ACCESSKIT_ACTION_SCROLL_TO_POINT;
1683
action_map[DisplayServer::AccessibilityAction::ACTION_SET_SCROLL_OFFSET] = ACCESSKIT_ACTION_SET_SCROLL_OFFSET;
1684
//action_map[DisplayServer::AccessibilityAction::ACTION_SET_SEQUENTIAL_FOCUS_NAVIGATION_STARTING_POINT] = ACCESSKIT_ACTION_SET_SEQUENTIAL_FOCUS_NAVIGATION_STARTING_POINT;
1685
action_map[DisplayServer::AccessibilityAction::ACTION_SET_VALUE] = ACCESSKIT_ACTION_SET_VALUE;
1686
action_map[DisplayServer::AccessibilityAction::ACTION_SHOW_CONTEXT_MENU] = ACCESSKIT_ACTION_SHOW_CONTEXT_MENU;
1687
action_map[DisplayServer::AccessibilityAction::ACTION_CUSTOM] = ACCESSKIT_ACTION_CUSTOM_ACTION;
1688
}
1689
1690
AccessibilityDriverAccessKit::~AccessibilityDriverAccessKit() {
1691
singleton = nullptr;
1692
}
1693
1694
#endif // ACCESSKIT_ENABLED
1695
1696