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). */