diff --git a/ui/src/app/title-bar/title-bar.ts b/ui/src/app/title-bar/title-bar.ts index 8cf5f0e..b2277d7 100644 --- a/ui/src/app/title-bar/title-bar.ts +++ b/ui/src/app/title-bar/title-bar.ts @@ -28,6 +28,10 @@ import { RpcService } from '../rpc.service'; selector: 'app-title-bar', host: { class: 'title-bar electrobun-webkit-app-region-drag', + // Published so the FRAME can react: a maximized Win7 window has square + // corners. The window root reads this off its own child via :has() rather + // than subscribing to windowState a second time — see styles.css. + '[class.is-maximized]': 'maximized()', '(dblclick)': 'toggle()', }, template: ` diff --git a/ui/src/styles.css b/ui/src/styles.css index dc4f395..6ccb3ff 100644 --- a/ui/src/styles.css +++ b/ui/src/styles.css @@ -615,6 +615,22 @@ body { font-family: var(--w7-family); } +/* The win7 window is a FRAMELESS, natively transparent window whose only + opaque surface is meant to be `.window` — that is the whole premise of the + 6px rounded frame, since the area outside the radius must let the desktop + through. The unlayered `html, body { background: var(--background) }` above + broke that premise silently: it painted an opaque rectangle behind the + frame, so the rounded corners had an opaque ground filling them in and the + window read as a rectangle with a drawn-on curve. + Unlayered on purpose, same reason as the font-family rule: the html/body + background it overrides is itself unlayered, and unlayered declarations beat + every @layer regardless of specificity — a `skinfix` rule could not touch + it. Scoped to .win7 so the modern skin keeps its opaque ground. */ +html.win7, +html.win7 body { + background: transparent; +} + /* Neutralizers live in `skin`, NOT `skinfix`, and this is load-bearing: `revert-layer` rolls a property back to the previous LAYER, so from inside `skin` it lands on `utilities` (the Tailwind classes already in the @@ -724,9 +740,12 @@ body { } /* ---- Window frame ---- - The native window is transparent (chromeOptions in src/bun/windows.ts), so - nothing but .window paints an opaque surface — that is what lets the 6px - corner radius actually be transparent at the corners. + The native window is transparent (chromeOptions in src/bun/windows.ts), and + nothing but .window may paint an opaque surface — that is what lets the 6px + corner radius actually be transparent at the corners. That invariant is NOT + free: html/body paint an opaque background unlayered, and had to be reset + to transparent for .win7 (see the rule above @layer skin). Anything else + that paints full-bleed will fill the corners the same way. NO drop shadow, by request: 7.css's `2px 2px 10px 1px #000000b3` needed a margin gutter to fall into and still read heavy against a real desktop, so the frame keeps only the inset 1px glass highlight from that shorthand @@ -741,6 +760,22 @@ body { box-shadow: inset 0 0 0 1px #fffa; } + /* A maximized Win7 window has SQUARE corners — the radius only exists to let + the desktop show past a floating frame, and a rounded maximized window + leaves four notches of desktop in the screen corners. + Read off the title bar's own `is-maximized` (title-bar.ts publishes it on + its host) with :has(), so the frame reacts without a second windowState + subscription. .title-bar is a DIRECT child of .window — app-title-bar + carries the class on its host element, which is why `>` holds here. + The radius is declared three times in 7.css — on .window and on both the + ::before tint and the ::after glass layer — so all three must be zeroed or + a rounded pseudo-element still cuts the corner off the square frame. */ + .win7 .window.w7-frame:has(> .title-bar.is-maximized), + .win7 .window.w7-frame:has(> .title-bar.is-maximized)::before, + .win7 .window.w7-frame:has(> .title-bar.is-maximized)::after { + border-radius: 0; + } + /* 7.css's glass layer is `backdrop-filter: blur(4px)` on .window::after — but CSS cannot sample the DESKTOP behind a transparent native window (there is no backdrop to read), and WebKitGTK paints the unsampleable