From a48fa4097b14cd4935806be4e6b4acae112c83fe Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 28 Feb 2021 02:45:30 +1000 Subject: [PATCH] CommonHostInterface: Fix key inputs getting stuck with modifiers --- src/duckstation-nogui/sdl_host_interface.cpp | 9 ++++--- src/duckstation-nogui/sdl_key_names.h | 27 ++++++++++++------- src/duckstation-qt/qthostinterface.cpp | 2 +- src/frontend-common/common_host_interface.cpp | 10 ++++--- src/frontend-common/common_host_interface.h | 4 +-- 5 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/duckstation-nogui/sdl_host_interface.cpp b/src/duckstation-nogui/sdl_host_interface.cpp index d162ebc54..96fd851ec 100644 --- a/src/duckstation-nogui/sdl_host_interface.cpp +++ b/src/duckstation-nogui/sdl_host_interface.cpp @@ -1,10 +1,10 @@ #include "sdl_host_interface.h" #include "frontend-common/controller_interface.h" +#include "frontend-common/fullscreen_ui.h" #include "frontend-common/icon.h" #include "frontend-common/ini_settings_interface.h" #include "frontend-common/sdl_controller_interface.h" #include "frontend-common/sdl_initializer.h" -#include "frontend-common/fullscreen_ui.h" #include "imgui.h" #include "imgui_impl_sdl.h" #include "scmversion/scmversion.h" @@ -307,7 +307,8 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event) case SDL_KEYUP: { // Binding mode - if (m_fullscreen_ui_enabled && m_controller_interface && m_controller_interface->HasHook() && event->key.repeat == 0) + if (m_fullscreen_ui_enabled && m_controller_interface && m_controller_interface->HasHook() && + event->key.repeat == 0) { String keyName; if (!SDLKeyNames::KeyEventToString(event, keyName)) @@ -324,9 +325,9 @@ void SDLHostInterface::HandleSDLEvent(const SDL_Event* event) if (!ImGui::GetIO().WantCaptureKeyboard && event->key.repeat == 0) { - const HostKeyCode code = static_cast(SDLKeyNames::KeyEventToInt(event)); + const u32 code = SDLKeyNames::KeyEventToInt(event); const bool pressed = (event->type == SDL_KEYDOWN); - HandleHostKeyEvent(code, pressed); + HandleHostKeyEvent(code & SDLKeyNames::KEY_MASK, code & SDLKeyNames::MODIFIER_MASK, pressed); } } break; diff --git a/src/duckstation-nogui/sdl_key_names.h b/src/duckstation-nogui/sdl_key_names.h index acf32e478..3222d6e15 100644 --- a/src/duckstation-nogui/sdl_key_names.h +++ b/src/duckstation-nogui/sdl_key_names.h @@ -10,6 +10,13 @@ namespace SDLKeyNames { +enum : u32 +{ + MODIFIER_SHIFT = 16, + KEY_MASK = ((1 << MODIFIER_SHIFT) - 1), + MODIFIER_MASK = ~KEY_MASK, +}; + static const std::map s_sdl_key_names = {{SDLK_RETURN, "Return"}, {SDLK_ESCAPE, "Escape"}, {SDLK_BACKSPACE, "Backspace"}, @@ -265,13 +272,13 @@ static const std::array s_sdl_key_modifiers = { {KMOD_LALT, static_cast(KMOD_LALT | KMOD_RALT), SDLK_LALT, SDLK_RALT, "Alt"}, {KMOD_LGUI, static_cast(KMOD_LGUI | KMOD_RGUI), SDLK_LGUI, SDLK_RGUI, "Meta"}}}; -const char* GetKeyName(SDL_Keycode key) +static const char* GetKeyName(SDL_Keycode key) { const auto it = s_sdl_key_names.find(key); return it == s_sdl_key_names.end() ? nullptr : it->second; } -std::optional GetKeyCodeForName(const std::string_view key_name) +static std::optional GetKeyCodeForName(const std::string_view key_name) { for (const auto& it : s_sdl_key_names) { @@ -282,24 +289,24 @@ std::optional GetKeyCodeForName(const std::string_view key_name) return std::nullopt; } -u32 KeyEventToInt(const SDL_Event* event) +static u32 KeyEventToInt(const SDL_Event* event) { u32 code = static_cast(event->key.keysym.sym); const SDL_Keymod mods = static_cast(event->key.keysym.mod); if (mods & (KMOD_LSHIFT | KMOD_RSHIFT)) - code |= static_cast(KMOD_LSHIFT) << 16; + code |= static_cast(KMOD_LSHIFT) << MODIFIER_SHIFT; if (mods & (KMOD_LCTRL | KMOD_RCTRL)) - code |= static_cast(KMOD_LCTRL) << 16; + code |= static_cast(KMOD_LCTRL) << MODIFIER_SHIFT; if (mods & (KMOD_LALT | KMOD_RALT)) - code |= static_cast(KMOD_LALT) << 16; + code |= static_cast(KMOD_LALT) << MODIFIER_SHIFT; if (mods & (KMOD_LGUI | KMOD_RGUI)) - code |= static_cast(KMOD_LGUI) << 16; + code |= static_cast(KMOD_LGUI) << MODIFIER_SHIFT; return code; } -bool KeyEventToString(const SDL_Event* event, String& out_string) +static bool KeyEventToString(const SDL_Event* event, String& out_string) { const SDL_Keycode key = event->key.keysym.sym; const SDL_Keymod mods = static_cast(event->key.keysym.mod); @@ -322,7 +329,7 @@ bool KeyEventToString(const SDL_Event* event, String& out_string) return true; } -std::optional ParseKeyString(const std::string_view key_str) +static std::optional ParseKeyString(const std::string_view key_str) { u32 modifiers = 0; std::string_view::size_type pos = 0; @@ -356,6 +363,6 @@ std::optional ParseKeyString(const std::string_view key_str) if (!key_code) return std::nullopt; - return static_cast(key_code.value()) | (modifiers << 16); + return static_cast(key_code.value()) | (modifiers << MODIFIER_SHIFT); } } // namespace SDLKeyNames diff --git a/src/duckstation-qt/qthostinterface.cpp b/src/duckstation-qt/qthostinterface.cpp index 960862a7f..3bb17fe42 100644 --- a/src/duckstation-qt/qthostinterface.cpp +++ b/src/duckstation-qt/qthostinterface.cpp @@ -381,7 +381,7 @@ void QtHostInterface::onDisplayWindowKeyEvent(int key, bool pressed) if (masked_key < countof(ImGuiIO::KeysDown)) ImGui::GetIO().KeysDown[masked_key] = pressed; - HandleHostKeyEvent(key, pressed); + HandleHostKeyEvent(key & ~Qt::KeyboardModifierMask, key & Qt::KeyboardModifierMask, pressed); } void QtHostInterface::onDisplayWindowMouseMoveEvent(int x, int y) diff --git a/src/frontend-common/common_host_interface.cpp b/src/frontend-common/common_host_interface.cpp index ec1dbb1a5..ae715f721 100644 --- a/src/frontend-common/common_host_interface.cpp +++ b/src/frontend-common/common_host_interface.cpp @@ -1267,11 +1267,15 @@ void CommonHostInterface::RegisterHotkey(String category, String name, String di m_hotkeys.push_back(HotkeyInfo{std::move(category), std::move(name), std::move(display_name), std::move(handler)}); } -bool CommonHostInterface::HandleHostKeyEvent(HostKeyCode key, bool pressed) +bool CommonHostInterface::HandleHostKeyEvent(HostKeyCode code, HostKeyCode modifiers, bool pressed) { - const auto iter = m_keyboard_input_handlers.find(key); + auto iter = m_keyboard_input_handlers.find(code | modifiers); if (iter == m_keyboard_input_handlers.end()) - return false; + { + // try without the modifier + if (modifiers == 0 || (iter = m_keyboard_input_handlers.find(code)) == m_keyboard_input_handlers.end()) + return false; + } iter->second(pressed); return true; diff --git a/src/frontend-common/common_host_interface.h b/src/frontend-common/common_host_interface.h index 3390f8956..9d4d832ac 100644 --- a/src/frontend-common/common_host_interface.h +++ b/src/frontend-common/common_host_interface.h @@ -347,7 +347,7 @@ protected: virtual bool AddRumbleToInputMap(const std::string& binding, u32 controller_index, u32 num_motors); void RegisterHotkey(String category, String name, String display_name, InputButtonHandler handler); - bool HandleHostKeyEvent(HostKeyCode code, bool pressed); + bool HandleHostKeyEvent(HostKeyCode code, HostKeyCode modifiers, bool pressed); bool HandleHostMouseEvent(HostMouseButton button, bool pressed); void UpdateInputMap(SettingsInterface& si); void ClearInputMap(); @@ -492,8 +492,8 @@ private: u32 controller_index; u32 num_motors; std::array last_strength; - ControllerRumbleCallback update_callback; u64 last_update_time; + ControllerRumbleCallback update_callback; }; std::vector m_controller_vibration_motors;