diff options
-rw-r--r-- | scene/gui/popup.cpp | 68 | ||||
-rw-r--r-- | scene/gui/popup.h | 9 |
2 files changed, 49 insertions, 28 deletions
diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index 5fc5f9b669..390ad30c4c 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -41,55 +41,71 @@ void Popup::_input_from_window(const Ref<InputEvent> &p_event) { } } -void Popup::_parent_focused() { - _close_pressed(); +void Popup::_initialize_visible_parents() { + visible_parents.clear(); + + Window *parent_window = this; + while (parent_window) { + parent_window = parent_window->get_parent_visible_window(); + if (parent_window) { + visible_parents.push_back(parent_window); + parent_window->connect("focus_entered", callable_mp(this, &Popup::_parent_focused)); + parent_window->connect("tree_exited", callable_mp(this, &Popup::_deinitialize_visible_parents)); + } + } +} + +void Popup::_deinitialize_visible_parents() { + for (uint32_t i = 0; i < visible_parents.size(); ++i) { + visible_parents[i]->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); + visible_parents[i]->disconnect("tree_exited", callable_mp(this, &Popup::_deinitialize_visible_parents)); + } + + visible_parents.clear(); } void Popup::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { if (is_visible()) { - parent_visible = get_parent_visible_window(); - if (parent_visible) { - parent_visible->connect("focus_entered", callable_mp(this, &Popup::_parent_focused)); - } + _initialize_visible_parents(); } else { - if (parent_visible) { - parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); - parent_visible = nullptr; - } - + _deinitialize_visible_parents(); emit_signal("popup_hide"); } } break; - case NOTIFICATION_EXIT_TREE: { - if (parent_visible) { - parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); - parent_visible = nullptr; + case NOTIFICATION_WM_WINDOW_FOCUS_IN: { + if (has_focus()) { + popped_up = true; } } break; + case NOTIFICATION_EXIT_TREE: { + _deinitialize_visible_parents(); + } break; case NOTIFICATION_WM_CLOSE_REQUEST: { _close_pressed(); - + } break; + case NOTIFICATION_APPLICATION_FOCUS_OUT: { + _close_pressed(); } break; } } -void Popup::_close_pressed() { - Window *parent_window = parent_visible; - if (parent_visible) { - parent_visible->disconnect("focus_entered", callable_mp(this, &Popup::_parent_focused)); - parent_visible = nullptr; +void Popup::_parent_focused() { + if (popped_up) { + _close_pressed(); } +} + +void Popup::_close_pressed() { + popped_up = false; + + _deinitialize_visible_parents(); call_deferred("hide"); emit_signal("cancelled"); - - if (parent_window) { - //parent_window->grab_focus(); - } } void Popup::set_as_minsize() { @@ -130,8 +146,6 @@ Rect2i Popup::_popup_adjust_rect() const { } Popup::Popup() { - parent_visible = nullptr; - set_wrap_controls(true); set_visible(false); set_transient(true); diff --git a/scene/gui/popup.h b/scene/gui/popup.h index 97c08095d3..3e5b89ccf3 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -33,12 +33,19 @@ #include "scene/main/window.h" +#include "core/local_vector.h" + class Popup : public Window { GDCLASS(Popup, Window); - Window *parent_visible; + LocalVector<Window *> visible_parents; + bool popped_up = false; void _input_from_window(const Ref<InputEvent> &p_event); + + void _initialize_visible_parents(); + void _deinitialize_visible_parents(); + void _parent_focused(); protected: |