diff --git a/cont/LuaUI/callins.lua b/cont/LuaUI/callins.lua index db7d4380c99..2279b135c37 100644 --- a/cont/LuaUI/callins.lua +++ b/cont/LuaUI/callins.lua @@ -23,6 +23,7 @@ CallInsList = { "MiniMapGeometryChanged", "CommandNotify", + "KeyBindingsChanged", "KeyMapChanged", "KeyPress", "KeyRelease", diff --git a/cont/LuaUI/widgets.lua b/cont/LuaUI/widgets.lua index 4808aa9a436..bbed83d538f 100644 --- a/cont/LuaUI/widgets.lua +++ b/cont/LuaUI/widgets.lua @@ -195,6 +195,7 @@ local callInLists = { 'AddConsoleLine', 'ViewResize', 'DrawScreen', + 'KeyBindingsChanged', 'KeyMapChanged', 'KeyPress', 'KeyRelease', @@ -1416,6 +1417,12 @@ end -- Keyboard call-ins -- +function widgetHandler:KeyBindingsChanged() + for _,w in ipairs(self.KeyBindingsChangedList) do + w:KeyBindingsChanged() + end +end + function widgetHandler:KeyMapChanged() for _,w in ipairs(self.KeyMapChangedList) do w:KeyMapChanged() diff --git a/rts/Game/UI/KeyBindings.cpp b/rts/Game/UI/KeyBindings.cpp index 9bafd6ca542..741584da127 100644 --- a/rts/Game/UI/KeyBindings.cpp +++ b/rts/Game/UI/KeyBindings.cpp @@ -9,6 +9,7 @@ #include "KeySet.h" #include "Sim/Units/UnitDef.h" #include "Sim/Units/UnitDefHandler.h" +#include "System/EventHandler.h" #include "System/FileSystem/FileHandler.h" #include "System/FileSystem/SimpleParser.h" #include "System/Log/ILog.h" @@ -858,7 +859,7 @@ void CKeyBindings::PushAction(const Action& action) } } -bool CKeyBindings::ExecuteCommand(const std::string& line) +bool CKeyBindings::ExecuteCommand(const std::string& line, bool sendEvents) { RECOIL_DETAILED_TRACY_ZONE; const std::vector words = CSimpleParser::Tokenize(line, 2); @@ -867,6 +868,7 @@ bool CKeyBindings::ExecuteCommand(const std::string& line) return false; const std::string command = StringToLower(words[0]); + bool changedKeys = true; if (command == "keydebug") { if (words.size() == 1) { @@ -876,6 +878,7 @@ bool CKeyBindings::ExecuteCommand(const std::string& line) // set debugEnabled = atoi(words[1].c_str()); } + changedKeys = false; // keydebug only toggles debug logging; it never changes bindings } else if (command == "keyload") { const std::string& filename = words.size() > 1 ? words[1] : DEFAULT_FILENAME; @@ -895,8 +898,8 @@ bool CKeyBindings::ExecuteCommand(const std::string& line) if (debugEnabled) LOG("[CKeyBindings::%s] line=%s", __func__, line.c_str()); - ExecuteCommand("unbindall"); - ExecuteCommand("unbind enter chat"); + ExecuteCommand("unbindall", false); + ExecuteCommand("unbind enter chat", false); if (loadStack.empty() && words.size() == 1) LoadDefaults(); @@ -942,6 +945,9 @@ bool CKeyBindings::ExecuteCommand(const std::string& line) if (buildHotkeyMap) BuildHotkeyMap(); + if (changedKeys && sendEvents) + eventHandler.KeyBindingsChanged(); + return false; } @@ -973,7 +979,7 @@ bool CKeyBindings::Load(const std::string& filename) CSimpleParser parser(ifs); while (!parser.Eof()) { - ExecuteCommand(parser.GetCleanLine()); + ExecuteCommand(parser.GetCleanLine(), false); } loadStack.pop_back(); diff --git a/rts/Game/UI/KeyBindings.h b/rts/Game/UI/KeyBindings.h index 04260a7993e..f51cf1bc1ba 100644 --- a/rts/Game/UI/KeyBindings.h +++ b/rts/Game/UI/KeyBindings.h @@ -48,7 +48,7 @@ class CKeyBindings : public CommandReceiver const HotkeyList& GetHotkeys(const std::string& action) const; virtual void PushAction(const Action&); - bool ExecuteCommand(const std::string& line); + bool ExecuteCommand(const std::string& line, bool sendEvents = true); // Receive configuration notifications (for KeyChainTimeout) void ConfigNotify(const std::string& key, const std::string& value); diff --git a/rts/Lua/LuaHandle.cpp b/rts/Lua/LuaHandle.cpp index 650a810499d..6043ec4b38a 100644 --- a/rts/Lua/LuaHandle.cpp +++ b/rts/Lua/LuaHandle.cpp @@ -3103,6 +3103,31 @@ void CLuaHandle::Pong(uint8_t pingTag, const spring_time pktSendTime, const spri RunCallIn(L, cmdStr, 3, 0); } +/*** Called when keybindings change. + * + * Called when: + * + * - An operation that changed current keybindings occurred, e.g. `bind k action`. If the operation operated on multiple keybindings, just a single event is called, at the end of it, e.g. `keyreload`. + * - Any operation that changes how actions are retrieved from input triggers happened, e.g. `fakemeta space`. + * + * Nothing is passed; call `Spring.GetKeyBindings` to read the current state. + * + * @function Callins:KeyBindingsChanged + */ +void CLuaHandle::KeyBindingsChanged() +{ + RECOIL_DETAILED_TRACY_ZONE; + LUA_CALL_IN_CHECK(L); + luaL_checkstack(L, 2, __func__); + + static const LuaHashString cmdStr(__func__); + + if (!cmdStr.GetGlobalFunc(L)) + return; + + RunCallIn(L, cmdStr, 0, 0); +} + /*** Called when the keymap changes * diff --git a/rts/Lua/LuaHandle.h b/rts/Lua/LuaHandle.h index 5256825a2b6..ab3ba6815e5 100644 --- a/rts/Lua/LuaHandle.h +++ b/rts/Lua/LuaHandle.h @@ -200,6 +200,7 @@ class CLuaHandle : public CEventClient void UnsyncedHeightMapUpdate(const SRectangle& rect) override; void Update() override; + void KeyBindingsChanged() override; bool KeyMapChanged() override; bool KeyPress(int keyCode, int scanCode, bool isRepeat) override; bool KeyRelease(int keyCode, int scanCode) override; diff --git a/rts/System/EventClient.cpp b/rts/System/EventClient.cpp index de94b03c58d..849ad9d0fce 100644 --- a/rts/System/EventClient.cpp +++ b/rts/System/EventClient.cpp @@ -61,6 +61,7 @@ void CEventClient::DrawLoadScreen() {} void CEventClient::LoadProgress(const std::string& msg, const bool replace_lastline) {} // from LuaUI +void CEventClient::KeyBindingsChanged() {} bool CEventClient::KeyMapChanged() { return false; } bool CEventClient::KeyPress(int keyCode, int scanCode, bool isRepeat) { return false; } bool CEventClient::KeyRelease(int keyCode, int scanCode) { return false; } diff --git a/rts/System/EventClient.h b/rts/System/EventClient.h index 3e17d1171c2..8f9acc6e772 100644 --- a/rts/System/EventClient.h +++ b/rts/System/EventClient.h @@ -283,6 +283,7 @@ class CEventClient virtual void Update(); virtual void UnsyncedHeightMapUpdate(const SRectangle& rect); + virtual void KeyBindingsChanged(); virtual bool KeyMapChanged(); virtual bool KeyPress(int keyCode, int scanCode, bool isRepeat); virtual bool KeyRelease(int keyCode, int scanCode); diff --git a/rts/System/EventHandler.cpp b/rts/System/EventHandler.cpp index d7969be7aa7..c529af67ce2 100644 --- a/rts/System/EventHandler.cpp +++ b/rts/System/EventHandler.cpp @@ -805,6 +805,12 @@ bool CEventHandler::CommandNotify(const Command& cmd) return ControlReverseIterateDefTrue(listCommandNotify, &CEventClient::CommandNotify, cmd); } +void CEventHandler::KeyBindingsChanged() +{ + ZoneScoped; + ITERATE_EVENTCLIENTLIST_NA(KeyBindingsChanged); +} + bool CEventHandler::KeyMapChanged() { ZoneScoped; diff --git a/rts/System/EventHandler.h b/rts/System/EventHandler.h index e7432aaaf50..7c9596883f1 100644 --- a/rts/System/EventHandler.h +++ b/rts/System/EventHandler.h @@ -221,6 +221,7 @@ class CEventHandler void UnsyncedHeightMapUpdate(const SRectangle& rect); void Update(); + void KeyBindingsChanged(); bool KeyMapChanged(); bool KeyPress(int keyCode, int scanCode, bool isRepeat); bool KeyRelease(int keyCode, int scanCode); diff --git a/rts/System/Events.def b/rts/System/Events.def index a0e069c27d3..3eaba68a8c2 100644 --- a/rts/System/Events.def +++ b/rts/System/Events.def @@ -97,6 +97,7 @@ SETUP_EVENT(Update, MANAGED_BIT | UNSYNCED_BIT) + SETUP_EVENT(KeyBindingsChanged, MANAGED_BIT | UNSYNCED_BIT) SETUP_EVENT(KeyMapChanged, MANAGED_BIT | UNSYNCED_BIT | CONTROL_BIT) SETUP_EVENT(KeyPress, MANAGED_BIT | UNSYNCED_BIT | CONTROL_BIT) SETUP_EVENT(KeyRelease, MANAGED_BIT | UNSYNCED_BIT | CONTROL_BIT)