diff options
author | RĂ©mi Verschelde <rverschelde@gmail.com> | 2020-11-28 09:04:25 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-28 09:04:25 +0100 |
commit | a09846e01542f199bbc7eb8b85003736a57f3e16 (patch) | |
tree | dcb2a7c189a7f65095cb1fef9f59eee45b072360 /scene/gui | |
parent | a6751e6c58e73d6b8d04e98bba5fb6e380fdf34f (diff) | |
parent | 7941235e06c8acf1cb2888de3db8905c60c8ff00 (diff) |
Merge pull request #42109 from EricEzaM/PR/input-and-shortcuts-rework
Shortcuts rework - fixed issues with input propagation and triggering of unwanted shortcuts.
Diffstat (limited to 'scene/gui')
-rw-r--r-- | scene/gui/base_button.cpp | 40 | ||||
-rw-r--r-- | scene/gui/base_button.h | 8 | ||||
-rw-r--r-- | scene/gui/control.cpp | 1 | ||||
-rw-r--r-- | scene/gui/menu_button.cpp | 9 | ||||
-rw-r--r-- | scene/gui/menu_button.h | 2 |
5 files changed, 51 insertions, 9 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index 1a19c75d27..fab0dea804 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -317,16 +317,21 @@ bool BaseButton::is_keep_pressed_outside() const { void BaseButton::set_shortcut(const Ref<Shortcut> &p_shortcut) { shortcut = p_shortcut; - set_process_unhandled_input(shortcut.is_valid()); + set_process_unhandled_key_input(shortcut.is_valid()); } Ref<Shortcut> BaseButton::get_shortcut() const { return shortcut; } -void BaseButton::_unhandled_input(Ref<InputEvent> p_event) { +void BaseButton::_unhandled_key_input(Ref<InputEvent> p_event) { + if (!_is_focus_owner_in_shorcut_context()) { + return; + } + if (!is_disabled() && is_visible_in_tree() && !p_event->is_echo() && shortcut.is_valid() && shortcut->is_shortcut(p_event)) { on_action_event(p_event); + accept_event(); } } @@ -360,9 +365,34 @@ Ref<ButtonGroup> BaseButton::get_button_group() const { return button_group; } +void BaseButton::set_shortcut_context(Node *p_node) { + ERR_FAIL_NULL_MSG(p_node, "Shortcut context node can't be null."); + shortcut_context = p_node->get_instance_id(); +} + +Node *BaseButton::get_shortcut_context() const { + Object *ctx_obj = ObjectDB::get_instance(shortcut_context); + Node *ctx_node = Object::cast_to<Node>(ctx_obj); + + return ctx_node; +} + +bool BaseButton::_is_focus_owner_in_shorcut_context() const { + if (shortcut_context == ObjectID()) { + // No context, therefore global - always "in" context. + return true; + } + + Node *ctx_node = get_shortcut_context(); + Control *vp_focus = get_focus_owner(); + + // If the context is valid and the viewport focus is valid, check if the context is the focus or is a parent of it. + return ctx_node && vp_focus && (ctx_node == vp_focus || ctx_node->is_a_parent_of(vp_focus)); +} + void BaseButton::_bind_methods() { ClassDB::bind_method(D_METHOD("_gui_input"), &BaseButton::_gui_input); - ClassDB::bind_method(D_METHOD("_unhandled_input"), &BaseButton::_unhandled_input); + ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &BaseButton::_unhandled_key_input); ClassDB::bind_method(D_METHOD("set_pressed", "pressed"), &BaseButton::set_pressed); ClassDB::bind_method(D_METHOD("is_pressed"), &BaseButton::is_pressed); ClassDB::bind_method(D_METHOD("is_hovered"), &BaseButton::is_hovered); @@ -386,6 +416,9 @@ void BaseButton::_bind_methods() { ClassDB::bind_method(D_METHOD("set_button_group", "button_group"), &BaseButton::set_button_group); ClassDB::bind_method(D_METHOD("get_button_group"), &BaseButton::get_button_group); + ClassDB::bind_method(D_METHOD("set_shortcut_context", "node"), &BaseButton::set_shortcut_context); + ClassDB::bind_method(D_METHOD("get_shortcut_context"), &BaseButton::get_shortcut_context); + BIND_VMETHOD(MethodInfo("_pressed")); BIND_VMETHOD(MethodInfo("_toggled", PropertyInfo(Variant::BOOL, "button_pressed"))); @@ -425,6 +458,7 @@ BaseButton::BaseButton() { set_focus_mode(FOCUS_ALL); action_mode = ACTION_MODE_BUTTON_RELEASE; button_mask = BUTTON_MASK_LEFT; + shortcut_context = ObjectID(); } BaseButton::~BaseButton() { diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index 33f19949cd..661801216d 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -50,6 +50,7 @@ private: bool shortcut_in_tooltip; bool keep_pressed_outside; Ref<Shortcut> shortcut; + ObjectID shortcut_context; ActionMode action_mode; struct Status { @@ -75,9 +76,11 @@ protected: virtual void toggled(bool p_pressed); static void _bind_methods(); virtual void _gui_input(Ref<InputEvent> p_event); - virtual void _unhandled_input(Ref<InputEvent> p_event); + virtual void _unhandled_key_input(Ref<InputEvent> p_event); void _notification(int p_what); + bool _is_focus_owner_in_shorcut_context() const; + public: enum DrawMode { DRAW_NORMAL, @@ -122,6 +125,9 @@ public: void set_button_group(const Ref<ButtonGroup> &p_group); Ref<ButtonGroup> get_button_group() const; + void set_shortcut_context(Node *p_node); + Node *get_shortcut_context() const; + BaseButton(); ~BaseButton(); }; diff --git a/scene/gui/control.cpp b/scene/gui/control.cpp index f9b7d828f4..46c3a44e98 100644 --- a/scene/gui/control.cpp +++ b/scene/gui/control.cpp @@ -2983,6 +2983,7 @@ void Control::_bind_methods() { BIND_VMETHOD(MethodInfo("_structured_text_parser", PropertyInfo(Variant::ARRAY, "args"), PropertyInfo(Variant::STRING, "text"))); BIND_VMETHOD(MethodInfo("_gui_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); + BIND_VMETHOD(MethodInfo("_unhandled_key_input", PropertyInfo(Variant::OBJECT, "event", PROPERTY_HINT_RESOURCE_TYPE, "InputEvent"))); BIND_VMETHOD(MethodInfo(Variant::VECTOR2, "_get_minimum_size")); MethodInfo get_drag_data = MethodInfo("get_drag_data", PropertyInfo(Variant::VECTOR2, "position")); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index d65e98ea46..b98b3f7094 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -34,6 +34,10 @@ #include "scene/main/window.h" void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) { + if (!_is_focus_owner_in_shorcut_context()) { + return; + } + if (disable_shortcuts) { return; } @@ -43,9 +47,6 @@ void MenuButton::_unhandled_key_input(Ref<InputEvent> p_event) { return; } - //bool global_only = (get_viewport()->get_modal_stack_top() && !get_viewport()->get_modal_stack_top()->is_a_parent_of(this)); - //if (popup->activate_item_by_event(p_event, global_only)) - // accept_event(); if (popup->activate_item_by_event(p_event, false)) { accept_event(); } @@ -100,7 +101,6 @@ void MenuButton::_notification(int p_what) { void MenuButton::_bind_methods() { ClassDB::bind_method(D_METHOD("get_popup"), &MenuButton::get_popup); - ClassDB::bind_method(D_METHOD("_unhandled_key_input"), &MenuButton::_unhandled_key_input); ClassDB::bind_method(D_METHOD("_set_items"), &MenuButton::_set_items); ClassDB::bind_method(D_METHOD("_get_items"), &MenuButton::_get_items); ClassDB::bind_method(D_METHOD("set_switch_on_hover", "enable"), &MenuButton::set_switch_on_hover); @@ -123,6 +123,7 @@ MenuButton::MenuButton() { set_toggle_mode(true); set_disable_shortcuts(false); set_process_unhandled_key_input(true); + set_focus_mode(FOCUS_NONE); set_action_mode(ACTION_MODE_BUTTON_PRESS); popup = memnew(PopupMenu); diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index 6330899ad3..65b46d5b69 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -42,7 +42,6 @@ class MenuButton : public Button { bool disable_shortcuts; PopupMenu *popup; - void _unhandled_key_input(Ref<InputEvent> p_event); Array _get_items() const; void _set_items(const Array &p_items); @@ -51,6 +50,7 @@ class MenuButton : public Button { protected: void _notification(int p_what); static void _bind_methods(); + virtual void _unhandled_key_input(Ref<InputEvent> p_event) override; public: virtual void pressed() override; |