Index: ps/trunk/source/gui/ObjectTypes/CInput.cpp =================================================================== --- ps/trunk/source/gui/ObjectTypes/CInput.cpp +++ ps/trunk/source/gui/ObjectTypes/CInput.cpp @@ -1128,6 +1128,8 @@ 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; Index: ps/trunk/source/ps/CConsole.cpp =================================================================== --- ps/trunk/source/ps/CConsole.cpp +++ ps/trunk/source/ps/CConsole.cpp @@ -641,6 +641,7 @@ if (hotkey == "console.toggle") { + ResetActiveHotkeys(); g_Console->ToggleVisible(); return IN_HANDLED; } Index: ps/trunk/source/ps/Hotkey.h =================================================================== --- ps/trunk/source/ps/Hotkey.h +++ ps/trunk/source/ps/Hotkey.h @@ -98,6 +98,15 @@ 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). */ extern bool HotkeyIsPressed(const CStr& keyname); Index: ps/trunk/source/ps/Hotkey.cpp =================================================================== --- ps/trunk/source/ps/Hotkey.cpp +++ ps/trunk/source/ps/Hotkey.cpp @@ -460,6 +460,21 @@ [&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];