diff options
| author | Rémi Verschelde <rverschelde@gmail.com> | 2024-01-29 13:15:42 +0100 |
|---|---|---|
| committer | Rémi Verschelde <rverschelde@gmail.com> | 2024-01-29 13:15:42 +0100 |
| commit | f220d46cdccb15f1aa141cd89c9dacee85b1b6ec (patch) | |
| tree | bd02a89eb9942b5e6e6b54335ad750661502bc86 /platform | |
| parent | 17e7f85c06366b427e5068c5b3e2940e27ff5f1d (diff) | |
| parent | 8406e60522bb8d09649193be43c1c819edc1d059 (diff) | |
| download | redot-engine-f220d46cdccb15f1aa141cd89c9dacee85b1b6ec.tar.gz | |
Merge pull request #80231 from romlok/input-key-location
Support detecting and mapping ctrl/alt/shift/meta by their left/right physical location
Diffstat (limited to 'platform')
23 files changed, 216 insertions, 15 deletions
diff --git a/platform/android/android_input_handler.cpp b/platform/android/android_input_handler.cpp index bd194478d9..8e7f355114 100644 --- a/platform/android/android_input_handler.cpp +++ b/platform/android/android_input_handler.cpp @@ -124,6 +124,7 @@ void AndroidInputHandler::process_key_event(int p_physical_keycode, int p_unicod ev->set_physical_keycode(physical_keycode); ev->set_key_label(fix_key_label(p_key_label, keycode)); ev->set_unicode(fix_unicode(unicode)); + ev->set_location(godot_location_from_android_code(p_physical_keycode)); ev->set_pressed(p_pressed); ev->set_echo(p_echo); diff --git a/platform/android/android_keys_utils.cpp b/platform/android/android_keys_utils.cpp index f50437e82a..83ee98e8bc 100644 --- a/platform/android/android_keys_utils.cpp +++ b/platform/android/android_keys_utils.cpp @@ -38,3 +38,12 @@ Key godot_code_from_android_code(unsigned int p_code) { } return Key::UNKNOWN; } + +KeyLocation godot_location_from_android_code(unsigned int p_code) { + for (int i = 0; android_godot_location_pairs[i].android_code != AKEYCODE_MAX; i++) { + if (android_godot_location_pairs[i].android_code == p_code) { + return android_godot_location_pairs[i].godot_code; + } + } + return KeyLocation::UNSPECIFIED; +} diff --git a/platform/android/android_keys_utils.h b/platform/android/android_keys_utils.h index 5cf5628a8b..77c0911f2b 100644 --- a/platform/android/android_keys_utils.h +++ b/platform/android/android_keys_utils.h @@ -177,4 +177,24 @@ static AndroidGodotCodePair android_godot_code_pairs[] = { Key godot_code_from_android_code(unsigned int p_code); +// Key location determination. +struct AndroidGodotLocationPair { + unsigned int android_code = 0; + KeyLocation godot_code = KeyLocation::UNSPECIFIED; +}; + +static AndroidGodotLocationPair android_godot_location_pairs[] = { + { AKEYCODE_ALT_LEFT, KeyLocation::LEFT }, + { AKEYCODE_ALT_RIGHT, KeyLocation::RIGHT }, + { AKEYCODE_SHIFT_LEFT, KeyLocation::LEFT }, + { AKEYCODE_SHIFT_RIGHT, KeyLocation::RIGHT }, + { AKEYCODE_CTRL_LEFT, KeyLocation::LEFT }, + { AKEYCODE_CTRL_RIGHT, KeyLocation::RIGHT }, + { AKEYCODE_META_LEFT, KeyLocation::LEFT }, + { AKEYCODE_META_RIGHT, KeyLocation::RIGHT }, + { AKEYCODE_MAX, KeyLocation::UNSPECIFIED } +}; + +KeyLocation godot_location_from_android_code(unsigned int p_code); + #endif // ANDROID_KEYS_UTILS_H diff --git a/platform/ios/display_server_ios.h b/platform/ios/display_server_ios.h index 3d19222fa8..3fdcc07f0b 100644 --- a/platform/ios/display_server_ios.h +++ b/platform/ios/display_server_ios.h @@ -119,7 +119,7 @@ public: // MARK: Keyboard - void key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed); + void key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed, KeyLocation p_location); bool is_keyboard_active() const; // MARK: Motion diff --git a/platform/ios/display_server_ios.mm b/platform/ios/display_server_ios.mm index c31f503605..c660dc5697 100644 --- a/platform/ios/display_server_ios.mm +++ b/platform/ios/display_server_ios.mm @@ -247,7 +247,7 @@ void DisplayServerIOS::touches_canceled(int p_idx) { // MARK: Keyboard -void DisplayServerIOS::key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed) { +void DisplayServerIOS::key(Key p_key, char32_t p_char, Key p_unshifted, Key p_physical, NSInteger p_modifier, bool p_pressed, KeyLocation p_location) { Ref<InputEventKey> ev; ev.instantiate(); ev->set_echo(false); @@ -270,6 +270,7 @@ void DisplayServerIOS::key(Key p_key, char32_t p_char, Key p_unshifted, Key p_ph ev->set_key_label(p_unshifted); ev->set_physical_keycode(p_physical); ev->set_unicode(fix_unicode(p_char)); + ev->set_location(p_location); perform_event(ev); } diff --git a/platform/ios/key_mapping_ios.h b/platform/ios/key_mapping_ios.h index 6cc61175bb..8874da3024 100644 --- a/platform/ios/key_mapping_ios.h +++ b/platform/ios/key_mapping_ios.h @@ -41,6 +41,7 @@ class KeyMappingIOS { public: static void initialize(); static Key remap_key(CFIndex p_keycode); + static KeyLocation key_location(CFIndex p_keycode); }; #endif // KEY_MAPPING_IOS_H diff --git a/platform/ios/key_mapping_ios.mm b/platform/ios/key_mapping_ios.mm index d2c84884d1..61f28aa84b 100644 --- a/platform/ios/key_mapping_ios.mm +++ b/platform/ios/key_mapping_ios.mm @@ -38,6 +38,7 @@ struct HashMapHasherKeys { }; HashMap<CFIndex, Key, HashMapHasherKeys> keyusage_map; +HashMap<CFIndex, KeyLocation, HashMapHasherKeys> location_map; void KeyMappingIOS::initialize() { if (@available(iOS 13.4, *)) { @@ -172,6 +173,15 @@ void KeyMappingIOS::initialize() { keyusage_map[0x029D] = Key::GLOBE; // "Globe" key on smart connector / Mac keyboard. keyusage_map[UIKeyboardHIDUsageKeyboardLANG1] = Key::JIS_EISU; keyusage_map[UIKeyboardHIDUsageKeyboardLANG2] = Key::JIS_KANA; + + location_map[UIKeyboardHIDUsageKeyboardLeftAlt] = KeyLocation::LEFT; + location_map[UIKeyboardHIDUsageKeyboardRightAlt] = KeyLocation::RIGHT; + location_map[UIKeyboardHIDUsageKeyboardLeftControl] = KeyLocation::LEFT; + location_map[UIKeyboardHIDUsageKeyboardRightControl] = KeyLocation::RIGHT; + location_map[UIKeyboardHIDUsageKeyboardLeftShift] = KeyLocation::LEFT; + location_map[UIKeyboardHIDUsageKeyboardRightShift] = KeyLocation::RIGHT; + location_map[UIKeyboardHIDUsageKeyboardLeftGUI] = KeyLocation::LEFT; + location_map[UIKeyboardHIDUsageKeyboardRightGUI] = KeyLocation::RIGHT; } } @@ -184,3 +194,13 @@ Key KeyMappingIOS::remap_key(CFIndex p_keycode) { } return Key::NONE; } + +KeyLocation KeyMappingIOS::key_location(CFIndex p_keycode) { + if (@available(iOS 13.4, *)) { + const KeyLocation *location = location_map.getptr(p_keycode); + if (location) { + return *location; + } + } + return KeyLocation::UNSPECIFIED; +} diff --git a/platform/ios/keyboard_input_view.mm b/platform/ios/keyboard_input_view.mm index bc6eb63ed5..8b614662b7 100644 --- a/platform/ios/keyboard_input_view.mm +++ b/platform/ios/keyboard_input_view.mm @@ -116,8 +116,8 @@ - (void)deleteText:(NSInteger)charactersToDelete { for (int i = 0; i < charactersToDelete; i++) { - DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, true); - DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, false); + DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, true, KeyLocation::UNSPECIFIED); + DisplayServerIOS::get_singleton()->key(Key::BACKSPACE, 0, Key::BACKSPACE, Key::NONE, 0, false, KeyLocation::UNSPECIFIED); } } @@ -137,8 +137,8 @@ key = Key::SPACE; } - DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, true); - DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, false); + DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, true, KeyLocation::UNSPECIFIED); + DisplayServerIOS::get_singleton()->key(key, character, key, Key::NONE, 0, false, KeyLocation::UNSPECIFIED); } } diff --git a/platform/ios/view_controller.mm b/platform/ios/view_controller.mm index 1f55670b68..6f6c04c2c8 100644 --- a/platform/ios/view_controller.mm +++ b/platform/ios/view_controller.mm @@ -78,13 +78,15 @@ us = u32lbl[0]; } + KeyLocation location = KeyMappingIOS::key_location(press.key.keyCode); + if (!u32text.is_empty() && !u32text.begins_with("UIKey")) { for (int i = 0; i < u32text.length(); i++) { const char32_t c = u32text[i]; - DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), c, fix_key_label(us, key), key, press.key.modifierFlags, true); + DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), c, fix_key_label(us, key), key, press.key.modifierFlags, true, location); } } else { - DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, true); + DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, true, location); } } } @@ -110,7 +112,9 @@ us = u32lbl[0]; } - DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, false); + KeyLocation location = KeyMappingIOS::key_location(press.key.keyCode); + + DisplayServerIOS::get_singleton()->key(fix_keycode(us, key), 0, fix_key_label(us, key), key, press.key.modifierFlags, false, location); } } } diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index f49f00e60f..20e2e897f2 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -3512,6 +3512,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, bool keypress = xkeyevent->type == KeyPress; Key keycode = KeyMappingX11::get_keycode(keysym_keycode); Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode); + KeyLocation key_location = KeyMappingX11::get_location(xkeyevent->keycode); if (keycode >= Key::A + 32 && keycode <= Key::Z + 32) { keycode -= 'a' - 'A'; @@ -3549,6 +3550,8 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, k->set_unicode(fix_unicode(tmp[i])); } + k->set_location(key_location); + k->set_echo(false); if (k->get_keycode() == Key::BACKTAB) { @@ -3574,6 +3577,8 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, Key keycode = KeyMappingX11::get_keycode(keysym_keycode); Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode); + KeyLocation key_location = KeyMappingX11::get_location(xkeyevent->keycode); + /* Phase 3, obtain a unicode character from the keysym */ // KeyMappingX11 also translates keysym to unicode. @@ -3673,6 +3678,9 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, if (keypress) { k->set_unicode(fix_unicode(unicode)); } + + k->set_location(key_location); + k->set_echo(p_echo); if (k->get_keycode() == Key::BACKTAB) { diff --git a/platform/linuxbsd/x11/key_mapping_x11.cpp b/platform/linuxbsd/x11/key_mapping_x11.cpp index c0e6b91d57..b589a2a573 100644 --- a/platform/linuxbsd/x11/key_mapping_x11.cpp +++ b/platform/linuxbsd/x11/key_mapping_x11.cpp @@ -1113,6 +1113,20 @@ void KeyMappingX11::initialize() { xkeysym_unicode_map[0x13BD] = 0x0153; xkeysym_unicode_map[0x13BE] = 0x0178; xkeysym_unicode_map[0x20AC] = 0x20AC; + + // Scancode to physical location map. + // Ctrl. + location_map[0x25] = KeyLocation::LEFT; + location_map[0x69] = KeyLocation::RIGHT; + // Shift. + location_map[0x32] = KeyLocation::LEFT; + location_map[0x3E] = KeyLocation::RIGHT; + // Alt. + location_map[0x40] = KeyLocation::LEFT; + location_map[0x6C] = KeyLocation::RIGHT; + // Meta. + location_map[0x85] = KeyLocation::LEFT; + location_map[0x86] = KeyLocation::RIGHT; } Key KeyMappingX11::get_keycode(KeySym p_keysym) { @@ -1173,3 +1187,11 @@ char32_t KeyMappingX11::get_unicode_from_keysym(KeySym p_keysym) { } return 0; } + +KeyLocation KeyMappingX11::get_location(unsigned int p_code) { + const KeyLocation *location = location_map.getptr(p_code); + if (location) { + return *location; + } + return KeyLocation::UNSPECIFIED; +} diff --git a/platform/linuxbsd/x11/key_mapping_x11.h b/platform/linuxbsd/x11/key_mapping_x11.h index ae8fd67f27..a51ee5f48e 100644 --- a/platform/linuxbsd/x11/key_mapping_x11.h +++ b/platform/linuxbsd/x11/key_mapping_x11.h @@ -54,6 +54,7 @@ class KeyMappingX11 { static inline HashMap<unsigned int, Key, HashMapHasherKeys> scancode_map; static inline HashMap<Key, unsigned int, HashMapHasherKeys> scancode_map_inv; static inline HashMap<KeySym, char32_t, HashMapHasherKeys> xkeysym_unicode_map; + static inline HashMap<unsigned int, KeyLocation, HashMapHasherKeys> location_map; KeyMappingX11() {} @@ -64,6 +65,7 @@ public: static unsigned int get_xlibcode(Key p_keysym); static Key get_scancode(unsigned int p_code); static char32_t get_unicode_from_keysym(KeySym p_keysym); + static KeyLocation get_location(unsigned int p_code); }; #endif // KEY_MAPPING_X11_H diff --git a/platform/macos/display_server_macos.h b/platform/macos/display_server_macos.h index cdd17a7e76..24d4a349e2 100644 --- a/platform/macos/display_server_macos.h +++ b/platform/macos/display_server_macos.h @@ -75,6 +75,7 @@ public: Key physical_keycode = Key::NONE; Key key_label = Key::NONE; uint32_t unicode = 0; + KeyLocation location = KeyLocation::UNSPECIFIED; }; struct WindowData { diff --git a/platform/macos/display_server_macos.mm b/platform/macos/display_server_macos.mm index 2bfe16828a..396b943251 100644 --- a/platform/macos/display_server_macos.mm +++ b/platform/macos/display_server_macos.mm @@ -478,6 +478,7 @@ void DisplayServerMacOS::_process_key_events() { k->set_physical_keycode(ke.physical_keycode); k->set_key_label(ke.key_label); k->set_unicode(ke.unicode); + k->set_location(ke.location); _push_input(k); } else { @@ -506,6 +507,7 @@ void DisplayServerMacOS::_process_key_events() { k->set_keycode(ke.keycode); k->set_physical_keycode(ke.physical_keycode); k->set_key_label(ke.key_label); + k->set_location(ke.location); if (i + 1 < key_event_pos && key_event_buffer[i + 1].keycode == Key::NONE) { k->set_unicode(key_event_buffer[i + 1].unicode); diff --git a/platform/macos/godot_content_view.mm b/platform/macos/godot_content_view.mm index 61065291d7..4505becbc2 100644 --- a/platform/macos/godot_content_view.mm +++ b/platform/macos/godot_content_view.mm @@ -606,6 +606,7 @@ ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]); ke.key_label = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true); ke.unicode = 0; + ke.location = KeyMappingMacOS::translate_location([event keyCode]); ke.raw = false; ds->push_to_key_event_buffer(ke); @@ -671,6 +672,7 @@ ke.physical_keycode = KeyMappingMacOS::translate_key(key); ke.key_label = KeyMappingMacOS::remap_key(key, mod, true); ke.unicode = 0; + ke.location = KeyMappingMacOS::translate_location(key); ds->push_to_key_event_buffer(ke); } @@ -698,6 +700,7 @@ ke.physical_keycode = KeyMappingMacOS::translate_key([event keyCode]); ke.key_label = KeyMappingMacOS::remap_key([event keyCode], [event modifierFlags], true); ke.unicode = 0; + ke.location = KeyMappingMacOS::translate_location([event keyCode]); ke.raw = true; ds->push_to_key_event_buffer(ke); diff --git a/platform/macos/key_mapping_macos.h b/platform/macos/key_mapping_macos.h index 1bda4eb406..f5b0ff8d02 100644 --- a/platform/macos/key_mapping_macos.h +++ b/platform/macos/key_mapping_macos.h @@ -45,6 +45,7 @@ public: static Key translate_key(unsigned int p_key); static unsigned int unmap_key(Key p_key); static Key remap_key(unsigned int p_key, unsigned int p_state, bool p_unicode); + static KeyLocation translate_location(unsigned int p_key); // Mapping for menu shortcuts. static String keycode_get_native_string(Key p_keycode); diff --git a/platform/macos/key_mapping_macos.mm b/platform/macos/key_mapping_macos.mm index db3fa4e02d..b5e72048e7 100644 --- a/platform/macos/key_mapping_macos.mm +++ b/platform/macos/key_mapping_macos.mm @@ -46,6 +46,7 @@ HashSet<unsigned int> numpad_keys; HashMap<unsigned int, Key, HashMapHasherKeys> keysym_map; HashMap<Key, unsigned int, HashMapHasherKeys> keysym_map_inv; HashMap<Key, char32_t, HashMapHasherKeys> keycode_map; +HashMap<unsigned int, KeyLocation, HashMapHasherKeys> location_map; void KeyMappingMacOS::initialize() { numpad_keys.insert(0x41); //kVK_ANSI_KeypadDecimal @@ -321,6 +322,20 @@ void KeyMappingMacOS::initialize() { keycode_map[Key::BAR] = '|'; keycode_map[Key::BRACERIGHT] = '}'; keycode_map[Key::ASCIITILDE] = '~'; + + // Keysym -> physical location. + // Ctrl. + location_map[0x3b] = KeyLocation::LEFT; + location_map[0x3e] = KeyLocation::RIGHT; + // Shift. + location_map[0x38] = KeyLocation::LEFT; + location_map[0x3c] = KeyLocation::RIGHT; + // Alt/Option. + location_map[0x3a] = KeyLocation::LEFT; + location_map[0x3d] = KeyLocation::RIGHT; + // Meta/Command (yes, right < left). + location_map[0x36] = KeyLocation::RIGHT; + location_map[0x37] = KeyLocation::LEFT; } bool KeyMappingMacOS::is_numpad_key(unsigned int p_key) { @@ -396,6 +411,15 @@ Key KeyMappingMacOS::remap_key(unsigned int p_key, unsigned int p_state, bool p_ } } +// Translates a macOS keycode to a Godot key location. +KeyLocation KeyMappingMacOS::translate_location(unsigned int p_key) { + const KeyLocation *location = location_map.getptr(p_key); + if (location) { + return *location; + } + return KeyLocation::UNSPECIFIED; +} + String KeyMappingMacOS::keycode_get_native_string(Key p_keycode) { const char32_t *key = keycode_map.getptr(p_keycode); if (key) { diff --git a/platform/web/display_server_web.cpp b/platform/web/display_server_web.cpp index b4a190d47e..aacbe4879f 100644 --- a/platform/web/display_server_web.cpp +++ b/platform/web/display_server_web.cpp @@ -187,6 +187,7 @@ void DisplayServerWeb::_key_callback(const String &p_key_event_code, const Strin Key keycode = dom_code2godot_scancode(p_key_event_code.utf8().get_data(), p_key_event_key.utf8().get_data(), false); Key scancode = dom_code2godot_scancode(p_key_event_code.utf8().get_data(), p_key_event_key.utf8().get_data(), true); + KeyLocation location = dom_code2godot_key_location(p_key_event_code.utf8().get_data()); DisplayServerWeb::KeyEvent ke; @@ -197,6 +198,7 @@ void DisplayServerWeb::_key_callback(const String &p_key_event_code, const Strin ke.physical_keycode = scancode; ke.key_label = fix_key_label(c, keycode); ke.unicode = fix_unicode(c); + ke.location = location; ke.mod = p_modifiers; if (ds->key_event_pos >= ds->key_event_buffer.size()) { @@ -1383,6 +1385,7 @@ void DisplayServerWeb::process_events() { ev->set_physical_keycode(ke.physical_keycode); ev->set_key_label(ke.key_label); ev->set_unicode(ke.unicode); + ev->set_location(ke.location); if (ke.raw) { dom2godot_mod(ev, ke.mod, ke.keycode); } diff --git a/platform/web/display_server_web.h b/platform/web/display_server_web.h index 140aef952b..682d10704f 100644 --- a/platform/web/display_server_web.h +++ b/platform/web/display_server_web.h @@ -95,6 +95,7 @@ private: Key physical_keycode = Key::NONE; Key key_label = Key::NONE; uint32_t unicode = 0; + KeyLocation location = KeyLocation::UNSPECIFIED; int mod = 0; }; diff --git a/platform/web/dom_keys.inc b/platform/web/dom_keys.inc index cd94b779c0..b20a3a46b9 100644 --- a/platform/web/dom_keys.inc +++ b/platform/web/dom_keys.inc @@ -223,3 +223,24 @@ Key dom_code2godot_scancode(EM_UTF8 const p_code[32], EM_UTF8 const p_key[32], b return Key::NONE; #undef DOM2GODOT } + +KeyLocation dom_code2godot_key_location(EM_UTF8 const p_code[32]) { +#define DOM2GODOT(m_str, m_godot_code) \ + if (memcmp((const void *)m_str, (void *)p_code, strlen(m_str) + 1) == 0) { \ + return KeyLocation::m_godot_code; \ + } + + DOM2GODOT("AltLeft", LEFT); + DOM2GODOT("AltRight", RIGHT); + DOM2GODOT("ControlLeft", LEFT); + DOM2GODOT("ControlRight", RIGHT); + DOM2GODOT("MetaLeft", LEFT); + DOM2GODOT("MetaRight", RIGHT); + DOM2GODOT("OSLeft", LEFT); + DOM2GODOT("OSRight", RIGHT); + DOM2GODOT("ShiftLeft", LEFT); + DOM2GODOT("ShiftRight", RIGHT); + + return KeyLocation::UNSPECIFIED; +#undef DOM2GODOT +} diff --git a/platform/windows/display_server_windows.cpp b/platform/windows/display_server_windows.cpp index 1c9b86d35d..657caa7939 100644 --- a/platform/windows/display_server_windows.cpp +++ b/platform/windows/display_server_windows.cpp @@ -169,20 +169,26 @@ DisplayServer::WindowID DisplayServerWindows::_get_focused_window_or_popup() con void DisplayServerWindows::_register_raw_input_devices(WindowID p_target_window) { use_raw_input = true; - RAWINPUTDEVICE rid[1] = {}; - rid[0].usUsagePage = 0x01; - rid[0].usUsage = 0x02; + RAWINPUTDEVICE rid[2] = {}; + rid[0].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC + rid[0].usUsage = 0x02; // HID_USAGE_GENERIC_MOUSE rid[0].dwFlags = 0; + rid[1].usUsagePage = 0x01; // HID_USAGE_PAGE_GENERIC + rid[1].usUsage = 0x06; // HID_USAGE_GENERIC_KEYBOARD + rid[1].dwFlags = 0; + if (p_target_window != INVALID_WINDOW_ID && windows.has(p_target_window)) { // Follow the defined window rid[0].hwndTarget = windows[p_target_window].hWnd; + rid[1].hwndTarget = windows[p_target_window].hWnd; } else { // Follow the keyboard focus rid[0].hwndTarget = 0; + rid[1].hwndTarget = 0; } - if (RegisterRawInputDevices(rid, 1, sizeof(rid[0])) == FALSE) { + if (RegisterRawInputDevices(rid, 2, sizeof(rid[0])) == FALSE) { // Registration failed. use_raw_input = false; } @@ -3348,7 +3354,7 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA } break; case WM_INPUT: { - if (mouse_mode != MOUSE_MODE_CAPTURED || !use_raw_input) { + if (!use_raw_input) { break; } @@ -3366,7 +3372,32 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA RAWINPUT *raw = (RAWINPUT *)lpb; - if (raw->header.dwType == RIM_TYPEMOUSE) { + if (raw->header.dwType == RIM_TYPEKEYBOARD) { + if (raw->data.keyboard.VKey == VK_SHIFT) { + // If multiple Shifts are held down at the same time, + // Windows natively only sends a KEYUP for the last one to be released. + if (raw->data.keyboard.Flags & RI_KEY_BREAK) { + if (GetAsyncKeyState(VK_SHIFT) < 0) { + // A Shift is released, but another Shift is still held + ERR_BREAK(key_event_pos >= KEY_EVENT_BUFFER_SIZE); + + KeyEvent ke; + ke.shift = false; + ke.alt = alt_mem; + ke.control = control_mem; + ke.meta = meta_mem; + ke.uMsg = WM_KEYUP; + ke.window_id = window_id; + + ke.wParam = VK_SHIFT; + // data.keyboard.MakeCode -> 0x2A - left shift, 0x36 - right shift. + // Bit 30 -> key was previously down, bit 31 -> key is being released. + ke.lParam = raw->data.keyboard.MakeCode << 16 | 1 << 30 | 1 << 31; + key_event_buffer[key_event_pos++] = ke; + } + } + } + } else if (mouse_mode == MOUSE_MODE_CAPTURED && raw->header.dwType == RIM_TYPEMOUSE) { Ref<InputEventMouseMotion> mm; mm.instantiate(); @@ -4371,6 +4402,7 @@ void DisplayServerWindows::_process_key_events() { } Key key_label = keycode; Key physical_keycode = KeyMappingWindows::get_scansym((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)); + KeyLocation location = KeyMappingWindows::get_location((ke.lParam >> 16) & 0xFF, ke.lParam & (1 << 24)); static BYTE keyboard_state[256]; memset(keyboard_state, 0, 256); @@ -4397,6 +4429,7 @@ void DisplayServerWindows::_process_key_events() { } k->set_keycode(keycode); k->set_physical_keycode(physical_keycode); + k->set_location(location); k->set_key_label(key_label); if (i + 1 < key_event_pos && key_event_buffer[i + 1].uMsg == WM_CHAR) { diff --git a/platform/windows/key_mapping_windows.cpp b/platform/windows/key_mapping_windows.cpp index b376854c0c..20905d0fe9 100644 --- a/platform/windows/key_mapping_windows.cpp +++ b/platform/windows/key_mapping_windows.cpp @@ -46,6 +46,7 @@ HashMap<unsigned int, Key, HashMapHasherKeys> vk_map; HashMap<unsigned int, Key, HashMapHasherKeys> scansym_map; HashMap<Key, unsigned int, HashMapHasherKeys> scansym_map_inv; HashMap<unsigned int, Key, HashMapHasherKeys> scansym_map_ext; +HashMap<unsigned int, KeyLocation, HashMapHasherKeys> location_map; void KeyMappingWindows::initialize() { // VK_LBUTTON (0x01) @@ -380,6 +381,15 @@ void KeyMappingWindows::initialize() { scansym_map_ext[0x6C] = Key::LAUNCHMAIL; scansym_map_ext[0x6D] = Key::LAUNCHMEDIA; scansym_map_ext[0x78] = Key::MEDIARECORD; + + // Scancode to physical location map. + // Shift. + location_map[0x2A] = KeyLocation::LEFT; + location_map[0x36] = KeyLocation::RIGHT; + // Meta. + location_map[0x5B] = KeyLocation::LEFT; + location_map[0x5C] = KeyLocation::RIGHT; + // Ctrl and Alt must be handled differently. } Key KeyMappingWindows::get_keysym(unsigned int p_code) { @@ -424,3 +434,16 @@ bool KeyMappingWindows::is_extended_key(unsigned int p_code) { p_code == VK_RIGHT || p_code == VK_DOWN; } + +KeyLocation KeyMappingWindows::get_location(unsigned int p_code, bool p_extended) { + // Right- ctrl and alt have the same scancode as left, but are in the extended keys. + const Key *key = scansym_map.getptr(p_code); + if (key && (*key == Key::CTRL || *key == Key::ALT)) { + return p_extended ? KeyLocation::RIGHT : KeyLocation::LEFT; + } + const KeyLocation *location = location_map.getptr(p_code); + if (location) { + return *location; + } + return KeyLocation::UNSPECIFIED; +} diff --git a/platform/windows/key_mapping_windows.h b/platform/windows/key_mapping_windows.h index a98aa7ed68..e6f184a2cc 100644 --- a/platform/windows/key_mapping_windows.h +++ b/platform/windows/key_mapping_windows.h @@ -47,6 +47,7 @@ public: static unsigned int get_scancode(Key p_keycode); static Key get_scansym(unsigned int p_code, bool p_extended); static bool is_extended_key(unsigned int p_code); + static KeyLocation get_location(unsigned int p_code, bool p_extended); }; #endif // KEY_MAPPING_WINDOWS_H |
