mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
[Accessibility] Process non-focusable windows (popups, menus) as part of the parent window tree.
This commit is contained in:
parent
0c51ede243
commit
7b47f5e8db
8 changed files with 96 additions and 42 deletions
|
@ -38,7 +38,7 @@
|
||||||
#include "scene/theme/theme_db.h"
|
#include "scene/theme/theme_db.h"
|
||||||
|
|
||||||
void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
|
void Popup::_input_from_window(const Ref<InputEvent> &p_event) {
|
||||||
if ((ac_popup || get_flag(FLAG_POPUP)) && p_event->is_action_pressed(SNAME("ui_cancel"), false, true)) {
|
if (get_flag(FLAG_POPUP) && p_event->is_action_pressed(SNAME("ui_cancel"), false, true)) {
|
||||||
hide_reason = HIDE_REASON_CANCELED; // ESC pressed, mark as canceled unconditionally.
|
hide_reason = HIDE_REASON_CANCELED; // ESC pressed, mark as canceled unconditionally.
|
||||||
_close_pressed();
|
_close_pressed();
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ void Popup::_notification(int p_what) {
|
||||||
} break;
|
} break;
|
||||||
|
|
||||||
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
|
case NOTIFICATION_APPLICATION_FOCUS_OUT: {
|
||||||
if (!is_in_edited_scene_root() && (get_flag(FLAG_POPUP) || ac_popup)) {
|
if (!is_in_edited_scene_root() && get_flag(FLAG_POPUP)) {
|
||||||
if (hide_reason == HIDE_REASON_NONE) {
|
if (hide_reason == HIDE_REASON_NONE) {
|
||||||
hide_reason = HIDE_REASON_UNFOCUSED;
|
hide_reason = HIDE_REASON_UNFOCUSED;
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ void Popup::_notification(int p_what) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Popup::_parent_focused() {
|
void Popup::_parent_focused() {
|
||||||
if (popped_up && (get_flag(FLAG_POPUP) || ac_popup)) {
|
if (popped_up && get_flag(FLAG_POPUP)) {
|
||||||
if (hide_reason == HIDE_REASON_NONE) {
|
if (hide_reason == HIDE_REASON_NONE) {
|
||||||
hide_reason = HIDE_REASON_UNFOCUSED;
|
hide_reason = HIDE_REASON_UNFOCUSED;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,6 @@ class Popup : public Window {
|
||||||
GDCLASS(Popup, Window);
|
GDCLASS(Popup, Window);
|
||||||
|
|
||||||
LocalVector<Window *> visible_parents;
|
LocalVector<Window *> visible_parents;
|
||||||
bool ac_popup = false;
|
|
||||||
bool popped_up = false;
|
bool popped_up = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -60,7 +59,6 @@ protected:
|
||||||
void _close_pressed();
|
void _close_pressed();
|
||||||
virtual Rect2i _popup_adjust_rect() const override;
|
virtual Rect2i _popup_adjust_rect() const override;
|
||||||
virtual void _input_from_window(const Ref<InputEvent> &p_event) override;
|
virtual void _input_from_window(const Ref<InputEvent> &p_event) override;
|
||||||
void set_ac_popup() { ac_popup = true; }
|
|
||||||
|
|
||||||
void _notification(int p_what);
|
void _notification(int p_what);
|
||||||
void _validate_property(PropertyInfo &p_property) const;
|
void _validate_property(PropertyInfo &p_property) const;
|
||||||
|
|
|
@ -3209,13 +3209,8 @@ void PopupMenu::popup(const Rect2i &p_bounds) {
|
||||||
_native_popup(p_bounds != Rect2i() ? p_bounds : Rect2i(get_position(), Size2i()));
|
_native_popup(p_bounds != Rect2i() ? p_bounds : Rect2i(get_position(), Size2i()));
|
||||||
} else {
|
} else {
|
||||||
if (is_inside_tree()) {
|
if (is_inside_tree()) {
|
||||||
bool ac = get_tree()->is_accessibility_enabled();
|
set_flag(FLAG_POPUP, true);
|
||||||
// Note: Native popup menus need keyboard focus to work with screen reader.
|
set_flag(FLAG_NO_FOCUS, !is_embedded());
|
||||||
set_flag(FLAG_POPUP, !ac);
|
|
||||||
set_flag(FLAG_NO_FOCUS, !is_embedded() && !ac);
|
|
||||||
if (ac) {
|
|
||||||
set_ac_popup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
moved = Vector2();
|
moved = Vector2();
|
||||||
|
@ -3253,13 +3248,8 @@ void PopupMenu::set_visible(bool p_visible) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (is_inside_tree()) {
|
if (is_inside_tree()) {
|
||||||
bool ac = get_tree()->is_accessibility_enabled();
|
set_flag(FLAG_POPUP, true);
|
||||||
// Note: Native popup menus need keyboard focus to work with screen reader.
|
set_flag(FLAG_NO_FOCUS, !is_embedded());
|
||||||
set_flag(FLAG_POPUP, !ac);
|
|
||||||
set_flag(FLAG_NO_FOCUS, !is_embedded() && !ac);
|
|
||||||
if (ac) {
|
|
||||||
set_ac_popup();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Popup::set_visible(p_visible);
|
Popup::set_visible(p_visible);
|
||||||
|
|
|
@ -68,7 +68,7 @@ void Node::_notification(int p_notification) {
|
||||||
for (int i = 0; i < get_child_count(); i++) {
|
for (int i = 0; i < get_child_count(); i++) {
|
||||||
Node *child_node = get_child(i);
|
Node *child_node = get_child(i);
|
||||||
Window *child_wnd = Object::cast_to<Window>(child_node);
|
Window *child_wnd = Object::cast_to<Window>(child_node);
|
||||||
if (child_wnd && !child_wnd->is_embedded()) {
|
if (child_wnd && !(child_wnd->is_visible() && (child_wnd->is_embedded() || child_wnd->is_popup()))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (child_node->is_part_of_edited_scene()) {
|
if (child_node->is_part_of_edited_scene()) {
|
||||||
|
@ -2055,6 +2055,14 @@ Window *Node::get_window() const {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Window *Node::get_non_popup_window() const {
|
||||||
|
Window *w = get_window();
|
||||||
|
while (w && w->is_popup()) {
|
||||||
|
w = w->get_parent_visible_window();
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
Window *Node::get_last_exclusive_window() const {
|
Window *Node::get_last_exclusive_window() const {
|
||||||
Window *w = get_window();
|
Window *w = get_window();
|
||||||
while (w && w->get_exclusive_child()) {
|
while (w && w->get_exclusive_child()) {
|
||||||
|
@ -3687,8 +3695,9 @@ RID Node::get_accessibility_element() const {
|
||||||
return RID();
|
return RID();
|
||||||
}
|
}
|
||||||
if (unlikely(data.accessibility_element.is_null())) {
|
if (unlikely(data.accessibility_element.is_null())) {
|
||||||
if (get_window() && get_window()->get_window_id() != DisplayServer::INVALID_WINDOW_ID) {
|
Window *w = get_non_popup_window();
|
||||||
data.accessibility_element = DisplayServer::get_singleton()->accessibility_create_element(get_window()->get_window_id(), DisplayServer::ROLE_CONTAINER);
|
if (w && w->get_window_id() != DisplayServer::INVALID_WINDOW_ID && get_window()->is_visible()) {
|
||||||
|
data.accessibility_element = DisplayServer::get_singleton()->accessibility_create_element(w->get_window_id(), DisplayServer::ROLE_CONTAINER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return data.accessibility_element;
|
return data.accessibility_element;
|
||||||
|
|
|
@ -500,6 +500,7 @@ public:
|
||||||
Node *find_parent(const String &p_pattern) const;
|
Node *find_parent(const String &p_pattern) const;
|
||||||
|
|
||||||
Window *get_window() const;
|
Window *get_window() const;
|
||||||
|
Window *get_non_popup_window() const;
|
||||||
Window *get_last_exclusive_window() const;
|
Window *get_last_exclusive_window() const;
|
||||||
|
|
||||||
_FORCE_INLINE_ SceneTree *get_tree() const {
|
_FORCE_INLINE_ SceneTree *get_tree() const {
|
||||||
|
|
|
@ -246,10 +246,10 @@ void SceneTree::_process_accessibility_changes(DisplayServer::WindowID p_window_
|
||||||
Vector<ObjectID> processed;
|
Vector<ObjectID> processed;
|
||||||
for (const ObjectID &id : accessibility_change_queue) {
|
for (const ObjectID &id : accessibility_change_queue) {
|
||||||
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(id));
|
Node *node = Object::cast_to<Node>(ObjectDB::get_instance(id));
|
||||||
if (!node || !node->get_window()) {
|
if (!node || !node->get_non_popup_window() || !node->get_window()->is_visible()) {
|
||||||
processed.push_back(id);
|
processed.push_back(id);
|
||||||
continue; // Invalid node, remove from list and skip.
|
continue; // Invalid node, remove from list and skip.
|
||||||
} else if (node->get_window()->get_window_id() != p_window_id) {
|
} else if (node->get_non_popup_window()->get_window_id() != p_window_id) {
|
||||||
continue; // Another window, skip.
|
continue; // Another window, skip.
|
||||||
}
|
}
|
||||||
node->notification(Node::NOTIFICATION_ACCESSIBILITY_UPDATE);
|
node->notification(Node::NOTIFICATION_ACCESSIBILITY_UPDATE);
|
||||||
|
@ -267,6 +267,15 @@ void SceneTree::_process_accessibility_changes(DisplayServer::WindowID p_window_
|
||||||
w_this = w_focus;
|
w_this = w_focus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Popups have no native window focus, but have focused element.
|
||||||
|
DisplayServer::WindowID popup_id = DisplayServer::get_singleton()->window_get_active_popup();
|
||||||
|
if (popup_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||||
|
Window *popup_w = Window::get_from_id(popup_id);
|
||||||
|
if (popup_w && w_this->is_ancestor_of(popup_w)) {
|
||||||
|
w_this = popup_w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
RID new_focus_element;
|
RID new_focus_element;
|
||||||
Control *n_focus = w_this->gui_get_focus_owner();
|
Control *n_focus = w_this->gui_get_focus_owner();
|
||||||
if (n_focus && !n_focus->is_part_of_edited_scene()) {
|
if (n_focus && !n_focus->is_part_of_edited_scene()) {
|
||||||
|
|
|
@ -570,6 +570,10 @@ bool Window::get_flag(Flags p_flag) const {
|
||||||
return flags[p_flag];
|
return flags[p_flag];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Window::is_popup() const {
|
||||||
|
return get_flag(Window::FLAG_POPUP) || get_flag(Window::FLAG_NO_FOCUS);
|
||||||
|
}
|
||||||
|
|
||||||
bool Window::is_maximize_allowed() const {
|
bool Window::is_maximize_allowed() const {
|
||||||
ERR_READ_THREAD_GUARD_V(false);
|
ERR_READ_THREAD_GUARD_V(false);
|
||||||
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||||
|
@ -680,11 +684,6 @@ void Window::_make_window() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_tree() && get_tree()->is_accessibility_supported()) {
|
|
||||||
get_tree()->_accessibility_force_update();
|
|
||||||
_accessibility_notify_enter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
_update_window_callbacks();
|
_update_window_callbacks();
|
||||||
|
|
||||||
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_VISIBLE);
|
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_VISIBLE);
|
||||||
|
@ -716,10 +715,6 @@ void Window::_clear_window() {
|
||||||
|
|
||||||
_update_from_window();
|
_update_from_window();
|
||||||
|
|
||||||
if (get_tree() && get_tree()->is_accessibility_supported()) {
|
|
||||||
_accessibility_notify_exit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
DisplayServer::get_singleton()->delete_sub_window(window_id);
|
DisplayServer::get_singleton()->delete_sub_window(window_id);
|
||||||
window_id = DisplayServer::INVALID_WINDOW_ID;
|
window_id = DisplayServer::INVALID_WINDOW_ID;
|
||||||
|
|
||||||
|
@ -886,7 +881,7 @@ void Window::_accessibility_notify_enter(Node *p_node) {
|
||||||
|
|
||||||
if (p_node != this) {
|
if (p_node != this) {
|
||||||
const Window *window = Object::cast_to<Window>(p_node);
|
const Window *window = Object::cast_to<Window>(p_node);
|
||||||
if (window && !window->is_embedded()) {
|
if (window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -901,7 +896,7 @@ void Window::_accessibility_notify_exit(Node *p_node) {
|
||||||
|
|
||||||
if (p_node != this) {
|
if (p_node != this) {
|
||||||
const Window *window = Object::cast_to<Window>(p_node);
|
const Window *window = Object::cast_to<Window>(p_node);
|
||||||
if (window && !window->is_embedded()) {
|
if (window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -950,23 +945,35 @@ void Window::set_visible(bool p_visible) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
embedder->_sub_window_register(this);
|
embedder->_sub_window_register(this);
|
||||||
embedder->queue_accessibility_update();
|
|
||||||
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
|
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_WHEN_PARENT_VISIBLE);
|
||||||
} else {
|
} else {
|
||||||
embedder->_sub_window_remove(this);
|
embedder->_sub_window_remove(this);
|
||||||
embedder->queue_accessibility_update();
|
|
||||||
embedder = nullptr;
|
embedder = nullptr;
|
||||||
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED);
|
RS::get_singleton()->viewport_set_update_mode(get_viewport_rid(), RS::VIEWPORT_UPDATE_DISABLED);
|
||||||
}
|
}
|
||||||
_update_window_size();
|
_update_window_size();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!visible) {
|
if (visible) {
|
||||||
|
if (get_tree() && get_tree()->is_accessibility_supported()) {
|
||||||
|
get_tree()->_accessibility_force_update();
|
||||||
|
_accessibility_notify_enter(this);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (get_tree() && get_tree()->is_accessibility_supported()) {
|
||||||
|
_accessibility_notify_exit(this);
|
||||||
|
}
|
||||||
focused = false;
|
focused = false;
|
||||||
if (focused_window == this) {
|
if (focused_window == this) {
|
||||||
focused_window = nullptr;
|
focused_window = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (get_parent()) {
|
||||||
|
get_parent()->queue_accessibility_update();
|
||||||
|
}
|
||||||
|
if (embedder) {
|
||||||
|
embedder->queue_accessibility_update();
|
||||||
|
}
|
||||||
|
|
||||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||||
emit_signal(SceneStringName(visibility_changed));
|
emit_signal(SceneStringName(visibility_changed));
|
||||||
|
@ -1371,10 +1378,10 @@ Viewport *Window::get_embedder() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
RID Window::get_accessibility_element() const {
|
RID Window::get_accessibility_element() const {
|
||||||
if (is_part_of_edited_scene()) {
|
if (!visible || is_part_of_edited_scene()) {
|
||||||
return RID();
|
return RID();
|
||||||
}
|
}
|
||||||
if (get_embedder()) {
|
if (get_embedder() || is_popup()) {
|
||||||
return Node::get_accessibility_element();
|
return Node::get_accessibility_element();
|
||||||
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
|
||||||
return DisplayServer::get_singleton()->accessibility_get_window_root(window_id);
|
return DisplayServer::get_singleton()->accessibility_get_window_root(window_id);
|
||||||
|
@ -1415,11 +1422,18 @@ void Window::_notification(int p_what) {
|
||||||
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_FOCUS, callable_mp(this, &Window::_accessibility_action_grab_focus));
|
DisplayServer::get_singleton()->accessibility_update_add_action(ae, DisplayServer::AccessibilityAction::ACTION_FOCUS, callable_mp(this, &Window::_accessibility_action_grab_focus));
|
||||||
DisplayServer::get_singleton()->accessibility_update_set_flag(ae, DisplayServer::AccessibilityFlags::FLAG_HIDDEN, !visible);
|
DisplayServer::get_singleton()->accessibility_update_set_flag(ae, DisplayServer::AccessibilityFlags::FLAG_HIDDEN, !visible);
|
||||||
|
|
||||||
if (get_embedder()) {
|
if (get_embedder() || is_popup()) {
|
||||||
Control *parent_ctrl = Object::cast_to<Control>(get_parent());
|
Control *parent_ctrl = Object::cast_to<Control>(get_parent());
|
||||||
Transform2D parent_tr = parent_ctrl ? parent_ctrl->get_global_transform() : Transform2D();
|
Transform2D parent_tr = parent_ctrl ? parent_ctrl->get_global_transform() : Transform2D();
|
||||||
Transform2D tr;
|
Transform2D tr;
|
||||||
tr.set_origin(position);
|
if (window_id == DisplayServer::INVALID_WINDOW_ID) {
|
||||||
|
tr.set_origin(position);
|
||||||
|
} else {
|
||||||
|
Window *np = get_non_popup_window();
|
||||||
|
if (np) {
|
||||||
|
tr.set_origin(get_position() - np->get_position());
|
||||||
|
}
|
||||||
|
}
|
||||||
DisplayServer::get_singleton()->accessibility_update_set_transform(ae, parent_tr.affine_inverse() * tr);
|
DisplayServer::get_singleton()->accessibility_update_set_transform(ae, parent_tr.affine_inverse() * tr);
|
||||||
DisplayServer::get_singleton()->accessibility_update_set_bounds(ae, Rect2(Point2(), size));
|
DisplayServer::get_singleton()->accessibility_update_set_bounds(ae, Rect2(Point2(), size));
|
||||||
|
|
||||||
|
@ -1540,9 +1554,19 @@ void Window::_notification(int p_what) {
|
||||||
_make_transient();
|
_make_transient();
|
||||||
}
|
}
|
||||||
if (visible) {
|
if (visible) {
|
||||||
|
if (window_id != DisplayServer::MAIN_WINDOW_ID && get_tree() && get_tree()->is_accessibility_supported()) {
|
||||||
|
get_tree()->_accessibility_force_update();
|
||||||
|
_accessibility_notify_enter(this);
|
||||||
|
}
|
||||||
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
notification(NOTIFICATION_VISIBILITY_CHANGED);
|
||||||
emit_signal(SceneStringName(visibility_changed));
|
emit_signal(SceneStringName(visibility_changed));
|
||||||
RS::get_singleton()->viewport_set_active(get_viewport_rid(), true);
|
RS::get_singleton()->viewport_set_active(get_viewport_rid(), true);
|
||||||
|
if (get_parent()) {
|
||||||
|
get_parent()->queue_accessibility_update();
|
||||||
|
}
|
||||||
|
if (embedder) {
|
||||||
|
embedder->queue_accessibility_update();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emits NOTIFICATION_THEME_CHANGED internally.
|
// Emits NOTIFICATION_THEME_CHANGED internally.
|
||||||
|
@ -1584,6 +1608,18 @@ void Window::_notification(int p_what) {
|
||||||
|
|
||||||
set_theme_context(nullptr, false);
|
set_theme_context(nullptr, false);
|
||||||
|
|
||||||
|
if (visible && window_id != DisplayServer::MAIN_WINDOW_ID) {
|
||||||
|
if (get_tree() && get_tree()->is_accessibility_supported()) {
|
||||||
|
_accessibility_notify_exit(this);
|
||||||
|
if (get_parent()) {
|
||||||
|
get_parent()->queue_accessibility_update();
|
||||||
|
}
|
||||||
|
if (embedder) {
|
||||||
|
embedder->queue_accessibility_update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
accessibility_title_element = RID();
|
accessibility_title_element = RID();
|
||||||
accessibility_announcement_element = RID();
|
accessibility_announcement_element = RID();
|
||||||
|
|
||||||
|
@ -1816,6 +1852,14 @@ Viewport *Window::get_parent_viewport() const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Window *Window::get_non_popup_window() const {
|
||||||
|
Window *w = const_cast<Window *>(this);
|
||||||
|
while (w && w->is_popup()) {
|
||||||
|
w = w->get_parent_visible_window();
|
||||||
|
}
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
Window *Window::get_parent_visible_window() const {
|
Window *Window::get_parent_visible_window() const {
|
||||||
ERR_READ_THREAD_GUARD_V(nullptr);
|
ERR_READ_THREAD_GUARD_V(nullptr);
|
||||||
Viewport *vp = get_parent_viewport();
|
Viewport *vp = get_parent_viewport();
|
||||||
|
|
|
@ -332,6 +332,8 @@ public:
|
||||||
void set_flag(Flags p_flag, bool p_enabled);
|
void set_flag(Flags p_flag, bool p_enabled);
|
||||||
bool get_flag(Flags p_flag) const;
|
bool get_flag(Flags p_flag) const;
|
||||||
|
|
||||||
|
bool is_popup() const;
|
||||||
|
|
||||||
bool is_maximize_allowed() const;
|
bool is_maximize_allowed() const;
|
||||||
|
|
||||||
void request_attention();
|
void request_attention();
|
||||||
|
@ -399,6 +401,7 @@ public:
|
||||||
Window *get_exclusive_child() const { return exclusive_child; }
|
Window *get_exclusive_child() const { return exclusive_child; }
|
||||||
HashSet<Window *> get_transient_children() const { return transient_children; }
|
HashSet<Window *> get_transient_children() const { return transient_children; }
|
||||||
Window *get_parent_visible_window() const;
|
Window *get_parent_visible_window() const;
|
||||||
|
Window *get_non_popup_window() const;
|
||||||
Viewport *get_parent_viewport() const;
|
Viewport *get_parent_viewport() const;
|
||||||
|
|
||||||
virtual void popup(const Rect2i &p_screen_rect = Rect2i());
|
virtual void popup(const Rect2i &p_screen_rect = Rect2i());
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue