From b2cf5e236a451ad6c025a7dc80914218be6bd5da Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Wed, 15 Apr 2026 16:05:56 +0200 Subject: [PATCH 1/5] fix: UI Toggle --- src/Menu.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Menu.cpp b/src/Menu.cpp index 0c69343e75..cb30841b76 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -1028,7 +1028,13 @@ void Menu::ProcessInputEventQueue() std::function action; }; KeyAction keyActions[] = { - { settings.ToggleKey, [this]() { if (!HomePageRenderer::ShouldShowFirstTimeSetup()) IsEnabled = !IsEnabled; } }, + { settings.ToggleKey, [this]() { + if (!HomePageRenderer::ShouldShowFirstTimeSetup()) { + IsEnabled = !IsEnabled; + if (IsEnabled) + ImGui::GetIO().ClearInputKeys(); // Prevent toggle key from remaining "held" in ImGui after open. + } + } }, { settings.SkipCompilationKey, [this, shaderCache]() { if (!ShouldSwallowInput() && shaderCache->IsCompiling()) shaderCache->backgroundCompilation = true; } }, { settings.EffectToggleKey, [shaderCache]() { shaderCache->SetEnabled(!shaderCache->IsEnabled()); } }, { settings.ShaderBlockPrevKey, [this, shaderCache]() { if (settings.EnableShaderBlocking) shaderCache->IterateShaderBlock(); } }, From c056c49afe63f9f8b07d861e00694739bafdeab8 Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Wed, 15 Apr 2026 16:23:00 +0200 Subject: [PATCH 2/5] fix: key assign --- src/Menu.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Menu.cpp b/src/Menu.cpp index cb30841b76..f09a055879 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -1086,7 +1086,9 @@ void Menu::ProcessInputEventQueue() bool isHotkey = ShouldSwallowInput() && std::any_of(std::begin(hotkeys), std::end(hotkeys), [key](const auto* combo) { return InputCombo::MatchesKeyboardCombo(*combo, key); }); - if (!isHotkey) { + // Swallow hotkey key-down events to avoid UI side effects, but always forward + // key-up events so ImGui state cannot get stuck in a held-key state. + if (!isHotkey || !event.IsPressed()) { // DirectInput loses key-up events after alt-tab; validate against OS state. bool pressed = event.IsPressed() && (GetAsyncKeyState(key) & Constants::KEY_PRESSED_MASK); io.AddKeyEvent(Util::Input::VirtualKeyToImGuiKey(key), pressed); From 6785e2ab92c7e2c7f08d35ac06804b0411dfc78a Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Wed, 15 Apr 2026 16:46:16 +0200 Subject: [PATCH 3/5] fix: input on key assign --- src/Menu.cpp | 14 +++++++++++++- src/Menu.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Menu.cpp b/src/Menu.cpp index f09a055879..8260fed239 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -954,6 +954,10 @@ void Menu::ProcessInputEventQueue() logger::trace("Detected key code {} ({})", event.keyCode, key); if (key == event.keyCode) key = MapVirtualKeyEx(event.keyCode, MAPVK_VSC_TO_VK_EX, GetKeyboardLayout(0)); + + const bool wasCapturingHotkey = IsCapturingHotkeyInput(); + const bool allowSetupCloseKey = wasCapturingHotkey && HomePageRenderer::ShouldShowFirstTimeSetup() && + (key == VK_RETURN || key == VK_ESCAPE); if (!event.IsPressed()) { // Skip key release if it was used to close the first-time setup dialog if (HomePageRenderer::ShouldSkipKeyRelease(key)) { @@ -1088,7 +1092,9 @@ void Menu::ProcessInputEventQueue() // Swallow hotkey key-down events to avoid UI side effects, but always forward // key-up events so ImGui state cannot get stuck in a held-key state. - if (!isHotkey || !event.IsPressed()) { + // While recording a new hotkey, suppress keyboard forwarding so capture input + // does not trigger menu navigation; first-time setup Enter/Escape is allowed. + if ((!isHotkey || !event.IsPressed()) && (!wasCapturingHotkey || allowSetupCloseKey)) { // DirectInput loses key-up events after alt-tab; validate against OS state. bool pressed = event.IsPressed() && (GetAsyncKeyState(key) & Constants::KEY_PRESSED_MASK); io.AddKeyEvent(Util::Input::VirtualKeyToImGuiKey(key), pressed); @@ -1106,6 +1112,12 @@ void Menu::ProcessInputEventQueue() _keyEventQueue.clear(); } +bool Menu::IsCapturingHotkeyInput() const +{ + return settingToggleKey || settingSkipCompilationKey || settingsEffectsToggle || + settingOverlayToggleKey || settingShaderBlockPrevKey || settingShaderBlockNextKey || settingWeatherEditorToggleKey; +} + void Menu::addToEventQueue(KeyEvent e) { std::unique_lock mutex(_inputEventMutex); diff --git a/src/Menu.h b/src/Menu.h index 61d5861c34..37f4c3d5e0 100644 --- a/src/Menu.h +++ b/src/Menu.h @@ -501,5 +501,6 @@ class Menu void addToEventQueue(KeyEvent e); void ProcessInputEventQueue(); + bool IsCapturingHotkeyInput() const; winrt::com_ptr dxgiAdapter3; }; \ No newline at end of file From 2bf748c6222346063a2b836a511d2e9a525806df Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 15 Apr 2026 14:49:07 +0000 Subject: [PATCH 4/5] =?UTF-8?q?style:=20=F0=9F=8E=A8=20apply=20pre-commit.?= =?UTF-8?q?ci=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automated formatting by clang-format, prettier, and other hooks. See https://pre-commit.ci for details. --- src/Menu.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Menu.cpp b/src/Menu.cpp index 8260fed239..38c3a9bbba 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -957,7 +957,7 @@ void Menu::ProcessInputEventQueue() const bool wasCapturingHotkey = IsCapturingHotkeyInput(); const bool allowSetupCloseKey = wasCapturingHotkey && HomePageRenderer::ShouldShowFirstTimeSetup() && - (key == VK_RETURN || key == VK_ESCAPE); + (key == VK_RETURN || key == VK_ESCAPE); if (!event.IsPressed()) { // Skip key release if it was used to close the first-time setup dialog if (HomePageRenderer::ShouldSkipKeyRelease(key)) { @@ -1033,12 +1033,12 @@ void Menu::ProcessInputEventQueue() }; KeyAction keyActions[] = { { settings.ToggleKey, [this]() { - if (!HomePageRenderer::ShouldShowFirstTimeSetup()) { - IsEnabled = !IsEnabled; - if (IsEnabled) - ImGui::GetIO().ClearInputKeys(); // Prevent toggle key from remaining "held" in ImGui after open. - } - } }, + if (!HomePageRenderer::ShouldShowFirstTimeSetup()) { + IsEnabled = !IsEnabled; + if (IsEnabled) + ImGui::GetIO().ClearInputKeys(); // Prevent toggle key from remaining "held" in ImGui after open. + } + } }, { settings.SkipCompilationKey, [this, shaderCache]() { if (!ShouldSwallowInput() && shaderCache->IsCompiling()) shaderCache->backgroundCompilation = true; } }, { settings.EffectToggleKey, [shaderCache]() { shaderCache->SetEnabled(!shaderCache->IsEnabled()); } }, { settings.ShaderBlockPrevKey, [this, shaderCache]() { if (settings.EnableShaderBlocking) shaderCache->IterateShaderBlock(); } }, @@ -1115,7 +1115,7 @@ void Menu::ProcessInputEventQueue() bool Menu::IsCapturingHotkeyInput() const { return settingToggleKey || settingSkipCompilationKey || settingsEffectsToggle || - settingOverlayToggleKey || settingShaderBlockPrevKey || settingShaderBlockNextKey || settingWeatherEditorToggleKey; + settingOverlayToggleKey || settingShaderBlockPrevKey || settingShaderBlockNextKey || settingWeatherEditorToggleKey; } void Menu::addToEventQueue(KeyEvent e) From 748083f2c5f7fd84e5d0eb934e650b3a028d076c Mon Sep 17 00:00:00 2001 From: SkrubbySkrubInAShrub Date: Wed, 15 Apr 2026 18:09:41 +0200 Subject: [PATCH 5/5] fix: slightly more targetted and clean --- src/Menu.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Menu.cpp b/src/Menu.cpp index 38c3a9bbba..e53f1fcb59 100644 --- a/src/Menu.cpp +++ b/src/Menu.cpp @@ -1090,13 +1090,13 @@ void Menu::ProcessInputEventQueue() bool isHotkey = ShouldSwallowInput() && std::any_of(std::begin(hotkeys), std::end(hotkeys), [key](const auto* combo) { return InputCombo::MatchesKeyboardCombo(*combo, key); }); - // Swallow hotkey key-down events to avoid UI side effects, but always forward - // key-up events so ImGui state cannot get stuck in a held-key state. - // While recording a new hotkey, suppress keyboard forwarding so capture input - // does not trigger menu navigation; first-time setup Enter/Escape is allowed. - if ((!isHotkey || !event.IsPressed()) && (!wasCapturingHotkey || allowSetupCloseKey)) { + // Always forward key-up events. Suppress key-down during active hotkeys, + // and during hotkey capture except setup close keys (Enter/Escape). + const bool isKeyDown = event.IsPressed(); + const bool suppressForwarding = isKeyDown && (isHotkey || (wasCapturingHotkey && !allowSetupCloseKey)); + if (!suppressForwarding) { // DirectInput loses key-up events after alt-tab; validate against OS state. - bool pressed = event.IsPressed() && (GetAsyncKeyState(key) & Constants::KEY_PRESSED_MASK); + bool pressed = isKeyDown && (GetAsyncKeyState(key) & Constants::KEY_PRESSED_MASK); io.AddKeyEvent(Util::Input::VirtualKeyToImGuiKey(key), pressed); if (key == VK_LCONTROL || key == VK_RCONTROL)