diff options
author | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2022-12-11 01:21:22 +0200 |
---|---|---|
committer | bruvzg <7645683+bruvzg@users.noreply.github.com> | 2023-01-23 15:08:12 +0200 |
commit | daad4aed62bfa471421f960179f0ac0fd78e8040 (patch) | |
tree | 86b7f69d180f253c51c4b567139d68850f9e365d /core/input | |
parent | 9937915ad77059b63582ffd4e324afb26f467b76 (diff) |
Cleanup and unify keyboard input.
- Unify keycode values (secondary label printed on a key), remove unused hardcoded Latin-1 codes.
- Unify IME behaviour, add inline composition string display on Windows and X11.
- Add key_label (localized label printed on a key) value to the key events, and allow mapping actions to the unshifted Unicode events.
- Add support for physical keyboard (Bluetooth or Sidecar) handling on iOS.
- Add support for media key handling on macOS.
Co-authored-by: Raul Santos <raulsntos@gmail.com>
Diffstat (limited to 'core/input')
-rw-r--r-- | core/input/input.cpp | 14 | ||||
-rw-r--r-- | core/input/input.h | 2 | ||||
-rw-r--r-- | core/input/input_event.cpp | 115 | ||||
-rw-r--r-- | core/input/input_event.h | 8 |
4 files changed, 129 insertions, 10 deletions
diff --git a/core/input/input.cpp b/core/input/input.cpp index 0afa004515..1ea9f00fee 100644 --- a/core/input/input.cpp +++ b/core/input/input.cpp @@ -93,6 +93,7 @@ void Input::_bind_methods() { ClassDB::bind_method(D_METHOD("is_anything_pressed"), &Input::is_anything_pressed); ClassDB::bind_method(D_METHOD("is_key_pressed", "keycode"), &Input::is_key_pressed); ClassDB::bind_method(D_METHOD("is_physical_key_pressed", "keycode"), &Input::is_physical_key_pressed); + ClassDB::bind_method(D_METHOD("is_key_label_pressed", "keycode"), &Input::is_key_label_pressed); ClassDB::bind_method(D_METHOD("is_mouse_button_pressed", "button"), &Input::is_mouse_button_pressed); ClassDB::bind_method(D_METHOD("is_joy_button_pressed", "device", "button"), &Input::is_joy_button_pressed); ClassDB::bind_method(D_METHOD("is_action_pressed", "action", "exact_match"), &Input::is_action_pressed, DEFVAL(false)); @@ -250,6 +251,11 @@ bool Input::is_physical_key_pressed(Key p_keycode) const { return physical_keys_pressed.has(p_keycode); } +bool Input::is_key_label_pressed(Key p_keycode) const { + _THREAD_SAFE_METHOD_ + return key_label_pressed.has(p_keycode); +} + bool Input::is_mouse_button_pressed(MouseButton p_button) const { _THREAD_SAFE_METHOD_ return mouse_button_mask.has_flag(mouse_button_to_mask(p_button)); @@ -499,6 +505,13 @@ void Input::_parse_input_event_impl(const Ref<InputEvent> &p_event, bool p_is_em physical_keys_pressed.erase(k->get_physical_keycode()); } } + if (k.is_valid() && !k->is_echo() && k->get_key_label() != Key::NONE) { + if (k->is_pressed()) { + key_label_pressed.insert(k->get_key_label()); + } else { + key_label_pressed.erase(k->get_key_label()); + } + } Ref<InputEventMouseButton> mb = p_event; @@ -919,6 +932,7 @@ void Input::release_pressed_events() { keys_pressed.clear(); physical_keys_pressed.clear(); + key_label_pressed.clear(); joy_buttons_pressed.clear(); _joy_axis.clear(); diff --git a/core/input/input.h b/core/input/input.h index 0915588700..f2de56b6b9 100644 --- a/core/input/input.h +++ b/core/input/input.h @@ -84,6 +84,7 @@ public: private: BitField<MouseButtonMask> mouse_button_mask; + RBSet<Key> key_label_pressed; RBSet<Key> physical_keys_pressed; RBSet<Key> keys_pressed; RBSet<JoyButton> joy_buttons_pressed; @@ -247,6 +248,7 @@ public: bool is_anything_pressed() const; bool is_key_pressed(Key p_keycode) const; bool is_physical_key_pressed(Key p_keycode) const; + bool is_key_label_pressed(Key p_keycode) const; bool is_mouse_button_pressed(MouseButton p_button) const; bool is_joy_button_pressed(int p_device, JoyButton p_button) const; bool is_action_pressed(const StringName &p_action, bool p_exact = false) const; diff --git a/core/input/input_event.cpp b/core/input/input_event.cpp index 0dd7fdc19b..dbe9b55ee3 100644 --- a/core/input/input_event.cpp +++ b/core/input/input_event.cpp @@ -285,6 +285,8 @@ void InputEventWithModifiers::_bind_methods() { ClassDB::bind_method(D_METHOD("set_meta_pressed", "pressed"), &InputEventWithModifiers::set_meta_pressed); ClassDB::bind_method(D_METHOD("is_meta_pressed"), &InputEventWithModifiers::is_meta_pressed); + ClassDB::bind_method(D_METHOD("get_modifiers_mask"), &InputEventWithModifiers::get_modifiers_mask); + ADD_PROPERTY(PropertyInfo(Variant::BOOL, "command_or_control_autoremap"), "set_command_or_control_autoremap", "is_command_or_control_autoremap"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "alt_pressed"), "set_alt_pressed", "is_alt_pressed"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "shift_pressed"), "set_shift_pressed", "is_shift_pressed"); @@ -328,6 +330,15 @@ Key InputEventKey::get_keycode() const { return keycode; } +void InputEventKey::set_key_label(Key p_key_label) { + key_label = p_key_label; + emit_changed(); +} + +Key InputEventKey::get_key_label() const { + return key_label; +} + void InputEventKey::set_physical_keycode(Key p_keycode) { physical_keycode = p_keycode; emit_changed(); @@ -363,13 +374,72 @@ Key InputEventKey::get_physical_keycode_with_modifiers() const { return physical_keycode | (int64_t)get_modifiers_mask(); } +Key InputEventKey::get_key_label_with_modifiers() const { + return key_label | get_modifiers_mask(); +} + +String InputEventKey::as_text_physical_keycode() const { + String kc; + + if (physical_keycode != Key::NONE) { + kc = keycode_get_string(physical_keycode); + } else { + kc = "(" + RTR("Unset") + ")"; + } + + if (kc.is_empty()) { + return kc; + } + + String mods_text = InputEventWithModifiers::as_text(); + return mods_text.is_empty() ? kc : mods_text + "+" + kc; +} + +String InputEventKey::as_text_keycode() const { + String kc; + + if (keycode != Key::NONE) { + kc = keycode_get_string(keycode); + } else { + kc = "(" + RTR("Unset") + ")"; + } + + if (kc.is_empty()) { + return kc; + } + + String mods_text = InputEventWithModifiers::as_text(); + return mods_text.is_empty() ? kc : mods_text + "+" + kc; +} + +String InputEventKey::as_text_key_label() const { + String kc; + + if (key_label != Key::NONE) { + kc = keycode_get_string(key_label); + } else { + kc = "(" + RTR("Unset") + ")"; + } + + if (kc.is_empty()) { + return kc; + } + + String mods_text = InputEventWithModifiers::as_text(); + return mods_text.is_empty() ? kc : mods_text + "+" + kc; +} + String InputEventKey::as_text() const { String kc; - if (keycode == Key::NONE) { + if (keycode == Key::NONE && physical_keycode == Key::NONE && key_label != Key::NONE) { + kc = keycode_get_string(key_label) + " (Unicode)"; + } else if (keycode != Key::NONE) { + kc = keycode_get_string(keycode); + } else if (physical_keycode != Key::NONE) { kc = keycode_get_string(physical_keycode) + " (" + RTR("Physical") + ")"; } else { - kc = keycode_get_string(keycode); + kc = "(" + RTR("Unset") + ")"; } if (kc.is_empty()) { @@ -386,11 +456,16 @@ String InputEventKey::to_string() { String kc = ""; String physical = "false"; - if (keycode == Key::NONE) { + + if (keycode == Key::NONE && physical_keycode == Key::NONE && unicode != 0) { + kc = "U+" + String::num_uint64(unicode, 16) + " (" + String::chr(unicode) + ")"; + } else if (keycode != Key::NONE) { + kc = itos((int64_t)keycode) + " (" + keycode_get_string(keycode) + ")"; + } else if (physical_keycode != Key::NONE) { kc = itos((int64_t)physical_keycode) + " (" + keycode_get_string(physical_keycode) + ")"; physical = "true"; } else { - kc = itos((int64_t)keycode) + " (" + keycode_get_string(keycode) + ")"; + kc = "(" + RTR("Unset") + ")"; } String mods = InputEventWithModifiers::as_text(); @@ -403,6 +478,7 @@ Ref<InputEventKey> InputEventKey::create_reference(Key p_keycode) { Ref<InputEventKey> ie; ie.instantiate(); ie->set_keycode(p_keycode & KeyModifierMask::CODE_MASK); + ie->set_key_label(p_keycode & KeyModifierMask::CODE_MASK); ie->set_unicode(char32_t(p_keycode & KeyModifierMask::CODE_MASK)); if ((p_keycode & KeyModifierMask::SHIFT) != Key::NONE) { @@ -435,11 +511,16 @@ bool InputEventKey::action_match(const Ref<InputEvent> &p_event, bool p_exact_ma } bool match; - if (keycode != Key::NONE) { + if (keycode == Key::NONE && physical_keycode == Key::NONE && key_label != Key::NONE) { + match = key_label == key->key_label; + } else if (keycode != Key::NONE) { match = keycode == key->keycode; + } else if (physical_keycode != Key::NONE) { + match = physical_keycode == key->physical_keycode; } else { - match = get_physical_keycode() == key->get_physical_keycode(); + match = false; } + Key action_mask = (Key)(int64_t)get_modifiers_mask(); Key key_mask = (Key)(int64_t)key->get_modifiers_mask(); if (key->is_pressed()) { @@ -470,12 +551,17 @@ bool InputEventKey::is_match(const Ref<InputEvent> &p_event, bool p_exact_match) return false; } - if (keycode == Key::NONE) { - return physical_keycode == key->physical_keycode && + if (keycode == Key::NONE && physical_keycode == Key::NONE && key_label != Key::NONE) { + return (key_label == key->key_label) && (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask()); - } else { - return keycode == key->keycode && + } else if (keycode != Key::NONE) { + return (keycode == key->keycode) && (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask()); + } else if (physical_keycode != Key::NONE) { + return (physical_keycode == key->physical_keycode) && + (!p_exact_match || get_modifiers_mask() == key->get_modifiers_mask()); + } else { + return false; } } @@ -488,6 +574,9 @@ void InputEventKey::_bind_methods() { ClassDB::bind_method(D_METHOD("set_physical_keycode", "physical_keycode"), &InputEventKey::set_physical_keycode); ClassDB::bind_method(D_METHOD("get_physical_keycode"), &InputEventKey::get_physical_keycode); + ClassDB::bind_method(D_METHOD("set_key_label", "key_label"), &InputEventKey::set_key_label); + ClassDB::bind_method(D_METHOD("get_key_label"), &InputEventKey::get_key_label); + ClassDB::bind_method(D_METHOD("set_unicode", "unicode"), &InputEventKey::set_unicode); ClassDB::bind_method(D_METHOD("get_unicode"), &InputEventKey::get_unicode); @@ -495,10 +584,16 @@ void InputEventKey::_bind_methods() { ClassDB::bind_method(D_METHOD("get_keycode_with_modifiers"), &InputEventKey::get_keycode_with_modifiers); ClassDB::bind_method(D_METHOD("get_physical_keycode_with_modifiers"), &InputEventKey::get_physical_keycode_with_modifiers); + ClassDB::bind_method(D_METHOD("get_key_label_with_modifiers"), &InputEventKey::get_key_label_with_modifiers); + + ClassDB::bind_method(D_METHOD("as_text_keycode"), &InputEventKey::as_text_keycode); + ClassDB::bind_method(D_METHOD("as_text_physical_keycode"), &InputEventKey::as_text_physical_keycode); + ClassDB::bind_method(D_METHOD("as_text_key_label"), &InputEventKey::as_text_key_label); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "pressed"), "set_pressed", "is_pressed"); ADD_PROPERTY(PropertyInfo(Variant::INT, "keycode"), "set_keycode", "get_keycode"); ADD_PROPERTY(PropertyInfo(Variant::INT, "physical_keycode"), "set_physical_keycode", "get_physical_keycode"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "key_label"), "set_key_label", "get_key_label"); ADD_PROPERTY(PropertyInfo(Variant::INT, "unicode"), "set_unicode", "get_unicode"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "echo"), "set_echo", "is_echo"); } diff --git a/core/input/input_event.h b/core/input/input_event.h index 2d7a72e327..797761b208 100644 --- a/core/input/input_event.h +++ b/core/input/input_event.h @@ -153,6 +153,7 @@ class InputEventKey : public InputEventWithModifiers { Key keycode = Key::NONE; // Key enum, without modifier masks. Key physical_keycode = Key::NONE; + Key key_label = Key::NONE; uint32_t unicode = 0; ///unicode bool echo = false; /// true if this is an echo key @@ -170,6 +171,9 @@ public: void set_physical_keycode(Key p_keycode); Key get_physical_keycode() const; + void set_key_label(Key p_key_label); + Key get_key_label() const; + void set_unicode(char32_t p_unicode); char32_t get_unicode() const; @@ -178,12 +182,16 @@ public: Key get_keycode_with_modifiers() const; Key get_physical_keycode_with_modifiers() const; + Key get_key_label_with_modifiers() const; virtual bool action_match(const Ref<InputEvent> &p_event, bool p_exact_match, float p_deadzone, bool *r_pressed, float *r_strength, float *r_raw_strength) const override; virtual bool is_match(const Ref<InputEvent> &p_event, bool p_exact_match = true) const override; virtual bool is_action_type() const override { return true; } + virtual String as_text_physical_keycode() const; + virtual String as_text_keycode() const; + virtual String as_text_key_label() const; virtual String as_text() const override; virtual String to_string() override; |