From b5f01372eeaf31c7b70e11c62448a057d5e36056 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 22 Jun 2020 20:19:02 +0200 Subject: [PATCH] Windows: distinguish left and right modifiers This is just some workaround until we either use a different input api for keyboards or until we refactor the keyboard_pad_handler to use Qt with native scan codes --- rpcs3/Input/keyboard_pad_handler.cpp | 73 +++++++++++++++++++++++++--- rpcs3/Input/keyboard_pad_handler.h | 3 ++ rpcs3/rpcs3qt/gs_frame.cpp | 4 +- 3 files changed, 70 insertions(+), 10 deletions(-) diff --git a/rpcs3/Input/keyboard_pad_handler.cpp b/rpcs3/Input/keyboard_pad_handler.cpp index f4c19bedf9..908a2059e4 100644 --- a/rpcs3/Input/keyboard_pad_handler.cpp +++ b/rpcs3/Input/keyboard_pad_handler.cpp @@ -190,9 +190,8 @@ void keyboard_pad_handler::processKeyEvent(QKeyEvent* event, bool pressed) return; } - auto handleKey = [this, pressed, event]() + auto handle_key = [this, pressed, event]() { - const QString name = qstr(GetKeyName(event)); QStringList list = GetKeyNames(event); if (list.isEmpty()) return; @@ -201,6 +200,8 @@ void keyboard_pad_handler::processKeyEvent(QKeyEvent* event, bool pressed) if (is_num_key) list.removeAll("Num"); + const QString name = qstr(GetKeyName(event)); + // TODO: Edge case: switching numlock keeps numpad keys pressed due to now different modifier // Handle every possible key combination, for example: ctrl+A -> {ctrl, A, ctrl+A} @@ -226,17 +227,17 @@ void keyboard_pad_handler::processKeyEvent(QKeyEvent* event, bool pressed) case Qt::Key_L: case Qt::Key_Return: if (event->modifiers() != Qt::AltModifier) - handleKey(); + handle_key(); break; case Qt::Key_P: case Qt::Key_S: case Qt::Key_R: case Qt::Key_E: if (event->modifiers() != Qt::ControlModifier) - handleKey(); + handle_key(); break; default: - handleKey(); + handle_key(); break; } event->ignore(); @@ -472,6 +473,12 @@ QStringList keyboard_pad_handler::GetKeyNames(const QKeyEvent* keyEvent) list.append(QKeySequence(keyEvent->key() | Qt::KeypadModifier).toString(QKeySequence::NativeText)); } + // Handle special cases + if (const std::string name = native_scan_code_to_string(keyEvent->nativeScanCode()); !name.empty()) + { + list.append(qstr(name)); + } + switch (keyEvent->key()) { case Qt::Key_Alt: @@ -500,6 +507,12 @@ QStringList keyboard_pad_handler::GetKeyNames(const QKeyEvent* keyEvent) std::string keyboard_pad_handler::GetKeyName(const QKeyEvent* keyEvent) { + // Handle special cases first + if (const std::string name = native_scan_code_to_string(keyEvent->nativeScanCode()); !name.empty()) + { + return name; + } + switch (keyEvent->key()) { case Qt::Key_Alt: @@ -534,6 +547,8 @@ u32 keyboard_pad_handler::GetKeyCode(const QString& keyName) { if (keyName.isEmpty()) return 0; + else if (const int native_scan_code = native_scan_code_from_string(sstr(keyName)); native_scan_code >= 0) + return Qt::Key_unknown + native_scan_code; // Special cases that can't be expressed with Qt::Key else if (keyName == "Alt") return Qt::Key_Alt; else if (keyName == "AltGr") @@ -546,14 +561,56 @@ u32 keyboard_pad_handler::GetKeyCode(const QString& keyName) return Qt::Key_Meta; QKeySequence seq(keyName); - u32 keyCode = 0; + u32 key_code = 0; if (seq.count() == 1) - keyCode = seq[0]; + key_code = seq[0]; else input_log.notice("GetKeyCode(%s): seq.count() = %d", sstr(keyName), seq.count()); - return keyCode; + return key_code; +} + +int keyboard_pad_handler::native_scan_code_from_string(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 +#ifdef _WIN32 + if (key == "Shift Left") + return 42; + else if (key == "Shift Right") + return 54; + else if (key == "Ctrl Left") + return 29; + else if (key == "Ctrl Right") + return 285; +#else + // TODO +#endif + return -1; +} + +std::string keyboard_pad_handler::native_scan_code_to_string(int native_scan_code) +{ + switch (native_scan_code) + { +#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"; +#else + // TODO + // NOTE for MacOs: nativeScanCode may not work +#endif + default: + return ""; + } } bool keyboard_pad_handler::bindPadToDevice(std::shared_ptr pad, const std::string& device) diff --git a/rpcs3/Input/keyboard_pad_handler.h b/rpcs3/Input/keyboard_pad_handler.h index 9886ac3895..2cd7966eb5 100644 --- a/rpcs3/Input/keyboard_pad_handler.h +++ b/rpcs3/Input/keyboard_pad_handler.h @@ -93,6 +93,9 @@ public: u32 GetKeyCode(const std::string& keyName); u32 GetKeyCode(const QString& keyName); + static int native_scan_code_from_string(const std::string& key); + static std::string native_scan_code_to_string(int native_scan_code); + protected: void Key(const u32 code, bool pressed, u16 value = 255); diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index 9a53547f02..0fd1c44d50 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -106,8 +106,8 @@ void gs_frame::showEvent(QShowEvent *event) { // we have to calculate new window positions, since the frame is only known once the window was created // the left and right margins are too big on my setup for some reason yet unknown, so we'll have to ignore them - int x = geometry().left(); //std::max(geometry().left(), frameMargins().left()); - int y = std::max(geometry().top(), frameMargins().top()); + const int x = geometry().left(); //std::max(geometry().left(), frameMargins().left()); + const int y = std::max(geometry().top(), frameMargins().top()); setPosition(x, y);