From 2294453c938774b656db67b9b876306d60900c57 Mon Sep 17 00:00:00 2001 From: Jokin Date: Sun, 16 Aug 2026 02:31:27 +0200 Subject: [PATCH] Stage 3a: wrap the app in 7.css's .window.glass.active frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The app rendered a bare .title-bar with no .window around it, which is why the Aero frame, glass and drop shadow were missing and the title-bar controls sat permanently in their inactive colours: EVERY control-glyph rule in 7.css is keyed on `.title-bar.active` / `.window.active .title-bar`, and nothing ever set .active. - app.html's root is now `.window.glass`, so it picks up the 6px radius, the 1px frame, the `inset 0 0 0 1px #fff9` highlight, the drop shadow and the backdrop-filter glass layer. - The content below the title bar moved into `.window-body`, 7.css's recessed inner panel (6px inset + its own border) — the thing that gives a Win7 window its depth. - `.active` binds to a new `windowFocused` signal, seeded from document.hasFocus() and updated from window focus/blur. The webview receives those when the NATIVE window's focus changes, so no RPC is needed. Harness renders the shell focused and unfocused: active shows the red close button and crisp glyphs, inactive desaturates, matching the reference. Native window transparency (for the drop shadow and rounded corners to fall outside the window rather than being clipped by an opaque surface) is deliberately NOT in this commit — it is a native flag with a real chance of misbehaving on Linux, so it gets its own change and a real-app check. Co-Authored-By: Claude --- ui/dev/harness.html | 17 +++++++++++++---- ui/src/app/app.html | 26 +++++++++++++++++--------- ui/src/app/app.ts | 8 ++++++++ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/ui/dev/harness.html b/ui/dev/harness.html index 4497084..fdbdfef 100644 --- a/ui/dev/harness.html +++ b/ui/dev/harness.html @@ -51,9 +51,9 @@
-
ours — bare .title-bar, no wrapper
+
ours — app.html shell (active above, inactive below)
-
+
miniSCP
@@ -62,9 +62,18 @@
-
-

No frame, no shadow, no glass.

+

Focused window.

+
+
+
+
miniSCP
+
+ + + +
+

Unfocused — chrome desaturates.

diff --git a/ui/src/app/app.html b/ui/src/app/app.html index 020fbbc..f5da772 100644 --- a/ui/src/app/app.html +++ b/ui/src/app/app.html @@ -1,4 +1,7 @@ -
+ +
@if (!rpc.available) {
@@ -10,17 +13,22 @@
} @else { - + - -
- - -
+ +
+ - - +
+ + +
+ + + +
} diff --git a/ui/src/app/app.ts b/ui/src/app/app.ts index 9b78da0..62a237d 100644 --- a/ui/src/app/app.ts +++ b/ui/src/app/app.ts @@ -45,6 +45,11 @@ import { UpdaterService } from './updater.service'; host: { '(window:keydown)': 'onWindowKeydown($event)', '(window:contextmenu)': 'blockContextMenu($event)', + // Aero greys an inactive window's title bar and controls. The webview gets + // DOM focus/blur when the native window's focus changes, so this needs no + // RPC — see the `active` binding on .window in app.html. + '(window:focus)': 'windowFocused.set(true)', + '(window:blur)': 'windowFocused.set(false)', }, }) export class App { @@ -62,6 +67,9 @@ export class App { /** The connection-manager window is open — this window is modal-blocked. */ readonly managerOpen = signal(false); + /** Drives `.window.active`: Aero desaturates an unfocused window's chrome. */ + readonly windowFocused = signal(document.hasFocus()); + /** Shown in the win7 title bar (no native titlebar to carry it). */ readonly appName = BRANDING.appName;