diff options
author | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-01-11 15:59:52 +0200 |
---|---|---|
committer | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-04-05 13:46:45 +0300 |
commit | d1207a0504329ea4da17753697785e227f53328e (patch) | |
tree | 04df5069927adf08dbffa30f05bcfaada43a119d /scene | |
parent | 479143ab2a6917bb696568a1daccd9466defd167 (diff) |
[Input] Add extra `shortcut_input` input processing step to process Unicode character input with Alt / Ctrl modifiers, after processing of shortcuts.
Diffstat (limited to 'scene')
-rw-r--r-- | scene/gui/base_button.cpp | 4 | ||||
-rw-r--r-- | scene/gui/base_button.h | 2 | ||||
-rw-r--r-- | scene/gui/file_dialog.cpp | 6 | ||||
-rw-r--r-- | scene/gui/file_dialog.h | 2 | ||||
-rw-r--r-- | scene/gui/line_edit.cpp | 22 | ||||
-rw-r--r-- | scene/gui/line_edit.h | 1 | ||||
-rw-r--r-- | scene/gui/menu_button.cpp | 4 | ||||
-rw-r--r-- | scene/gui/menu_button.h | 2 | ||||
-rw-r--r-- | scene/gui/text_edit.cpp | 16 | ||||
-rw-r--r-- | scene/gui/text_edit.h | 1 | ||||
-rw-r--r-- | scene/main/node.cpp | 46 | ||||
-rw-r--r-- | scene/main/node.h | 7 | ||||
-rw-r--r-- | scene/main/scene_tree.cpp | 3 | ||||
-rw-r--r-- | scene/main/scene_tree.h | 1 | ||||
-rw-r--r-- | scene/main/viewport.cpp | 14 | ||||
-rw-r--r-- | scene/main/viewport.h | 1 |
16 files changed, 119 insertions, 13 deletions
diff --git a/scene/gui/base_button.cpp b/scene/gui/base_button.cpp index ab86face7e..789c01adf3 100644 --- a/scene/gui/base_button.cpp +++ b/scene/gui/base_button.cpp @@ -339,14 +339,14 @@ bool BaseButton::is_keep_pressed_outside() const { void BaseButton::set_shortcut(const Ref<Shortcut> &p_shortcut) { shortcut = p_shortcut; - set_process_unhandled_key_input(shortcut.is_valid()); + set_process_shortcut_input(shortcut.is_valid()); } Ref<Shortcut> BaseButton::get_shortcut() const { return shortcut; } -void BaseButton::unhandled_key_input(const Ref<InputEvent> &p_event) { +void BaseButton::shortcut_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); if (!_is_focus_owner_in_shortcut_context()) { diff --git a/scene/gui/base_button.h b/scene/gui/base_button.h index a2b6ee0845..f4f9b88868 100644 --- a/scene/gui/base_button.h +++ b/scene/gui/base_button.h @@ -77,7 +77,7 @@ protected: virtual void toggled(bool p_pressed); static void _bind_methods(); virtual void gui_input(const Ref<InputEvent> &p_event) override; - virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; + virtual void shortcut_input(const Ref<InputEvent> &p_event) override; void _notification(int p_what); bool _is_focus_owner_in_shortcut_context() const; diff --git a/scene/gui/file_dialog.cpp b/scene/gui/file_dialog.cpp index e71ab64535..5e74658470 100644 --- a/scene/gui/file_dialog.cpp +++ b/scene/gui/file_dialog.cpp @@ -95,7 +95,7 @@ void FileDialog::_notification(int p_what) { switch (p_what) { case NOTIFICATION_VISIBILITY_CHANGED: { if (!is_visible()) { - set_process_unhandled_input(false); + set_process_shortcut_input(false); } } break; @@ -119,7 +119,7 @@ void FileDialog::_notification(int p_what) { } } -void FileDialog::unhandled_input(const Ref<InputEvent> &p_event) { +void FileDialog::shortcut_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); Ref<InputEventKey> k = p_event; @@ -217,7 +217,7 @@ void FileDialog::_post_popup() { tree->grab_focus(); } - set_process_unhandled_input(true); + set_process_shortcut_input(true); // For open dir mode, deselect all items on file dialog open. if (mode == FILE_MODE_OPEN_DIR) { diff --git a/scene/gui/file_dialog.h b/scene/gui/file_dialog.h index 9bba93bb89..b41a08c6c7 100644 --- a/scene/gui/file_dialog.h +++ b/scene/gui/file_dialog.h @@ -133,7 +133,7 @@ private: void _update_drives(bool p_select = true); - virtual void unhandled_input(const Ref<InputEvent> &p_event) override; + virtual void shortcut_input(const Ref<InputEvent> &p_event) override; bool _is_open_should_be_disabled(); diff --git a/scene/gui/line_edit.cpp b/scene/gui/line_edit.cpp index e063d3aeba..b3f051bb75 100644 --- a/scene/gui/line_edit.cpp +++ b/scene/gui/line_edit.cpp @@ -215,6 +215,27 @@ void LineEdit::_delete(bool p_word, bool p_all_to_right) { } } +void LineEdit::unhandled_key_input(const Ref<InputEvent> &p_event) { + Ref<InputEventKey> k = p_event; + + if (k.is_valid()) { + if (!k->is_pressed()) { + return; + } + // Handle Unicode (with modifiers active, process after shortcuts). + if (has_focus() && editable && (k->get_unicode() >= 32)) { + selection_delete(); + char32_t ucodestr[2] = { (char32_t)k->get_unicode(), 0 }; + int prev_len = text.length(); + insert_text_at_caret(ucodestr); + if (text.length() != prev_len) { + _text_changed(); + } + accept_event(); + } + } +} + void LineEdit::gui_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); @@ -2445,6 +2466,7 @@ LineEdit::LineEdit(const String &p_placeholder) { set_focus_mode(FOCUS_ALL); set_default_cursor_shape(CURSOR_IBEAM); set_mouse_filter(MOUSE_FILTER_STOP); + set_process_unhandled_key_input(true); caret_blink_timer = memnew(Timer); add_child(caret_blink_timer, false, INTERNAL_MODE_FRONT); diff --git a/scene/gui/line_edit.h b/scene/gui/line_edit.h index 444c9a1c50..b86ccd6421 100644 --- a/scene/gui/line_edit.h +++ b/scene/gui/line_edit.h @@ -202,6 +202,7 @@ private: protected: void _notification(int p_what); static void _bind_methods(); + virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; virtual void gui_input(const Ref<InputEvent> &p_event) override; bool _set(const StringName &p_name, const Variant &p_value); diff --git a/scene/gui/menu_button.cpp b/scene/gui/menu_button.cpp index 7e724e4d71..1feee017c2 100644 --- a/scene/gui/menu_button.cpp +++ b/scene/gui/menu_button.cpp @@ -33,7 +33,7 @@ #include "core/os/keyboard.h" #include "scene/main/window.h" -void MenuButton::unhandled_key_input(const Ref<InputEvent> &p_event) { +void MenuButton::shortcut_input(const Ref<InputEvent> &p_event) { ERR_FAIL_COND(p_event.is_null()); if (!_is_focus_owner_in_shortcut_context()) { @@ -232,7 +232,7 @@ MenuButton::MenuButton(const String &p_text) : set_flat(true); set_toggle_mode(true); set_disable_shortcuts(false); - set_process_unhandled_key_input(true); + set_process_shortcut_input(true); set_focus_mode(FOCUS_NONE); set_action_mode(ACTION_MODE_BUTTON_PRESS); diff --git a/scene/gui/menu_button.h b/scene/gui/menu_button.h index e3ead9c291..0a6b46c796 100644 --- a/scene/gui/menu_button.h +++ b/scene/gui/menu_button.h @@ -54,7 +54,7 @@ protected: bool _get(const StringName &p_name, Variant &r_ret) const; void _get_property_list(List<PropertyInfo> *p_list) const; static void _bind_methods(); - virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; + virtual void shortcut_input(const Ref<InputEvent> &p_event) override; public: virtual void pressed() override; diff --git a/scene/gui/text_edit.cpp b/scene/gui/text_edit.cpp index 1f49491eb8..86969e3ef4 100644 --- a/scene/gui/text_edit.cpp +++ b/scene/gui/text_edit.cpp @@ -1542,6 +1542,21 @@ void TextEdit::_notification(int p_what) { } } +void TextEdit::unhandled_key_input(const Ref<InputEvent> &p_event) { + Ref<InputEventKey> k = p_event; + + if (k.is_valid()) { + if (!k->is_pressed()) { + return; + } + // Handle Unicode (with modifiers active, process after shortcuts). + if (has_focus() && editable && (k->get_unicode() >= 32)) { + handle_unicode_input(k->get_unicode()); + accept_event(); + } + } +} + void TextEdit::gui_input(const Ref<InputEvent> &p_gui_input) { ERR_FAIL_COND(p_gui_input.is_null()); @@ -6620,6 +6635,7 @@ TextEdit::TextEdit(const String &p_placeholder) { set_focus_mode(FOCUS_ALL); _update_caches(); set_default_cursor_shape(CURSOR_IBEAM); + set_process_unhandled_key_input(true); text.set_tab_size(text.get_tab_size()); diff --git a/scene/gui/text_edit.h b/scene/gui/text_edit.h index 7d36051a37..b365e9c61c 100644 --- a/scene/gui/text_edit.h +++ b/scene/gui/text_edit.h @@ -623,6 +623,7 @@ protected: public: /* General overrides. */ + virtual void unhandled_key_input(const Ref<InputEvent> &p_event) override; virtual void gui_input(const Ref<InputEvent> &p_gui_input) override; virtual Size2 get_minimum_size() const override; virtual bool is_text_field() const override; diff --git a/scene/main/node.cpp b/scene/main/node.cpp index 7933045c5f..34bb1cde05 100644 --- a/scene/main/node.cpp +++ b/scene/main/node.cpp @@ -79,6 +79,9 @@ void Node::_notification(int p_notification) { if (data.input) { add_to_group("_vp_input" + itos(get_viewport()->get_instance_id())); } + if (data.shortcut_input) { + add_to_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id())); + } if (data.unhandled_input) { add_to_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id())); } @@ -100,6 +103,9 @@ void Node::_notification(int p_notification) { if (data.input) { remove_from_group("_vp_input" + itos(get_viewport()->get_instance_id())); } + if (data.shortcut_input) { + remove_from_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id())); + } if (data.unhandled_input) { remove_from_group("_vp_unhandled_input" + itos(get_viewport()->get_instance_id())); } @@ -126,6 +132,10 @@ void Node::_notification(int p_notification) { set_process_input(true); } + if (GDVIRTUAL_IS_OVERRIDDEN(_shortcut_input)) { + set_process_shortcut_input(true); + } + if (GDVIRTUAL_IS_OVERRIDDEN(_unhandled_input)) { set_process_unhandled_input(true); } @@ -835,6 +845,26 @@ bool Node::is_processing_input() const { return data.input; } +void Node::set_process_shortcut_input(bool p_enable) { + if (p_enable == data.shortcut_input) { + return; + } + data.shortcut_input = p_enable; + if (!is_inside_tree()) { + return; + } + + if (p_enable) { + add_to_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id())); + } else { + remove_from_group("_vp_shortcut_input" + itos(get_viewport()->get_instance_id())); + } +} + +bool Node::is_processing_shortcut_input() const { + return data.shortcut_input; +} + void Node::set_process_unhandled_input(bool p_enable) { if (p_enable == data.unhandled_input) { return; @@ -2615,6 +2645,15 @@ void Node::_call_input(const Ref<InputEvent> &p_event) { } input(p_event); } + +void Node::_call_shortcut_input(const Ref<InputEvent> &p_event) { + GDVIRTUAL_CALL(_shortcut_input, p_event); + if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) { + return; + } + shortcut_input(p_event); +} + void Node::_call_unhandled_input(const Ref<InputEvent> &p_event) { GDVIRTUAL_CALL(_unhandled_input, p_event); if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) { @@ -2622,6 +2661,7 @@ void Node::_call_unhandled_input(const Ref<InputEvent> &p_event) { } unhandled_input(p_event); } + void Node::_call_unhandled_key_input(const Ref<InputEvent> &p_event) { GDVIRTUAL_CALL(_unhandled_key_input, p_event); if (!is_inside_tree() || !get_viewport() || get_viewport()->is_input_handled()) { @@ -2633,6 +2673,9 @@ void Node::_call_unhandled_key_input(const Ref<InputEvent> &p_event) { void Node::input(const Ref<InputEvent> &p_event) { } +void Node::shortcut_input(const Ref<InputEvent> &p_key_event) { +} + void Node::unhandled_input(const Ref<InputEvent> &p_event) { } @@ -2694,6 +2737,8 @@ void Node::_bind_methods() { ClassDB::bind_method(D_METHOD("is_processing"), &Node::is_processing); ClassDB::bind_method(D_METHOD("set_process_input", "enable"), &Node::set_process_input); ClassDB::bind_method(D_METHOD("is_processing_input"), &Node::is_processing_input); + ClassDB::bind_method(D_METHOD("set_process_shortcut_input", "enable"), &Node::set_process_shortcut_input); + ClassDB::bind_method(D_METHOD("is_processing_shortcut_input"), &Node::is_processing_shortcut_input); ClassDB::bind_method(D_METHOD("set_process_unhandled_input", "enable"), &Node::set_process_unhandled_input); ClassDB::bind_method(D_METHOD("is_processing_unhandled_input"), &Node::is_processing_unhandled_input); ClassDB::bind_method(D_METHOD("set_process_unhandled_key_input", "enable"), &Node::set_process_unhandled_key_input); @@ -2854,6 +2899,7 @@ void Node::_bind_methods() { GDVIRTUAL_BIND(_ready); GDVIRTUAL_BIND(_get_configuration_warnings); GDVIRTUAL_BIND(_input, "event"); + GDVIRTUAL_BIND(_shortcut_input, "event"); GDVIRTUAL_BIND(_unhandled_input, "event"); GDVIRTUAL_BIND(_unhandled_key_input, "event"); } diff --git a/scene/main/node.h b/scene/main/node.h index 1f973a0cb4..57b150e29a 100644 --- a/scene/main/node.h +++ b/scene/main/node.h @@ -136,6 +136,7 @@ private: bool process_internal = false; bool input = false; + bool shortcut_input = false; bool unhandled_input = false; bool unhandled_key_input = false; @@ -215,11 +216,13 @@ protected: //call from SceneTree void _call_input(const Ref<InputEvent> &p_event); + void _call_shortcut_input(const Ref<InputEvent> &p_event); void _call_unhandled_input(const Ref<InputEvent> &p_event); void _call_unhandled_key_input(const Ref<InputEvent> &p_event); protected: virtual void input(const Ref<InputEvent> &p_event); + virtual void shortcut_input(const Ref<InputEvent> &p_key_event); virtual void unhandled_input(const Ref<InputEvent> &p_event); virtual void unhandled_key_input(const Ref<InputEvent> &p_key_event); @@ -231,6 +234,7 @@ protected: GDVIRTUAL0RC(Vector<String>, _get_configuration_warnings) GDVIRTUAL1(_input, Ref<InputEvent>) + GDVIRTUAL1(_shortcut_input, Ref<InputEvent>) GDVIRTUAL1(_unhandled_input, Ref<InputEvent>) GDVIRTUAL1(_unhandled_key_input, Ref<InputEvent>) @@ -395,6 +399,9 @@ public: void set_process_input(bool p_enable); bool is_processing_input() const; + void set_process_shortcut_input(bool p_enable); + bool is_processing_shortcut_input() const; + void set_process_unhandled_input(bool p_enable); bool is_processing_unhandled_input() const; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 8eeedf51a9..d005633bb5 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -897,6 +897,9 @@ void SceneTree::_call_input_pause(const StringName &p_group, CallInputType p_cal case CALL_INPUT_TYPE_INPUT: n->_call_input(p_input); break; + case CALL_INPUT_TYPE_SHORTCUT_INPUT: + n->_call_shortcut_input(p_input); + break; case CALL_INPUT_TYPE_UNHANDLED_INPUT: n->_call_unhandled_input(p_input); break; diff --git a/scene/main/scene_tree.h b/scene/main/scene_tree.h index 0f8cbedb41..705ca6ebd3 100644 --- a/scene/main/scene_tree.h +++ b/scene/main/scene_tree.h @@ -204,6 +204,7 @@ private: enum CallInputType { CALL_INPUT_TYPE_INPUT, + CALL_INPUT_TYPE_SHORTCUT_INPUT, CALL_INPUT_TYPE_UNHANDLED_INPUT, CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, }; diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index a38bed71d1..e20287c875 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2744,11 +2744,18 @@ void Viewport::push_unhandled_input(const Ref<InputEvent> &p_event, bool p_local ev = p_event; } + // Shortcut Input. + if (Object::cast_to<InputEventKey>(*ev) != nullptr || Object::cast_to<InputEventShortcut>(*ev) != nullptr) { + get_tree()->_call_input_pause(shortcut_input_group, SceneTree::CALL_INPUT_TYPE_SHORTCUT_INPUT, ev, this); + } + // Unhandled Input. - get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, ev, this); + if (!is_input_handled()) { + get_tree()->_call_input_pause(unhandled_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_INPUT, ev, this); + } - // Unhandled key Input - used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, etc. - if (!is_input_handled() && (Object::cast_to<InputEventKey>(*ev) != nullptr || Object::cast_to<InputEventShortcut>(*ev) != nullptr)) { + // Unhandled key Input - Used for performance reasons - This is called a lot less than _unhandled_input since it ignores MouseMotion, and to handle Unicode input with Alt / Ctrl modifiers after handling shortcuts. + if (!is_input_handled() && (Object::cast_to<InputEventKey>(*ev) != nullptr)) { get_tree()->_call_input_pause(unhandled_key_input_group, SceneTree::CALL_INPUT_TYPE_UNHANDLED_KEY_INPUT, ev, this); } @@ -3879,6 +3886,7 @@ Viewport::Viewport() { input_group = "_vp_input" + id; gui_input_group = "_vp_gui_input" + id; unhandled_input_group = "_vp_unhandled_input" + id; + shortcut_input_group = "_vp_shortcut_input" + id; unhandled_key_input_group = "_vp_unhandled_key_input" + id; // Window tooltip. diff --git a/scene/main/viewport.h b/scene/main/viewport.h index 80be53fab8..32882fbb68 100644 --- a/scene/main/viewport.h +++ b/scene/main/viewport.h @@ -270,6 +270,7 @@ private: Rect2i to_screen_rect; StringName input_group; StringName gui_input_group; + StringName shortcut_input_group; StringName unhandled_input_group; StringName unhandled_key_input_group; |