[Accessibility] Handle adapter activation/deactivation.

This commit is contained in:
Pāvels Nadtočajevs 2026-01-29 09:02:10 +02:00
parent 8db94f7b5e
commit 876dcc8a5d
No known key found for this signature in database
GPG key ID: 8413210218EF35D2
7 changed files with 140 additions and 4 deletions

View file

@ -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);

View file

@ -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;

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");

View file

@ -720,6 +720,7 @@ void Window::_make_window() {
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()->window_request_hdr_output(hdr_output_requested, 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();
@ -943,6 +944,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();
@ -1032,10 +1043,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) {
@ -1479,8 +1492,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: {
@ -1600,6 +1619,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.
{
@ -1638,6 +1658,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));
@ -1692,6 +1713,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();
}

View file

@ -171,6 +171,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;

View file

@ -726,6 +726,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);

View file

@ -464,7 +464,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;
@ -735,6 +735,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);
@ -967,6 +970,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;