From c7f89e5cd32c3eb40cce83a7d48476cf785123e5 Mon Sep 17 00:00:00 2001 From: DanS Date: Sat, 4 Jul 2026 14:14:27 -0500 Subject: [PATCH] feat(security): live-blur backdrop for the lock screen (Phase 4) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The security DIALOGS (encrypt/decrypt/change-passphrase/remove-encryption, PIN set/change/remove) already adopted the blur backdrop via the Phase 2 flip (they use BeginOverlayDialog). This finishes Phase 4 by giving the bespoke lock screen the same live-blur backdrop over the wallet content — restyle only, auth logic (PIN/passphrase input, attempt counting, lockout timer) untouched. The lock screen previously defaulted to backdrop-alpha=0 (wallet fully visible behind the card); the blur now obscures it — a privacy improvement as well as a consistency one. Capture-once on lock-open + resize (frame-gap detected via the shared BlurCaptureStateFor), MarkBlurOverlayDrawn drives the theme-effect suppression + acrylic re-capture on unlock. The opaque base in DrawFullWindowBlurBackdrop guarantees the wallet is obscured even if blur is unavailable (low-spec / acrylic-off / capture failure) — no content leak. UV mapping is screen-space, so the content-area sub-rect blurs the correct region. Needs GUI verification of every auth path (PIN/passphrase unlock, lockout). Co-Authored-By: Claude Opus 4.8 (1M context) --- src/app_security.cpp | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/src/app_security.cpp b/src/app_security.cpp index 04d4976..aa8a8ee 100644 --- a/src/app_security.cpp +++ b/src/app_security.cpp @@ -771,11 +771,29 @@ void App::renderLockScreen() { ImVec2 winPos = ImGui::GetWindowPos(); ImVec2 winSize = ImGui::GetWindowSize(); - // Optional backdrop (0 = no darkening) - float backdropAlpha = ui::schema::UI().drawElement("screens.lock-screen", "backdrop-alpha").opacity; - if (backdropAlpha > 0.0f) { - ImU32 backdropCol = IM_COL32(0, 0, 0, (int)(255 * backdropAlpha)); - dl->AddRectFilled(winPos, ImVec2(winPos.x + winSize.x, winPos.y + winSize.y), backdropCol); + // Live-blur backdrop over the wallet content while locked — matches the app's modal look AND + // obscures the wallet for privacy (the old backdrop defaulted to 0 = fully visible). Capture-once + // on lock-open + resize; the opaque base inside DrawFullWindowBlurBackdrop guarantees the wallet + // is obscured even when the blur is unavailable (low-spec / acrylic-off / first frame / capture + // failure), so this can't leak content. Purely visual — the auth logic below is untouched. + ImVec2 winMax(winPos.x + winSize.x, winPos.y + winSize.y); + { + BlurCaptureState& cap = BlurCaptureStateFor("##LockScreen"); + int frame = ImGui::GetFrameCount(); + bool justLocked = (cap.lastSeenFrame < frame - 1); + cap.lastSeenFrame = frame; + if (justLocked || cap.w != winSize.x || cap.h != winSize.y) cap.captureFrames = 3; + cap.w = winSize.x; cap.h = winSize.y; + CapturingBlurBackdropRef() = (cap.captureFrames > 0); + if (cap.captureFrames > 0) { + if (ImDrawCallback liveCap = ui::effects::ImGuiAcrylic::GetLiveCaptureCallback()) { + dl->AddCallback(liveCap, nullptr); + dl->AddCallback(ImDrawCallback_ResetRenderState, nullptr); + } + cap.captureFrames--; + } + DrawFullWindowBlurBackdrop(dl, winPos, winMax, /*allowBlur=*/!justLocked); + MarkBlurOverlayDrawn(nullptr); // suppress foreground theme-effect bleed + re-capture on unlock } // Card