feat(security): live-blur backdrop for the lock screen (Phase 4)

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) <noreply@anthropic.com>
This commit is contained in:
2026-07-04 14:14:27 -05:00
parent 34ded6b441
commit c7f89e5cd3

View File

@@ -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