From 8008d885adaf1675ea03ee5edf10db0cffec9909 Mon Sep 17 00:00:00 2001 From: Nicholas Bly <73457207+NicholasBly@users.noreply.github.com> Date: Fri, 18 Sep 2026 18:22:48 -0400 Subject: [PATCH] Fix controller input leaking when exit prompt is open (#233) * Add exit prompt check to input blocking logic * Improve settings hint layout and exit handling Refactor settings input hint display and exit prompt logic. * Simplify input blocking with ApplyInputBlockState Refactored input blocking logic into ApplyInputBlockState function. --- runtime/src/settings_overlay.cpp | 37 +++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/runtime/src/settings_overlay.cpp b/runtime/src/settings_overlay.cpp index 8127eae..5de0d30 100644 --- a/runtime/src/settings_overlay.cpp +++ b/runtime/src/settings_overlay.cpp @@ -1213,15 +1213,20 @@ void DrawTopBar() { ImGui::GetBackgroundDrawList()->AddRectFilled(viewport->Pos, ImVec2(viewport->Pos.x + viewport->Size.x, viewport->Pos.y + viewport->Size.y), IM_COL32(0, 0, 0, 70)); + constexpr float kHintMargin = 10.0f; ImGui::SetNextWindowPos(ImVec2(viewport->Pos.x + viewport->Size.x * 0.5f, - viewport->Pos.y + viewport->Size.y - 24.0f), - ImGuiCond_Always, ImVec2(0.5f, 1.0f)); - ImGui::SetNextWindowBgAlpha(0.85f); + viewport->Pos.y + ImGui::GetFrameHeight() + kHintMargin), + ImGuiCond_Always, ImVec2(0.5f, 0.0f)); + ImGui::SetNextWindowBgAlpha(0.55f); if (ImGui::Begin("Settings input hint", nullptr, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing)) { - ImGui::TextUnformatted("Settings open - game controls disabled. Press F10 to return to the game."); + for (const char* line : {"Settings open - game controls disabled.", + "Press F10 to return to the game."}) { + ImGui::SetCursorPosX((ImGui::GetWindowWidth() - ImGui::CalcTextSize(line).x) * 0.5f); + ImGui::TextUnformatted(line); + } } ImGui::End(); if (!ImGui::BeginMainMenuBar()) return; @@ -1333,6 +1338,13 @@ void PersistDisplayModeIfChanged() { g_displayMode = active; RuntimeConfigFile::SetDisplayMode(std::string(kDisplayModeConfigNames[static_cast(active)])); } + +void ApplyInputBlockState() { + const bool blocked = controller_mapping_wizard::IsActive() || g_rebind.active || + g_exitPromptOpen || g_topBarVisible; + PADBlockInput(blocked); + InputBindings::SetInputBlocked(blocked); +} } // namespace void InitializeRuntimeSettings() noexcept { @@ -1380,6 +1392,7 @@ void HandleEvents(const AuroraEvent* events) noexcept { } if (!g_rebind.active && IsToggleKey(ev->sdl, SDL_SCANCODE_F10)) { SetTopBarVisible(!g_topBarVisible); + ApplyInputBlockState(); } if (!g_rebind.active && g_muteHotkey != PAD_KEY_INVALID && IsToggleKey(ev->sdl, static_cast(g_muteHotkey))) { @@ -1387,8 +1400,15 @@ void HandleEvents(const AuroraEvent* events) noexcept { AudioBackend::Instance().SetMuted(g_audioMuted); RuntimeConfigFile::SetAudioMuted(g_audioMuted); } - if (!g_rebind.active && !g_topBarVisible && IsToggleKey(ev->sdl, SDL_SCANCODE_ESCAPE)) { - g_exitPromptOpen = true; + if (!g_rebind.active && IsToggleKey(ev->sdl, SDL_SCANCODE_ESCAPE)) { + if (g_exitPromptOpen) { + g_exitPromptOpen = false; + } else if (g_topBarVisible) { + SetTopBarVisible(false); + } else { + g_exitPromptOpen = true; + } + ApplyInputBlockState(); } if (IsMouseActivity(ev->sdl)) { g_lastMouseActivity = Clock::now(); @@ -1436,10 +1456,7 @@ void Draw() noexcept { DrawTopBar(); DrawExitPrompt(); controller_mapping_wizard::Draw(); - // The wizard captures raw presses; keep them out of the game. - const bool inputBlocked = controller_mapping_wizard::IsActive() || g_rebind.active; - PADBlockInput(inputBlocked); - InputBindings::SetInputBlocked(inputBlocked); + ApplyInputBlockState(); DrawStartupScreen(); }