diff --git a/drivers/accesskit/accessibility_driver_accesskit.cpp b/drivers/accesskit/accessibility_driver_accesskit.cpp index c0794462c8..57b73f81e8 100644 --- a/drivers/accesskit/accessibility_driver_accesskit.cpp +++ b/drivers/accesskit/accessibility_driver_accesskit.cpp @@ -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 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); diff --git a/drivers/accesskit/accessibility_driver_accesskit.h b/drivers/accesskit/accessibility_driver_accesskit.h index 2349602818..a4196c6bcb 100644 --- a/drivers/accesskit/accessibility_driver_accesskit.h +++ b/drivers/accesskit/accessibility_driver_accesskit.h @@ -81,7 +81,10 @@ class AccessibilityDriverAccessKit : public AccessibilityDriver { #endif RID root_id; + bool initial_update_completed = false; HashSet 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; diff --git a/modules/camera/camera_macos.mm b/modules/camera/camera_macos.mm index 7de5e91ec6..7e3b78e2da 100644 --- a/modules/camera/camera_macos.mm +++ b/modules/camera/camera_macos.mm @@ -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"); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 10ac9f3aba..55dfff3c84 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -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(); } diff --git a/scene/main/window.h b/scene/main/window.h index 84a872ac1e..1f7c30a546 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -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; diff --git a/servers/display/display_server.cpp b/servers/display/display_server.cpp index 24f44e3562..1a34068765 100644 --- a/servers/display/display_server.cpp +++ b/servers/display/display_server.cpp @@ -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); diff --git a/servers/display/display_server.h b/servers/display/display_server.h index a52ed07442..1306857738 100644 --- a/servers/display/display_server.h +++ b/servers/display/display_server.h @@ -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;