From 7921b2986b4b5c3964dcd8e14de199f5910d53eb Mon Sep 17 00:00:00 2001 From: Jokin Date: Sun, 16 Aug 2026 04:04:04 +0200 Subject: [PATCH] Let the frame corners be transparent; square them when maximized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The rounded frame only works if nothing paints an opaque full-bleed surface behind it — the area outside a border-radius is not painted by the element, so whatever sits underneath fills the corners. The frame comment asserted that invariant ("nothing but .window paints an opaque surface") but nothing enforced it: `html, body { background: var(--background) }` painted an opaque rectangle across the whole window, so the corners had a ground to show and the window read as a rectangle with a curve drawn on it. Reset html/body to transparent under .win7. The override has to be UNLAYERED, which is the non-obvious part: the html/body rule it overrides is itself unlayered, and unlayered declarations beat every @layer regardless of specificity, so the skinfix layer could not have reached it. Corrected the frame comment, which stated the invariant as if it were free. Maximized windows now drop the radius: a rounded maximized window leaves four notches of desktop in the screen corners. title-bar.ts publishes its existing `maximized` signal as `is-maximized` on its host, and the frame reads it off its own direct child with :has(), avoiding a second windowState subscription. 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 are zeroed; leaving one rounded would cut the corner off the square frame. NOT visually verified, and I could not verify it here: `import -window` captures the window's own pixels without compositing, so a genuinely transparent corner and an opaquely black one flatten to the same black in the capture, and forcing png32 just fills alpha with 1. XWayland's root window is not the composited desktop, and no compositor-level capture tool (grim/scrot/maim) is installed. Both rules are confirmed present in the built stylesheet; whether the corner now shows the desktop, and how the maximized state looks, need eyes on the actual screen. Co-Authored-By: Claude --- ui/src/app/title-bar/title-bar.ts | 4 +++ ui/src/styles.css | 41 ++++++++++++++++++++++++++++--- 2 files changed, 42 insertions(+), 3 deletions(-) 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