Single-window mode popups and edited scene windows fixes.

Fix single-window mode popup not closing when OptionBox is clicked.
Fix single-window mode submenus closing when parent menu item, that was used to open it is clicked (using same safe-area logic as platform specific code).
Disallow windows that are part of an edited scene from being set as exclusive or popup to prevent it from locking up the editor.
This commit is contained in:
bruvzg 2022-06-09 11:59:01 +03:00
parent 803d25a20a
commit f7269fe878
No known key found for this signature in database
GPG Key ID: 7960FCF39844EC38
5 changed files with 69 additions and 13 deletions

View File

@ -108,9 +108,7 @@ void Popup::_close_pressed() {
_deinitialize_visible_parents();
// Hide after returning to process events, but only if we don't
// get popped up in the interim.
call_deferred(SNAME("_popup_conditional_hide"));
call_deferred(SNAME("hide"));
}
void Popup::_post_popup() {
@ -118,15 +116,8 @@ void Popup::_post_popup() {
popped_up = true;
}
void Popup::_popup_conditional_hide() {
if (!popped_up) {
hide();
}
}
void Popup::_bind_methods() {
ADD_SIGNAL(MethodInfo("popup_hide"));
ClassDB::bind_method(D_METHOD("_popup_conditional_hide"), &Popup::_popup_conditional_hide);
}
Rect2i Popup::_popup_adjust_rect() const {

View File

@ -48,8 +48,6 @@ class Popup : public Window {
void _initialize_visible_parents();
void _deinitialize_visible_parents();
void _parent_focused();
protected:
void _close_pressed();
virtual Rect2i _popup_adjust_rect() const override;
@ -57,7 +55,7 @@ protected:
void _notification(int p_what);
static void _bind_methods();
void _popup_conditional_hide();
virtual void _parent_focused();
virtual void _post_popup() override;

View File

@ -243,6 +243,29 @@ void PopupMenu::_activate_submenu(int p_over, bool p_by_keyboard) {
}
}
void PopupMenu::_parent_focused() {
if (is_embedded()) {
Point2 mouse_pos_adjusted;
Window *window_parent = Object::cast_to<Window>(get_parent()->get_viewport());
while (window_parent) {
if (!window_parent->is_embedded()) {
mouse_pos_adjusted += window_parent->get_position();
break;
}
window_parent = Object::cast_to<Window>(window_parent->get_parent()->get_viewport());
}
Rect2 safe_area = DisplayServer::get_singleton()->window_get_popup_safe_rect(get_window_id());
Point2 pos = DisplayServer::get_singleton()->mouse_get_position() - mouse_pos_adjusted;
if (safe_area == Rect2i() || !safe_area.has_point(pos)) {
Popup::_parent_focused();
} else {
grab_focus();
}
}
}
void PopupMenu::_submenu_timeout() {
if (mouse_over == submenu_over) {
_activate_submenu(mouse_over);

View File

@ -148,6 +148,8 @@ public:
// this value should be updated to reflect the new size.
static const int ITEM_PROPERTY_SIZE = 10;
virtual void _parent_focused() override;
void add_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
void add_icon_item(const Ref<Texture2D> &p_icon, const String &p_label, int p_id = -1, Key p_accel = Key::NONE);
void add_check_item(const String &p_label, int p_id = -1, Key p_accel = Key::NONE);

View File

@ -165,14 +165,26 @@ void Window::set_flag(Flags p_flag, bool p_enabled) {
embedder->_sub_window_update(this);
} else if (window_id != DisplayServer::INVALID_WINDOW_ID) {
#ifdef TOOLS_ENABLED
if ((p_flag != FLAG_POPUP) || !(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
DisplayServer::get_singleton()->window_set_flag(DisplayServer::WindowFlags(p_flag), p_enabled, window_id);
}
#else
DisplayServer::get_singleton()->window_set_flag(DisplayServer::WindowFlags(p_flag), p_enabled, window_id);
#endif
}
}
bool Window::get_flag(Flags p_flag) const {
ERR_FAIL_INDEX_V(p_flag, FLAG_MAX, false);
if (window_id != DisplayServer::INVALID_WINDOW_ID) {
#ifdef TOOLS_ENABLED
if ((p_flag != FLAG_POPUP) || !(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
flags[p_flag] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(p_flag), window_id);
}
#else
flags[p_flag] = DisplayServer::get_singleton()->window_get_flag(DisplayServer::WindowFlags(p_flag), window_id);
#endif
}
return flags[p_flag];
}
@ -255,7 +267,15 @@ void Window::_make_window() {
#endif
DisplayServer::get_singleton()->window_set_title(tr_title, window_id);
DisplayServer::get_singleton()->window_attach_instance_id(get_instance_id(), window_id);
#ifdef TOOLS_ENABLED
if (!(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
} else {
DisplayServer::get_singleton()->window_set_exclusive(window_id, false);
}
#else
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
#endif
_update_window_size();
@ -441,6 +461,8 @@ void Window::set_visible(bool p_visible) {
ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
transient_parent->exclusive_child = this;
}
#else
transient_parent->exclusive_child = this;
#endif
} else {
if (transient_parent->exclusive_child == this) {
@ -488,7 +510,13 @@ void Window::_make_transient() {
window->transient_children.insert(this);
if (is_inside_tree() && is_visible() && exclusive) {
if (transient_parent->exclusive_child == nullptr) {
#ifdef TOOLS_ENABLED
if (!(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
transient_parent->exclusive_child = this;
}
#else
transient_parent->exclusive_child = this;
#endif
} else if (transient_parent->exclusive_child != this) {
ERR_PRINT("Making child transient exclusive, but parent has another exclusive child");
}
@ -531,13 +559,27 @@ void Window::set_exclusive(bool p_exclusive) {
exclusive = p_exclusive;
if (!embedder && window_id != DisplayServer::INVALID_WINDOW_ID) {
#ifdef TOOLS_ENABLED
if (!(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
} else {
DisplayServer::get_singleton()->window_set_exclusive(window_id, false);
}
#else
DisplayServer::get_singleton()->window_set_exclusive(window_id, exclusive);
#endif
}
if (transient_parent) {
if (p_exclusive && is_inside_tree() && is_visible()) {
ERR_FAIL_COND_MSG(transient_parent->exclusive_child && transient_parent->exclusive_child != this, "Transient parent has another exclusive child.");
#ifdef TOOLS_ENABLED
if (!(Engine::get_singleton()->is_editor_hint() && get_tree()->get_edited_scene_root() && get_tree()->get_edited_scene_root()->is_ancestor_of(this))) {
transient_parent->exclusive_child = this;
}
#else
transient_parent->exclusive_child = this;
#endif
} else {
if (transient_parent->exclusive_child == this) {
transient_parent->exclusive_child = nullptr;