diff --git a/rpcs3/Emu/Io/KeyboardHandler.cpp b/rpcs3/Emu/Io/KeyboardHandler.cpp index d89eba24cd..7e70577a5b 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.cpp +++ b/rpcs3/Emu/Io/KeyboardHandler.cpp @@ -94,7 +94,7 @@ void KeyboardHandlerBase::RemoveConsumer(keyboard_consumer::identifier id) } } -bool KeyboardHandlerBase::HandleKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key) +bool KeyboardHandlerBase::HandleKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key) { bool consumed = false; @@ -102,13 +102,13 @@ bool KeyboardHandlerBase::HandleKey(u32 code, bool pressed, bool is_auto_repeat, for (auto& [id, consumer] : m_consumers) { - consumed |= consumer.ConsumeKey(code, pressed, is_auto_repeat, key); + consumed |= consumer.ConsumeKey(qt_code, native_code, pressed, is_auto_repeat, key); } return consumed; } -bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key) +bool keyboard_consumer::ConsumeKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key) { bool consumed = false; @@ -124,22 +124,24 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, KbData& data = keyboard.m_data; const KbConfig& config = keyboard.m_config; - if (auto it = keyboard.m_keys.find(code); it != keyboard.m_keys.end()) + if (auto it = keyboard.m_keys.find(qt_code); it != keyboard.m_keys.end()) { KbButton& button = it->second; + const u32 out_key_code = get_out_key_code(qt_code, native_code, button.m_outKeyCode); + u16 kcode = CELL_KEYC_NO_EVENT; - bool is_meta_key = IsMetaKey(code); + bool is_meta_key = IsMetaKey(qt_code); if (!is_meta_key) { if (config.code_type == CELL_KB_CODETYPE_RAW) { - kcode = button.m_outKeyCode; + kcode = out_key_code; } else // config.code_type == CELL_KB_CODETYPE_ASCII { - kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, button.m_outKeyCode); + kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, out_key_code); } } @@ -153,33 +155,33 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, // Meta Keys if (is_meta_key) { - data.mkey |= button.m_outKeyCode; + data.mkey |= out_key_code; if (config.read_mode == CELL_KB_RMODE_INPUTCHAR) { - data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, true); + data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, true); } else { - data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, true); + data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, true); } } else { // Led Keys - if (code == Key_CapsLock) data.led ^= CELL_KB_LED_CAPS_LOCK; - if (code == Key_NumLock) data.led ^= CELL_KB_LED_NUM_LOCK; - if (code == Key_ScrollLock) data.led ^= CELL_KB_LED_SCROLL_LOCK; - // if (code == Key_Kana_Lock) data.led ^= CELL_KB_LED_KANA; - // if (code == ???) data.led ^= CELL_KB_LED_COMPOSE; + if (qt_code == Key_CapsLock) data.led ^= CELL_KB_LED_CAPS_LOCK; + if (qt_code == Key_NumLock) data.led ^= CELL_KB_LED_NUM_LOCK; + if (qt_code == Key_ScrollLock) data.led ^= CELL_KB_LED_SCROLL_LOCK; + // if (qt_code == Key_Kana_Lock) data.led ^= CELL_KB_LED_KANA; + // if (qt_code == ???) data.led ^= CELL_KB_LED_COMPOSE; if (config.read_mode == CELL_KB_RMODE_INPUTCHAR) { - data.buttons[0] = KbButton(kcode, button.m_outKeyCode, true); + data.buttons[0] = KbButton(kcode, out_key_code, true); } else { - data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(kcode, button.m_outKeyCode, true); + data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(kcode, out_key_code, true); } } @@ -190,13 +192,13 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, // Meta Keys if (is_meta_key) { - data.mkey &= ~button.m_outKeyCode; + data.mkey &= ~out_key_code; } // Needed to indicate key releases. Without this you have to tap another key before using the same key again if (config.read_mode == CELL_KB_RMODE_INPUTCHAR) { - data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, false); + data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, false); data.len = 1; } else @@ -205,7 +207,7 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, for (s32 i = 0; i < data.len; i++) { - if (data.buttons[i].m_keyCode == kcode && (!is_meta_key || data.buttons[i].m_outKeyCode == button.m_outKeyCode)) + if (data.buttons[i].m_keyCode == kcode && (!is_meta_key || data.buttons[i].m_outKeyCode == out_key_code)) { index = i; break; @@ -219,7 +221,7 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, if (data.len <= 1) { - data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, false); + data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, false); } data.len = std::max(1, data.len - 1); @@ -247,10 +249,32 @@ bool keyboard_consumer::IsMetaKey(u32 code) return code == Key_Control || code == Key_Shift || code == Key_Alt + || code == Key_Meta || code == Key_Super_L || code == Key_Super_R; } +u32 keyboard_consumer::get_out_key_code(u32 qt_code, u32 native_code, u32 out_key_code) +{ + // Parse native key codes to differentiate between left and right keys. (Qt sometimes really sucks) + // NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment + switch (qt_code) + { + case Key_Control: + return native_code == native_key::ctrl_l ? CELL_KB_MKEY_L_CTRL : CELL_KB_MKEY_R_CTRL; + case Key_Shift: + return native_code == native_key::shift_l ? CELL_KB_MKEY_L_SHIFT : CELL_KB_MKEY_R_SHIFT; + case Key_Alt: + return native_code == native_key::alt_l ? CELL_KB_MKEY_L_ALT : CELL_KB_MKEY_R_ALT; + case Key_Meta: + return native_code == native_key::meta_l ? CELL_KB_MKEY_L_WIN : CELL_KB_MKEY_R_WIN; + default: + break; + } + + return out_key_code; +} + void KeyboardHandlerBase::SetIntercepted(bool intercepted) { std::lock_guard lock(m_mutex); @@ -294,12 +318,33 @@ void keyboard_consumer::ReleaseAllKeys() { for (const auto& [key_code, button] : keyboard.m_keys) { - ConsumeKey(button.m_keyCode, false, false, {}); + switch (button.m_keyCode) + { + case Key_Control: + ConsumeKey(button.m_keyCode, native_key::ctrl_l, false, false, {}); + ConsumeKey(button.m_keyCode, native_key::ctrl_r, false, false, {}); + break; + case Key_Shift: + ConsumeKey(button.m_keyCode, native_key::shift_l, false, false, {}); + ConsumeKey(button.m_keyCode, native_key::shift_r, false, false, {}); + break; + case Key_Alt: + ConsumeKey(button.m_keyCode, native_key::alt_l, false, false, {}); + ConsumeKey(button.m_keyCode, native_key::alt_r, false, false, {}); + break; + case Key_Meta: + ConsumeKey(button.m_keyCode, native_key::meta_l, false, false, {}); + ConsumeKey(button.m_keyCode, native_key::meta_r, false, false, {}); + break; + default: + ConsumeKey(button.m_keyCode, 0, false, false, {}); + break; + } } for (const std::u32string& key : keyboard.m_extra_data.pressed_keys) { - ConsumeKey(CELL_KEYC_NO_EVENT, false, false, key); + ConsumeKey(CELL_KEYC_NO_EVENT, 0, false, false, key); } keyboard.m_extra_data.pressed_keys.clear(); diff --git a/rpcs3/Emu/Io/KeyboardHandler.h b/rpcs3/Emu/Io/KeyboardHandler.h index c62bb099b6..51404b72c4 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.h +++ b/rpcs3/Emu/Io/KeyboardHandler.h @@ -22,6 +22,39 @@ enum QtKeys Key_Super_R = 0x01000054 }; +// See https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values +enum native_key : u32 +{ +#ifdef _WIN32 + ctrl_l = 0x001D, + ctrl_r = 0xE01D, + shift_l = 0x002A, + shift_r = 0x0036, + alt_l = 0x0038, + alt_r = 0xE038, + meta_l = 0xE05B, + meta_r = 0xE05C, +#elif defined (__APPLE__) + ctrl_l = 0x3B, // kVK_Control + ctrl_r = 0x3E, // kVK_RightControl + shift_l = 0x38, // kVK_Shift + shift_r = 0x3C, // kVK_RightShift + alt_l = 0x3A, // kVK_Option + alt_r = 0x3D, // kVK_RightOption + meta_l = 0x37, // kVK_Command + meta_r = 0x36, // kVK_RightCommand +#else + ctrl_l = 0x0025, + ctrl_r = 0x0069, + shift_l = 0x0032, + shift_r = 0x003E, + alt_l = 0x0040, + alt_r = 0x006C, + meta_l = 0x0085, + meta_r = 0x0086, +#endif +}; + struct KbInfo { u32 max_connect = 0; @@ -88,7 +121,7 @@ public: keyboard_consumer() {} keyboard_consumer(identifier id) : m_id(id) {} - bool ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key); + bool ConsumeKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key); void SetIntercepted(bool intercepted); static bool IsMetaKey(u32 code); @@ -103,6 +136,8 @@ public: void ReleaseAllKeys(); protected: + u32 get_out_key_code(u32 qt_code, u32 native_code, u32 out_key_code); + identifier m_id = identifier::unknown; KbInfo m_info{}; std::vector m_keyboards; @@ -126,7 +161,7 @@ public: keyboard_consumer& GetConsumer(keyboard_consumer::identifier id); void RemoveConsumer(keyboard_consumer::identifier id); - bool HandleKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key); + bool HandleKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key); void SetIntercepted(bool intercepted); stx::init_mutex init; diff --git a/rpcs3/Input/basic_keyboard_handler.cpp b/rpcs3/Input/basic_keyboard_handler.cpp index 90f26dc902..50ee435ead 100644 --- a/rpcs3/Input/basic_keyboard_handler.cpp +++ b/rpcs3/Input/basic_keyboard_handler.cpp @@ -110,7 +110,7 @@ void basic_keyboard_handler::keyPressEvent(QKeyEvent* keyEvent) const int key = getUnmodifiedKey(keyEvent); - if (key < 0 || !HandleKey(static_cast(key), true, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String())) + if (key < 0 || !HandleKey(static_cast(key), keyEvent->nativeScanCode(), true, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String())) { keyEvent->ignore(); } @@ -131,7 +131,7 @@ void basic_keyboard_handler::keyReleaseEvent(QKeyEvent* keyEvent) const int key = getUnmodifiedKey(keyEvent); - if (key < 0 || !HandleKey(static_cast(key), false, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String())) + if (key < 0 || !HandleKey(static_cast(key), keyEvent->nativeScanCode(), false, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String())) { keyEvent->ignore(); } @@ -182,11 +182,14 @@ void basic_keyboard_handler::LoadSettings(Keyboard& keyboard) buttons.emplace_back(Qt::Key_Control, CELL_KB_MKEY_L_CTRL); buttons.emplace_back(Qt::Key_Shift, CELL_KB_MKEY_L_SHIFT); buttons.emplace_back(Qt::Key_Alt, CELL_KB_MKEY_L_ALT); - buttons.emplace_back(Qt::Key_Super_L, CELL_KB_MKEY_L_WIN); + buttons.emplace_back(Qt::Key_Meta, CELL_KB_MKEY_L_WIN); //buttons.emplace_back(, CELL_KB_MKEY_R_CTRL); // There is no way to know if it's left or right in Qt at the moment //buttons.emplace_back(, CELL_KB_MKEY_R_SHIFT); // There is no way to know if it's left or right in Qt at the moment //buttons.emplace_back(, CELL_KB_MKEY_R_ALT); // There is no way to know if it's left or right in Qt at the moment - buttons.emplace_back(Qt::Key_Super_R, CELL_KB_MKEY_R_WIN); + //buttons.emplace_back(, CELL_KB_MKEY_R_WIN); // There is no way to know if it's left or right in Qt at the moment + + buttons.emplace_back(Qt::Key_Super_L, CELL_KB_MKEY_L_WIN); // The super keys are supposed to be the windows keys, but they trigger the meta key instead. Let's assign the windows keys to both. + buttons.emplace_back(Qt::Key_Super_R, CELL_KB_MKEY_R_WIN); // The super keys are supposed to be the windows keys, but they trigger the meta key instead. Let's assign the windows keys to both. // CELL_KB_RAWDAT //buttons.emplace_back(, CELL_KEYC_NO_EVENT); // Redundant, listed for completeness @@ -222,7 +225,7 @@ void basic_keyboard_handler::LoadSettings(Keyboard& keyboard) buttons.emplace_back(Qt::Key_Down, CELL_KEYC_DOWN_ARROW); buttons.emplace_back(Qt::Key_Up, CELL_KEYC_UP_ARROW); //buttons.emplace_back(, CELL_KEYC_NUM_LOCK); - buttons.emplace_back(Qt::Key_Meta, CELL_KEYC_APPLICATION); + //buttons.emplace_back(, CELL_KEYC_APPLICATION); // This is probably the PS key on the PS3 keyboard buttons.emplace_back(Qt::Key_Kana_Shift, CELL_KEYC_KANA); // maybe Key_Kana_Lock buttons.emplace_back(Qt::Key_Henkan, CELL_KEYC_HENKAN); buttons.emplace_back(Qt::Key_Muhenkan, CELL_KEYC_MUHENKAN); diff --git a/rpcs3/Input/keyboard_pad_handler.cpp b/rpcs3/Input/keyboard_pad_handler.cpp index 5179673226..fb25334850 100644 --- a/rpcs3/Input/keyboard_pad_handler.cpp +++ b/rpcs3/Input/keyboard_pad_handler.cpp @@ -1,6 +1,7 @@ #include "keyboard_pad_handler.h" #include "pad_thread.h" #include "Emu/Io/pad_config.h" +#include "Emu/Io/KeyboardHandler.h" #include "Input/product_info.h" #include "rpcs3qt/gs_frame.h" @@ -821,12 +822,16 @@ u32 keyboard_pad_handler::GetKeyCode(const QString& keyName) int keyboard_pad_handler::native_scan_code_from_string([[maybe_unused]] const std::string& key) { - // NOTE: Qt throws a Ctrl key at us when using Alt Gr, so there is no point in distinguishing left and right Alt at the moment + // NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment + if (key == "Shift Left") return native_key::shift_l; + if (key == "Shift Right") return native_key::shift_r; + if (key == "Ctrl Left") return native_key::ctrl_l; + if (key == "Ctrl Right") return native_key::ctrl_r; + if (key == "Alt Left") return native_key::alt_l; + if (key == "Alt Right") return native_key::alt_r; + if (key == "Meta Left") return native_key::meta_l; + if (key == "Meta Right") return native_key::meta_r; #ifdef _WIN32 - if (key == "Shift Left") return 42; - if (key == "Shift Right") return 54; - if (key == "Ctrl Left") return 29; - if (key == "Ctrl Right") return 285; if (key == "Num+0" || key == "Num+Ins") return 82; if (key == "Num+1" || key == "Num+End") return 79; if (key == "Num+2" || key == "Num+Down") return 80; @@ -851,15 +856,20 @@ int keyboard_pad_handler::native_scan_code_from_string([[maybe_unused]] const st std::string keyboard_pad_handler::native_scan_code_to_string(int native_scan_code) { + // NOTE: the other Qt function "nativeVirtualKey" does not distinguish between VK_SHIFT and VK_RSHIFT key in Qt at the moment + // NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment + // NOTE: for MacOs: nativeScanCode may not work switch (native_scan_code) { + case native_key::shift_l: return "Shift Left"; + case native_key::shift_r: return "Shift Right"; + case native_key::ctrl_l: return "Ctrl Left"; + case native_key::ctrl_r: return "Ctrl Right"; + case native_key::alt_l: return "Alt Left"; + case native_key::alt_r: return "Alt Right"; + case native_key::meta_l: return "Meta Left"; + case native_key::meta_r: return "Meta Right"; #ifdef _WIN32 - // NOTE: the other Qt function "nativeVirtualKey" does not distinguish between VK_SHIFT and VK_RSHIFT key in Qt at the moment - // NOTE: Qt throws a Ctrl key at us when using Alt Gr, so there is no point in distinguishing left and right Alt at the moment - case 42: return "Shift Left"; - case 54: return "Shift Right"; - case 29: return "Ctrl Left"; - case 285: return "Ctrl Right"; case 82: return "Num+0"; // Also "Num+Ins" depending on numlock case 79: return "Num+1"; // Also "Num+End" depending on numlock case 80: return "Num+2"; // Also "Num+Down" depending on numlock @@ -878,7 +888,6 @@ std::string keyboard_pad_handler::native_scan_code_to_string(int native_scan_cod case 284: return "Num+Enter"; #else // TODO - // NOTE for MacOs: nativeScanCode may not work #endif default: return ""; }