From fa02d19fd170d050bb47c4e525061bf96afdb62a Mon Sep 17 00:00:00 2001 From: Markus Sauermann <6299227+Sauermann@users.noreply.github.com> Date: Fri, 1 Sep 2023 08:40:35 +0200 Subject: [PATCH] Fix internal events not being delivered to some Window types `AcceptDialog`, `Popup` and `PopupMenu` no longer subscribe to "window_input" signal, because that is only sent if it is not an internal signal. Instead they receive events in `_input_from_window`. They ensure that the event is also propagated to their super-function, just like previously the signals would be treated. --- scene/gui/dialogs.cpp | 3 +-- scene/gui/dialogs.h | 2 +- scene/gui/popup.cpp | 3 +-- scene/gui/popup.h | 3 +-- scene/gui/popup_menu.cpp | 13 +++++++++---- scene/gui/popup_menu.h | 3 ++- scene/main/window.cpp | 7 ++++++- scene/main/window.h | 1 + 8 files changed, 22 insertions(+), 13 deletions(-) diff --git a/scene/gui/dialogs.cpp b/scene/gui/dialogs.cpp index 957a8f276ee9..3e827e76dce3 100644 --- a/scene/gui/dialogs.cpp +++ b/scene/gui/dialogs.cpp @@ -42,6 +42,7 @@ void AcceptDialog::_input_from_window(const Ref &p_event) { if (close_on_escape && p_event->is_action_pressed(SNAME("ui_cancel"), false, true)) { _cancel_pressed(); } + Window::_input_from_window(p_event); } void AcceptDialog::_parent_focused() { @@ -428,8 +429,6 @@ AcceptDialog::AcceptDialog() { ok_button->connect("pressed", callable_mp(this, &AcceptDialog::_ok_pressed)); set_title(TTRC("Alert!")); - - connect("window_input", callable_mp(this, &AcceptDialog::_input_from_window)); } AcceptDialog::~AcceptDialog() { diff --git a/scene/gui/dialogs.h b/scene/gui/dialogs.h index d5cbaaeef818..e28d6b7467cc 100644 --- a/scene/gui/dialogs.h +++ b/scene/gui/dialogs.h @@ -65,11 +65,11 @@ class AcceptDialog : public Window { static bool swap_cancel_ok; - void _input_from_window(const Ref &p_event); void _parent_focused(); protected: virtual Size2 _get_contents_minimum_size() const override; + virtual void _input_from_window(const Ref &p_event) override; void _notification(int p_what); static void _bind_methods(); diff --git a/scene/gui/popup.cpp b/scene/gui/popup.cpp index b16e8371a259..8369bedda95b 100644 --- a/scene/gui/popup.cpp +++ b/scene/gui/popup.cpp @@ -39,6 +39,7 @@ void Popup::_input_from_window(const Ref &p_event) { if (get_flag(FLAG_POPUP) && p_event->is_action_pressed(SNAME("ui_cancel"), false, true)) { _close_pressed(); } + Window::_input_from_window(p_event); } void Popup::_initialize_visible_parents() { @@ -204,8 +205,6 @@ Popup::Popup() { set_flag(FLAG_BORDERLESS, true); set_flag(FLAG_RESIZE_DISABLED, true); set_flag(FLAG_POPUP, true); - - connect("window_input", callable_mp(this, &Popup::_input_from_window)); } Popup::~Popup() { diff --git a/scene/gui/popup.h b/scene/gui/popup.h index d524e448ddec..25edca36577d 100644 --- a/scene/gui/popup.h +++ b/scene/gui/popup.h @@ -47,14 +47,13 @@ class Popup : public Window { Ref panel_style; } theme_cache; - void _input_from_window(const Ref &p_event); - void _initialize_visible_parents(); void _deinitialize_visible_parents(); protected: void _close_pressed(); virtual Rect2i _popup_adjust_rect() const override; + virtual void _input_from_window(const Ref &p_event) override; void _notification(int p_what); void _validate_property(PropertyInfo &p_property) const; diff --git a/scene/gui/popup_menu.cpp b/scene/gui/popup_menu.cpp index d6b8dd02025d..cf8082d13741 100644 --- a/scene/gui/popup_menu.cpp +++ b/scene/gui/popup_menu.cpp @@ -378,9 +378,16 @@ void PopupMenu::_submenu_timeout() { submenu_over = -1; } -void PopupMenu::gui_input(const Ref &p_event) { - ERR_FAIL_COND(p_event.is_null()); +void PopupMenu::_input_from_window(const Ref &p_event) { + if (p_event.is_valid()) { + _input_from_window_internal(p_event); + } else { + WARN_PRINT_ONCE("PopupMenu has received an invalid InputEvent. Consider filtering invalid events out."); + } + Popup::_input_from_window(p_event); +} +void PopupMenu::_input_from_window_internal(const Ref &p_event) { if (!items.is_empty()) { Input *input = Input::get_singleton(); Ref joypadmotion_event = p_event; @@ -2799,8 +2806,6 @@ PopupMenu::PopupMenu() { scroll_container->add_child(control, false, INTERNAL_MODE_FRONT); control->connect("draw", callable_mp(this, &PopupMenu::_draw_items)); - connect("window_input", callable_mp(this, &PopupMenu::gui_input)); - submenu_timer = memnew(Timer); submenu_timer->set_wait_time(0.3); submenu_timer->set_one_shot(true); diff --git a/scene/gui/popup_menu.h b/scene/gui/popup_menu.h index 5d5f4a8322a6..3e542b5d8b68 100644 --- a/scene/gui/popup_menu.h +++ b/scene/gui/popup_menu.h @@ -112,7 +112,6 @@ class PopupMenu : public Popup { void _shape_item(int p_idx); - virtual void gui_input(const Ref &p_event); void _activate_submenu(int p_over, bool p_by_keyboard = false); void _submenu_timeout(); @@ -191,10 +190,12 @@ class PopupMenu : public Popup { void _minimum_lifetime_timeout(); void _close_pressed(); void _menu_changed(); + void _input_from_window_internal(const Ref &p_event); protected: virtual void add_child_notify(Node *p_child) override; virtual void remove_child_notify(Node *p_child) override; + virtual void _input_from_window(const Ref &p_event) override; void _notification(int p_what); bool _set(const StringName &p_name, const Variant &p_value); diff --git a/scene/main/window.cpp b/scene/main/window.cpp index 2c28dc31d608..0d554de6f453 100644 --- a/scene/main/window.cpp +++ b/scene/main/window.cpp @@ -1543,7 +1543,12 @@ void Window::_window_input(const Ref &p_ev) { } } - if (p_ev->get_device() != InputEvent::DEVICE_ID_INTERNAL) { + // If the event needs to be handled in a Window-derived class, then it should overwrite + // `_input_from_window` instead of subscribing to the `window_input` signal, because the signal + // filters out internal events. + _input_from_window(p_ev); + + if (p_ev->get_device() != InputEvent::DEVICE_ID_INTERNAL && is_inside_tree()) { emit_signal(SceneStringNames::get_singleton()->window_input, p_ev); } diff --git a/scene/main/window.h b/scene/main/window.h index 8a54b6c7d3ee..3ef8d41b1b02 100644 --- a/scene/main/window.h +++ b/scene/main/window.h @@ -239,6 +239,7 @@ class Window : public Viewport { virtual void _post_popup() {} virtual void _update_theme_item_cache(); + virtual void _input_from_window(const Ref &p_event) {} void _notification(int p_what); static void _bind_methods();