Stage 3b: transparent native window so the Aero frame is a real frame

.window's 6px radius and its outer drop shadow are painted by the webview
OUTSIDE the window's own rectangle, so on an opaque surface they were simply
clipped — square corners, no shadow. chromeOptions now passes
`transparent: true`, the page paints no background of its own, and .window
takes a 6px margin as the gutter the shadow falls into (h-screen shrinks by the
same amount so the gutter does not produce a scrollbar).

Confirmed on Linux/WebKitGTK in a real run, which is the half the Firefox
harness cannot model:
  GTK: Created window without decorations (custom titlebar)
  GTK: Created transparent window
  GTK WebKit: Applied transparent background to webview

Also caught by the run rather than shipped: `transparent` is set in
chromeOptions, which openSecondaryWindow spreads too — so the editor and
connection-manager windows became transparent while still rendering bare
content, i.e. floating widgets on nothing. Both roots now take the same
.window.glass frame and their own windowFocused signal. The editor's blur
binding had to merge with the existing flushDraft() call; a duplicated host key
is a TS1117 build error rather than a merge, which is how it surfaced.

The old anti-flash <style> in index.html is gone with the opaque backgrounds it
guarded — windows are created hidden and revealed on dom-ready anyway.

Not handled yet: a maximized Win7 window has no radius, shadow or gutter. The
6px margin currently applies in every state.

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2026-08-16 02:35:44 +02:00
co-authored by Claude
parent 2294453c93
commit fe75904872
7 changed files with 44 additions and 24 deletions
@@ -1,5 +1,5 @@
<div class="flex h-screen flex-col bg-background text-foreground">
<!-- win7 skin only: frameless window. Fixed-size modal, so Close only. -->
<div class="window glass flex h-screen flex-col" [class.active]="windowFocused()">
<!-- Frameless window. Fixed-size modal, so Close only. -->
<app-title-bar
[title]="i18n.t('connMgr.title')"
[resizable]="false"
@@ -78,10 +78,16 @@ function fromDraft(d: Draft): SavedConnection {
host: {
'(window:keydown.escape)': 'onEscape()',
'(window:contextmenu)': 'blockContextMenu($event)',
// Aero desaturates an unfocused window's chrome — see .window.active.
'(window:focus)': 'windowFocused.set(true)',
'(window:blur)': 'windowFocused.set(false)',
},
})
export class ConnectionManager {
readonly i18n = inject(I18nService);
/** Drives `.window.active` on this window's Aero frame. */
readonly windowFocused = signal(document.hasFocus());
readonly store = inject(ConnectionsService);
readonly dialogs = inject(DialogsService);
private readonly rpc = inject(RpcService);
+3 -3
View File
@@ -1,4 +1,4 @@
<div class="flex h-screen flex-col bg-background text-foreground">
<div class="window glass flex h-screen flex-col" [class.active]="windowFocused()">
@if (!ctx) {
<div class="flex flex-1 items-center justify-center">
<div class="max-w-sm rounded-lg border border-border bg-card p-6 text-center shadow-sm">
@@ -10,8 +10,8 @@
</div>
</div>
} @else {
<!-- win7 skin only: the window is frameless. The X runs the SAME dirty
prompt as ⌘W and the Close button — never a raw window close. -->
<!-- The window is frameless. The X runs the SAME dirty prompt as ⌘W and
the Close button — never a raw window close. -->
<app-title-bar [title]="ctx.name + (dirty() ? ' *' : '')" (closeRequested)="requestClose()" />
<!-- header: on macOS this row IS the titlebar (hiddenInset + drag region),
elsewhere the native titlebar sits above and this is a compact strip -->
+8 -1
View File
@@ -35,12 +35,19 @@ const DRAFT_DEBOUNCE_MS = 400;
templateUrl: './editor-window.html',
host: {
'(window:keydown)': 'onKeydown($event)',
'(window:blur)': 'flushDraft()',
'(window:contextmenu)': 'blockContextMenu($event)',
// Aero desaturates an unfocused window's chrome — see .window.active.
// blur already had to flush the draft; both run from the one binding
// (a duplicated key is a TS1117 build error, not a merge).
'(window:focus)': 'windowFocused.set(true)',
'(window:blur)': 'flushDraft(); windowFocused.set(false)',
},
})
export class EditorWindow {
readonly i18n = inject(I18nService);
/** Drives `.window.active` on this window's Aero frame. */
readonly windowFocused = signal(document.hasFocus());
readonly ctx = EDITOR_CONTEXT;
readonly modLabel = MOD_LABEL;
readonly altLabel = ALT_LABEL;