From 7032a3c12ad2916e10956670289851b2a5b77795 Mon Sep 17 00:00:00 2001 From: wraitii Date: Sat, 3 Apr 2021 20:12:40 +0000 Subject: [PATCH] Further hotkey work: clear hotkeys when an input box/the console gets focus. This is necessary following 2d53308e1b, which now handles key-up in input to prevent hotkeys from firing then. Hotkeys are a global system, which means opening e.g. the chat window or the summary does't reset things. If you press "S" to scroll the in-game camera down, then press 'return' to open the chat, the camera keeps scrolling down. Following 2d53308e1b, it never released since it never got the keyup. To handle this nicely, we need to explicitly clear hotkeys when input boxes get focus (respectively the console). Differential Revision: https://code.wildfiregames.com/D3797 This was SVN commit r25186. --- source/gui/ObjectTypes/CInput.cpp | 2 ++ source/ps/CConsole.cpp | 1 + source/ps/Hotkey.cpp | 15 +++++++++++++++ source/ps/Hotkey.h | 9 +++++++++ 4 files changed, 27 insertions(+) diff --git a/source/gui/ObjectTypes/CInput.cpp b/source/gui/ObjectTypes/CInput.cpp index b07f56c976..9e7fce68fc 100644 --- a/source/gui/ObjectTypes/CInput.cpp +++ b/source/gui/ObjectTypes/CInput.cpp @@ -1128,6 +1128,8 @@ void CInput::HandleMessage(SGUIMessage& Message) m_PrevTime = 0.0; m_CursorVisState = false; + ResetActiveHotkeys(); + // Tell the IME where to draw the candidate list SDL_Rect rect; rect.h = m_CachedActualSize.GetSize().Height; diff --git a/source/ps/CConsole.cpp b/source/ps/CConsole.cpp index 12491afe43..c5f24ee42f 100644 --- a/source/ps/CConsole.cpp +++ b/source/ps/CConsole.cpp @@ -641,6 +641,7 @@ InReaction conInputHandler(const SDL_Event_* ev) if (hotkey == "console.toggle") { + ResetActiveHotkeys(); g_Console->ToggleVisible(); return IN_HANDLED; } diff --git a/source/ps/Hotkey.cpp b/source/ps/Hotkey.cpp index 32dbdcea6b..ce435fc04e 100644 --- a/source/ps/Hotkey.cpp +++ b/source/ps/Hotkey.cpp @@ -460,6 +460,21 @@ bool EventWillFireHotkey(const SDL_Event_* ev, const CStr& keyname) [&keyname](const PressedHotkey& v){ return v.mapping->name == keyname; }) != newPressedHotkeys.end(); } +void ResetActiveHotkeys() +{ + newPressedHotkeys.clear(); + for (const PressedHotkey& hotkey : pressedHotkeys) + { + SDL_Event_ hotkeyNotification; + hotkeyNotification.ev.type = hotkey.retriggered ? SDL_HOTKEYUP_SILENT : SDL_HOTKEYUP; + hotkeyNotification.ev.user.data1 = const_cast(hotkey.mapping->name.c_str()); + in_push_priority_event(&hotkeyNotification); + } + pressedHotkeys.clear(); + activeScancodes.clear(); + currentEvent = nullptr; +} + bool HotkeyIsPressed(const CStr& keyname) { return g_HotkeyStatus[keyname]; diff --git a/source/ps/Hotkey.h b/source/ps/Hotkey.h index 28516cd75b..fb27bdd3c8 100644 --- a/source/ps/Hotkey.h +++ b/source/ps/Hotkey.h @@ -97,6 +97,15 @@ extern InReaction HotkeyInputActualHandler(const SDL_Event_* ev); */ extern bool EventWillFireHotkey(const SDL_Event_* ev, const CStr& keyname); +/** + * Resets all currently active hotkeys (and clears in-flight hotkeys). + * You should call this when something grabs key input, e.g. an input box, + * as those prevent keydown/keyup messages from reaching the hotkey system, + * and can lead to hotkeys being stuck active. + * NB: active hotkeys are released immediately and "HotkeyUp" message sent. + */ +extern void ResetActiveHotkeys(); + /** * @return whether the hotkey is currently pressed (i.e. active). */