[Accessibility] Handle adapter activation/deactivation.

(cherry picked from commit 876dcc8a5d2b1ca0cffcc84ea8cfd06d69fadde4)
This commit is contained in:
Pāvels Nadtočajevs
2026-01-29 09:02:10 +02:00
committed by Thaddeus Crews
parent 4caac57d2a
commit effdbbfafd
7 changed files with 140 additions and 4 deletions
@@ -73,6 +73,7 @@ bool AccessibilityDriverAccessKit::window_create(DisplayServer::WindowID p_windo
#ifdef LINUXBSD_ENABLED
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);
#endif
print_verbose(vformat("Accessibility: window %d adapter created.", p_window_id));
if (wd.adapter == nullptr) {
memdelete(ae);
@@ -89,6 +90,8 @@ void AccessibilityDriverAccessKit::window_destroy(DisplayServer::WindowID p_wind
WindowData *wd = windows.getptr(p_window_id);
ERR_FAIL_NULL(wd);
print_verbose(vformat("Accessibility: window %d adapter destroyed.", p_window_id));
#ifdef WINDOWS_ENABLED
accesskit_windows_subclassing_adapter_free(wd->adapter);
#endif
@@ -104,7 +107,22 @@ void AccessibilityDriverAccessKit::window_destroy(DisplayServer::WindowID p_wind
}
void AccessibilityDriverAccessKit::_accessibility_deactivation_callback(void *p_user_data) {
// NOP
DisplayServer::WindowID window_id = (DisplayServer::WindowID)(size_t)p_user_data;
WindowData *wd = singleton->windows.getptr(window_id);
ERR_FAIL_NULL(wd);
print_verbose(vformat("Accessibility: window %d adapter deactivated.", window_id));
if (singleton->focus.is_valid()) {
AccessibilityElement *ae = singleton->rid_owner.get_or_null(singleton->focus);
if (ae && ae->window_id == window_id) {
singleton->focus = RID();
}
}
if (wd->deactivate.is_valid()) {
wd->deactivate.call_deferred(); // Should be called on main thread only.
}
wd->update.clear();
}
void AccessibilityDriverAccessKit::_accessibility_action_callback(struct accesskit_action_request *p_request, void *p_user_data) {
@@ -215,9 +233,58 @@ accesskit_tree_update *AccessibilityDriverAccessKit::_accessibility_initial_tree
accesskit_tree_update_set_tree(tree_update, accesskit_tree_new(win_id));
accesskit_tree_update_push_node(tree_update, win_id, win_node);
print_verbose(vformat("Accessibility: window %d adapter activated.", window_id));
if (wd->activate.is_valid()) {
wd->activate.call_deferred(); // Should be called on main thread only.
}
return tree_update;
}
void AccessibilityDriverAccessKit::accessibility_set_window_callbacks(DisplayServer::WindowID p_window_id, const Callable &p_activate_callable, const Callable &p_deativate_callable) {
WindowData *wd = singleton->windows.getptr(p_window_id);
ERR_FAIL_NULL(wd);
wd->activate = p_activate_callable;
wd->deactivate = p_deativate_callable;
}
void AccessibilityDriverAccessKit::accessibility_window_activation_completed(DisplayServer::WindowID p_window_id) {
WindowData *wd = singleton->windows.getptr(p_window_id);
if (!wd) {
return;
}
print_verbose(vformat("Accessibility: window %d adapter initial update completed.", p_window_id));
wd->initial_update_completed = true;
}
void AccessibilityDriverAccessKit::accessibility_window_deactivation_completed(DisplayServer::WindowID p_window_id) {
WindowData *wd = singleton->windows.getptr(p_window_id);
if (!wd) {
return;
}
print_verbose(vformat("Accessibility: window %d adapter deactivation completed.", p_window_id));
#ifdef DEV_ENABLED
LocalVector<RID> to_delete;
for (const RID &rid : rid_owner.get_owned_list()) {
AccessibilityElement *ae = rid_owner.get_or_null(rid);
if (rid != wd->root_id && ae && ae->window_id == p_window_id) {
ERR_PRINT(vformat("Accessibility/BUG: Accessibility element %d was not deleted on window %d adapter deactivation.", rid.get_id(), p_window_id));
to_delete.push_back(rid);
}
}
for (const RID &rid : to_delete) {
_free_recursive(wd, rid);
}
#endif
wd->initial_update_completed = false;
}
RID AccessibilityDriverAccessKit::accessibility_create_element(DisplayServer::WindowID p_window_id, DisplayServer::AccessibilityRole p_role) {
AccessibilityElement *ae = memnew(AccessibilityElement);
ae->role = _accessibility_role(p_role);
@@ -81,7 +81,10 @@ class AccessibilityDriverAccessKit : public AccessibilityDriver {
#endif
RID root_id;
bool initial_update_completed = false;
HashSet<RID> update;
Callable activate;
Callable deactivate;
};
RID focus;
@@ -127,6 +130,9 @@ public:
void accessibility_set_window_rect(DisplayServer::WindowID p_window_id, const Rect2 &p_rect_out, const Rect2 &p_rect_in) override;
void accessibility_set_window_focused(DisplayServer::WindowID p_window_id, bool p_focused) override;
void accessibility_set_window_callbacks(DisplayServer::WindowID p_window_id, const Callable &p_activate_callable, const Callable &p_deativate_callable) override;
void accessibility_window_activation_completed(DisplayServer::WindowID p_window_id) override;
void accessibility_window_deactivation_completed(DisplayServer::WindowID p_window_id) override;
void accessibility_update_set_role(const RID &p_id, DisplayServer::AccessibilityRole p_role) override;
void accessibility_update_set_name(const RID &p_id, const String &p_name) override;
+14
View File
@@ -63,8 +63,22 @@
width[1] = 0;
height[1] = 0;
#ifdef APPLE_EMBEDDED_ENABLED
[p_device lockForConfiguration:&error];
[p_device setFocusMode:AVCaptureFocusModeLocked];
[p_device setExposureMode:AVCaptureExposureModeLocked];
[p_device setWhiteBalanceMode:AVCaptureWhiteBalanceModeLocked];
[p_device unlockForConfiguration];
#endif // APPLE_EMBEDDED_ENABLED
[self beginConfiguration];
#ifdef APPLE_EMBEDDED_ENABLED
self.sessionPreset = AVCaptureSessionPreset1280x720;
#endif // APPLE_EMBEDDED_ENABLED
input = [AVCaptureDeviceInput deviceInputWithDevice:p_device error:&error];
if (!input) {
print_line("Couldn't get input device for camera");
+24 -2
View File
@@ -672,6 +672,7 @@ void Window::_make_window() {
DisplayServer::get_singleton()->window_set_mouse_passthrough(mpath, window_id);
DisplayServer::get_singleton()->window_set_title(displayed_title, window_id);
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
DisplayServer::get_singleton()->accessibility_set_window_callbacks(window_id, callable_mp(this, &Window::_accessibility_activate), callable_mp(this, &Window::_accessibility_deactivate));
_update_window_size();
@@ -895,6 +896,16 @@ void Window::hide() {
set_visible(false);
}
void Window::_accessibility_activate() {
_accessibility_notify_enter(this);
DisplayServer::get_singleton()->accessibility_window_activation_completed(get_window_id());
}
void Window::_accessibility_deactivate() {
_accessibility_notify_exit(this);
DisplayServer::get_singleton()->accessibility_window_deactivation_completed(get_window_id());
}
void Window::_accessibility_notify_enter(Node *p_node) {
p_node->queue_accessibility_update();
@@ -977,10 +988,12 @@ void Window::set_visible(bool p_visible) {
if (get_tree() && get_tree()->is_accessibility_supported()) {
get_tree()->_accessibility_force_update();
_accessibility_notify_enter(this);
DisplayServer::get_singleton()->accessibility_window_activation_completed(get_window_id());
}
} else {
if (get_tree() && get_tree()->is_accessibility_supported()) {
_accessibility_notify_exit(this);
DisplayServer::get_singleton()->accessibility_window_deactivation_completed(get_window_id());
}
focused = false;
if (focused_window == this) {
@@ -1424,8 +1437,14 @@ void Window::_notification(int p_what) {
ERR_MAIN_THREAD_GUARD;
switch (p_what) {
case NOTIFICATION_ACCESSIBILITY_INVALIDATE: {
accessibility_title_element = RID();
accessibility_announcement_element = RID();
if (accessibility_title_element.is_valid()) {
DisplayServer::get_singleton()->accessibility_free_element(accessibility_title_element);
accessibility_title_element = RID();
}
if (accessibility_announcement_element.is_valid()) {
DisplayServer::get_singleton()->accessibility_free_element(accessibility_announcement_element);
accessibility_announcement_element = RID();
}
} break;
case NOTIFICATION_ACCESSIBILITY_UPDATE: {
@@ -1545,6 +1564,7 @@ void Window::_notification(int p_what) {
window_id = DisplayServer::MAIN_WINDOW_ID;
focused_window = this;
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
DisplayServer::get_singleton()->accessibility_set_window_callbacks(window_id, callable_mp(this, &Window::_accessibility_activate), callable_mp(this, &Window::_accessibility_deactivate));
_update_from_window();
// Since this window already exists (created on start), we must update pos and size from it.
{
@@ -1578,6 +1598,7 @@ void Window::_notification(int p_what) {
if (window_id != DisplayServer::MAIN_WINDOW_ID && get_tree() && get_tree()->is_accessibility_supported()) {
get_tree()->_accessibility_force_update();
_accessibility_notify_enter(this);
DisplayServer::get_singleton()->accessibility_window_activation_completed(get_window_id());
}
notification(NOTIFICATION_VISIBILITY_CHANGED);
emit_signal(SceneStringName(visibility_changed));
@@ -1632,6 +1653,7 @@ void Window::_notification(int p_what) {
if (visible && window_id != DisplayServer::MAIN_WINDOW_ID) {
if (get_tree() && get_tree()->is_accessibility_supported()) {
_accessibility_notify_exit(this);
DisplayServer::get_singleton()->accessibility_window_deactivation_completed(get_window_id());
if (get_parent()) {
get_parent()->queue_accessibility_update();
}
+3
View File
@@ -167,6 +167,9 @@ private:
void _accessibility_notify_enter(Node *p_node);
void _accessibility_notify_exit(Node *p_node);
void _accessibility_activate();
void _accessibility_deactivate();
bool _try_parent_dialog(Node *p_from_node);
Size2i max_size_used;
+18
View File
@@ -716,6 +716,24 @@ void DisplayServer::accessibility_set_window_focused(DisplayServer::WindowID p_w
}
}
void DisplayServer::accessibility_set_window_callbacks(DisplayServer::WindowID p_window_id, const Callable &p_activate_callable, const Callable &p_deativate_callable) {
if (accessibility_driver) {
accessibility_driver->accessibility_set_window_callbacks(p_window_id, p_activate_callable, p_deativate_callable);
}
}
void DisplayServer::accessibility_window_activation_completed(DisplayServer::WindowID p_window_id) {
if (accessibility_driver) {
accessibility_driver->accessibility_window_activation_completed(p_window_id);
}
}
void DisplayServer::accessibility_window_deactivation_completed(DisplayServer::WindowID p_window_id) {
if (accessibility_driver) {
accessibility_driver->accessibility_window_deactivation_completed(p_window_id);
}
}
void DisplayServer::accessibility_update_set_role(const RID &p_id, DisplayServer::AccessibilityRole p_role) {
if (accessibility_driver) {
accessibility_driver->accessibility_update_set_role(p_id, p_role);
+7 -1
View File
@@ -446,7 +446,7 @@ public:
virtual WindowID get_window_at_screen_position(const Point2i &p_position) const = 0;
virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) = 0;
virtual void window_attach_instance_id(ObjectID p_instance, WindowID p_window = MAIN_WINDOW_ID) = 0; // Note: internal method used by Window, do not expose.
virtual ObjectID window_get_attached_instance_id(WindowID p_window = MAIN_WINDOW_ID) const = 0;
virtual void window_set_rect_changed_callback(const Callable &p_callable, WindowID p_window = MAIN_WINDOW_ID) = 0;
@@ -698,6 +698,9 @@ public:
virtual void accessibility_set_window_rect(DisplayServer::WindowID p_window_id, const Rect2 &p_rect_out, const Rect2 &p_rect_in);
virtual void accessibility_set_window_focused(DisplayServer::WindowID p_window_id, bool p_focused);
virtual void accessibility_set_window_callbacks(DisplayServer::WindowID p_window_id, const Callable &p_activate_callable, const Callable &p_deativate_callable); // Note: internal method used by Window, do not expose.
virtual void accessibility_window_activation_completed(DisplayServer::WindowID p_window_id); // Note: internal method used by Window, do not expose.
virtual void accessibility_window_deactivation_completed(DisplayServer::WindowID p_window_id); // Note: internal method used by Window, do not expose.
virtual void accessibility_update_set_role(const RID &p_id, DisplayServer::AccessibilityRole p_role);
virtual void accessibility_update_set_name(const RID &p_id, const String &p_name);
@@ -930,6 +933,9 @@ public:
virtual void accessibility_set_window_rect(DisplayServer::WindowID p_window_id, const Rect2 &p_rect_out, const Rect2 &p_rect_in) = 0;
virtual void accessibility_set_window_focused(DisplayServer::WindowID p_window_id, bool p_focused) = 0;
virtual void accessibility_set_window_callbacks(DisplayServer::WindowID p_window_id, const Callable &p_activate_callable, const Callable &p_deativate_callable) = 0;
virtual void accessibility_window_activation_completed(DisplayServer::WindowID p_window_id) = 0;
virtual void accessibility_window_deactivation_completed(DisplayServer::WindowID p_window_id) = 0;
virtual void accessibility_update_set_role(const RID &p_id, DisplayServer::AccessibilityRole p_role) = 0;
virtual void accessibility_update_set_name(const RID &p_id, const String &p_name) = 0;