fix(ui): theme-aware modal backdrop + full-window lock overlay

Address two GUI-review points:
1. Light themes no longer get a dark modal backdrop: DrawFullWindowBlurBackdrop
   now tints toward the theme app background (WithAlpha(Background(), ...)) for
   both the opaque base and the frost, so a light theme gets a light frosted
   backdrop and a dark theme a dark one. Fixes all blur overlays, not just the
   lock screen.
2. The lock screen now blurs the WHOLE window (sidebar included), not just the
   content area: renderLockScreen opens a full-viewport borderless overlay window
   (##LockOverlay, same pattern as the modal overlays / portfolio, opened from
   within ##ContentArea) with an input blocker, instead of drawing in the content
   child. Removed the theme-independent dark scrim (contradicted point 1).

Auth logic untouched. Needs GUI re-verify of all auth paths + that the whole
screen (incl. sidebar) obscures on lock and unlock returns cleanly.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-04 15:51:57 -05:00
parent 42df658275
commit 10289b33b5
2 changed files with 29 additions and 8 deletions

View File

@@ -767,9 +767,28 @@ void App::checkIdleMining() {
void App::renderLockScreen() { void App::renderLockScreen() {
using namespace ui::material; using namespace ui::material;
// Full-window lock overlay: cover the ENTIRE viewport (sidebar included) so the whole screen is
// obscured while locked, not just the tab-content area. A borderless, transparent, focused window
// over the main viewport (same pattern as the modal overlays; opened from within ##ContentArea,
// like the portfolio modal). Ended at the bottom of this function.
ImGuiViewport* vp = ImGui::GetMainViewport();
ImVec2 winPos = vp->Pos, winSize = vp->Size;
ImGui::SetNextWindowPos(winPos);
ImGui::SetNextWindowSize(winSize);
ImGui::SetNextWindowFocus();
ImGui::PushStyleColor(ImGuiCol_WindowBg, ImVec4(0, 0, 0, 0)); // transparent — we draw the backdrop
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
ImGui::Begin("##LockOverlay", nullptr,
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse |
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoSavedSettings);
ImDrawList* dl = ImGui::GetWindowDrawList(); ImDrawList* dl = ImGui::GetWindowDrawList();
ImVec2 winPos = ImGui::GetWindowPos(); // Consume input to everything behind (sidebar included) while locked.
ImVec2 winSize = ImGui::GetWindowSize(); ImGui::SetCursorScreenPos(winPos);
ImGui::InvisibleButton("##LockInputBlocker", winSize,
ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle);
// Live-blur backdrop over the wallet content while locked — matches the app's modal look AND // 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 // obscures the wallet for privacy (the old backdrop defaulted to 0 = fully visible). Capture-once
@@ -793,10 +812,6 @@ void App::renderLockScreen() {
cap.captureFrames--; cap.captureFrames--;
} }
DrawFullWindowBlurBackdrop(dl, winPos, winMax, /*allowBlur=*/!justLocked); DrawFullWindowBlurBackdrop(dl, winPos, winMax, /*allowBlur=*/!justLocked);
// A lock screen should read as a clearly-dimmed "locked" state; the blur alone is light in a
// light theme, which washes out the card. Add a theme-independent dark scrim over the blur so
// the card pops in both themes (standard lock-screen dimming).
dl->AddRectFilled(winPos, winMax, IM_COL32(6, 8, 16, 140));
MarkBlurOverlayDrawn(nullptr); // suppress foreground theme-effect bleed + re-capture on unlock MarkBlurOverlayDrawn(nullptr); // suppress foreground theme-effect bleed + re-capture on unlock
} }
@@ -1068,6 +1083,10 @@ void App::renderLockScreen() {
unlockWallet(std::string(lock_passphrase_buf_), timeout); unlockWallet(std::string(lock_passphrase_buf_), timeout);
} }
} }
ImGui::End(); // ##LockOverlay
ImGui::PopStyleVar(3); // WindowRounding, WindowBorderSize, WindowPadding
ImGui::PopStyleColor(); // WindowBg
} }
// =========================================================================== // ===========================================================================

View File

@@ -497,7 +497,9 @@ inline void DrawGlassPanel(ImDrawList* dl, const ImVec2& pMin,
inline void DrawFullWindowBlurBackdrop(ImDrawList* dl, const ImVec2& pMin, const ImVec2& pMax, inline void DrawFullWindowBlurBackdrop(ImDrawList* dl, const ImVec2& pMin, const ImVec2& pMax,
bool allowBlur = true) bool allowBlur = true)
{ {
dl->AddRectFilled(pMin, pMax, IM_COL32(9, 10, 16, 255)); // opaque base (shows through if the blur is faint) // Theme-aware tones: a light theme gets a light frosted backdrop, a dark theme a dark one — the
// backdrop tints toward the app background rather than a hardcoded dark.
dl->AddRectFilled(pMin, pMax, WithAlpha(Background(), 255)); // opaque base (fallback / faint-blur show-through)
if (allowBlur && IsBackdropActive() && !dragonx::ui::effects::isLowSpecMode() if (allowBlur && IsBackdropActive() && !dragonx::ui::effects::isLowSpecMode()
&& effects::ImGuiAcrylic::IsEnabled() && effects::ImGuiAcrylic::IsAvailable()) { && effects::ImGuiAcrylic::IsEnabled() && effects::ImGuiAcrylic::IsAvailable()) {
// Safe to use a strong custom radius here: while a full-window overlay is active every glass // Safe to use a strong custom radius here: while a full-window overlay is active every glass
@@ -507,7 +509,7 @@ inline void DrawFullWindowBlurBackdrop(ImDrawList* dl, const ImVec2& pMin, const
params.blurRadius = 64.0f; // strong full-window blur params.blurRadius = 64.0f; // strong full-window blur
params.fallbackColor.w = 1.0f; // full-strength blur so the live content reads params.fallbackColor.w = 1.0f; // full-strength blur so the live content reads
effects::ImGuiAcrylic::DrawAcrylicRect(dl, pMin, pMax, params, 0.0f); effects::ImGuiAcrylic::DrawAcrylicRect(dl, pMin, pMax, params, 0.0f);
dl->AddRectFilled(pMin, pMax, IM_COL32(6, 8, 18, 70)); // slight dim so the card reads as foreground dl->AddRectFilled(pMin, pMax, WithAlpha(Background(), 70)); // subtle theme-tinted frost so the card reads as foreground
} }
} }