From fdf2430fc45e8a2b620fa55e23afb454886aea63 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 3 Jul 2023 09:09:52 -0700 Subject: [PATCH 1/2] filter out spurious STRING keybindings that don't match actual SDL string input --- docs/changelog.txt | 1 + library/include/modules/Screen.h | 4 ++-- library/modules/Screen.cpp | 8 +++++--- plugins/overlay.cpp | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/docs/changelog.txt b/docs/changelog.txt index d10407621..f30db1b41 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -36,6 +36,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences: ## New Plugins ## Fixes +- Fix extra keys appearing in DFHack text boxes when shift (or any other modifier) is released before the other key you were pressing ## Misc Improvements diff --git a/library/include/modules/Screen.h b/library/include/modules/Screen.h index daa08ca59..b918ab6c2 100644 --- a/library/include/modules/Screen.h +++ b/library/include/modules/Screen.h @@ -229,8 +229,8 @@ namespace DFHack DFHACK_EXPORT bool hasActiveScreens(Plugin *p); DFHACK_EXPORT void raise(df::viewscreen *screen); - // returns a new set with text interface keys from the text buffer added in (if any) - DFHACK_EXPORT std::set add_text_keys(const std::set& keys); + // returns a new set of interface keys that ensures that string input matches the DF text buffer + DFHACK_EXPORT std::set normalize_text_keys(const std::set& keys); /// Retrieve the string representation of the bound key. DFHACK_EXPORT std::string getKeyDisplay(df::interface_key key); diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 76f782edb..c7ef88c60 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -585,8 +585,10 @@ void Hide::merge() { } } } -std::set Screen::add_text_keys(const std::set& keys) { - std::set combined_keys(keys); +std::set Screen::normalize_text_keys(const std::set& keys) { + std::set combined_keys; + std::copy_if(keys.begin(), keys.end(), std::inserter(combined_keys, combined_keys.begin()), + [](df::interface_key k){ return k <= df::interface_key::STRING_A000 || k > df::interface_key::STRING_A255; } ); if (df::global::enabler->last_text_input[0]) { char c = df::global::enabler->last_text_input[0]; df::interface_key key = charToKey(c); @@ -952,7 +954,7 @@ int dfhack_lua_viewscreen::do_input(lua_State *L) } lua_pushvalue(L, -2); - Lua::PushInterfaceKeys(L, Screen::add_text_keys(*keys)); + Lua::PushInterfaceKeys(L, Screen::normalize_text_keys(*keys)); lua_call(L, 2, 0); self->update_focus(L, -1); diff --git a/plugins/overlay.cpp b/plugins/overlay.cpp index 7185f73a1..5dc9ed327 100644 --- a/plugins/overlay.cpp +++ b/plugins/overlay.cpp @@ -76,7 +76,7 @@ struct viewscreen_overlay : T { [&](lua_State *L) { Lua::Push(L, T::_identity.getName()); Lua::Push(L, this); - Lua::PushInterfaceKeys(L, Screen::add_text_keys(*input)); + Lua::PushInterfaceKeys(L, Screen::normalize_text_keys(*input)); }, [&](lua_State *L) { input_is_handled = lua_toboolean(L, -1); }); From 5a36a0fcbdaa3cddd0b59408a1d72f6770ab8305 Mon Sep 17 00:00:00 2001 From: Myk Taylor Date: Mon, 3 Jul 2023 11:44:33 -0700 Subject: [PATCH 2/2] ensure we can still inject strings with simulateInput --- library/LuaApi.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/library/LuaApi.cpp b/library/LuaApi.cpp index d2c32cf63..8823eb270 100644 --- a/library/LuaApi.cpp +++ b/library/LuaApi.cpp @@ -2603,14 +2603,29 @@ static int screen_doSimulateInput(lua_State *L) int sz = lua_rawlen(L, 2); std::set keys; + char str = '\0'; for (int j = 1; j <= sz; j++) { lua_rawgeti(L, 2, j); - keys.insert((df::interface_key)lua_tointeger(L, -1)); + df::interface_key k = (df::interface_key)lua_tointeger(L, -1); + if (!str && k > df::interface_key::STRING_A000 && k <= df::interface_key::STRING_A255) + str = Screen::keyToChar(k); + keys.insert(k); lua_pop(L, 1); } + // if we're injecting a text keybinding, ensure it is reflected in the enabler text buffer + std::string prev_input; + if (str) { + prev_input = (const char *)&df::global::enabler->last_text_input[0]; + df::global::enabler->last_text_input[0] = str; + df::global::enabler->last_text_input[1] = '\0'; + } + screen->feed(&keys); + + if (str) + strcpy((char *)&df::global::enabler->last_text_input[0], prev_input.c_str()); return 0; }