From 8846a96e3db303679abf40743ff2f6fe416e6b77 Mon Sep 17 00:00:00 2001 From: DanS Date: Thu, 9 Jul 2026 20:03:56 -0500 Subject: [PATCH] fix(sweep): flush leaked ImGui popup so scroll survives the full UI sweep MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The send-confirm surface renders via RenderSendConfirmPopup, which calls ImGui::OpenPopup() every frame — but BeginOverlayDialog is a plain window, so that popup is never consumed by a BeginPopup and is normally cleared only when a mouse click triggers ImGui's click-to-dismiss. The headless sweep never clicks and tears the surface down by just clearing its flag, so the orphaned popup lingered on OpenPopupStack past the end of the sweep. A stuck popup makes IsPopupOpen(AnyPopup) permanently true, which disables the smooth-scroll wheel capture in draw_helpers::ApplySmoothScroll — so after a sweep the mouse wheel stopped scrolling Settings / Explorer / Console (the tabs that use ApplySmoothScroll; native-scroll tabs were unaffected). Flush any lingering popup (ClosePopupToLevel) right after each surface's teardown, so it can't bleed into the next capture or survive the sweep. Confirmed via instrumentation: only 'popup-send-confirm' leaked (stack=1, once per skin); now flushed. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app_sweep.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/app_sweep.cpp b/src/app_sweep.cpp index 1fdbf24..052f560 100644 --- a/src/app_sweep.cpp +++ b/src/app_sweep.cpp @@ -22,6 +22,9 @@ #include "util/platform.h" #include "wallet/wallet_capabilities.h" +#include "imgui.h" +#include "imgui_internal.h" // ClosePopupToLevel / OpenPopupStack — flush stuck popups after teardown + #include #include @@ -465,6 +468,15 @@ void App::onScreenshotCaptured() { const SweepTarget& t = sweep_targets_[sweep_target_idx_]; if (t.teardown) t.teardown(*this); } + // Some surfaces leave an ImGui popup open (e.g. the send-confirm dialog calls OpenPopup but is + // torn down by just clearing its flag). The headless sweep never clicks, so ImGui's normal + // click-to-dismiss cleanup never runs and the popup lingers on the stack — which keeps + // IsPopupOpen(AnyPopup) true forever and disables the smooth-scroll wheel capture on + // Settings/Explorer/Console (draw_helpers::ApplySmoothScroll). Flush any lingering popup here so + // it can't bleed into the next surface's capture or survive past the sweep. + if (ImGuiContext* g = ImGui::GetCurrentContext(); g && g->OpenPopupStack.Size > 0) + ImGui::ClosePopupToLevel(0, false); + if (++sweep_target_idx_ >= static_cast(sweep_targets_.size())) { sweep_target_idx_ = 0; if (++sweep_skin_idx_ >= static_cast(sweep_skins_.size())) {