git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commit68e4863b4a04ad2c1239363f40b228ab6e5e731e
parent398f965169
authorLucas Galante <[email protected]>
date2026-08-25 13:50
7b-2: window_silhouette_radius; RFC — nine clients migrated

The silhouette's effective radius (shared nominal x corner-span factor) as
a named scalar: PlateSpec::radii_for reads it, and apps whose root surface
paints through non-Plate prims (rounded_rect / border / legacy tuples)
read it directly instead of the un-spanned root_plate_corner_radius. RFC
7b-2 marked done with the A/B revision (migration IS the arc correction),
the cloud/test-interface skips, and the pane-emission deferral into 7c.

 docs/rfc-core-rebuild.md | 24 +++++++++++++++++++++---
 src/layout.rs            | 10 ++++++++++
 src/scene/paint.rs       |  3 +--
 3 files changed, 32 insertions(+), 5 deletions(-)

diff --git a/docs/rfc-core-rebuild.md b/docs/rfc-core-rebuild.md
index 29167b6..a94a5bc 100644
--- a/docs/rfc-core-rebuild.md
+++ b/docs/rfc-core-rebuild.md
@@ -2484,9 +2484,27 @@ Constraint respected: **each crate still builds standalone** — the new core is
       see (raw JSON-pointer reads, not getter calls) gained the canonical-first chain:
       `layout::window_corner_radius`'s shared-config read, and cce-grid's silhouette
       read.
-    - **7b-2 — pending.** Migrate the remaining clients' hand-rolled root plates onto
-      `PlateSpec` (per-repo, AE=0 each) and convert the designer's pane plate EMISSION
-      (not just radii) to specs. 7c builds on the role flip.
+    - **7b-2 — DONE (2026-08-25).** Nine clients migrated: files, terminal,
+      system-interface, authenticator, data-editor (Prim::Plate hand-rolls →
+      `plate_spec`, plus data-editor's concentric `corner_frame` now follows the
+      silhouette), and graph, fonts, color-editor, text-editor (non-Plate root emissions —
+      rounded_rect/border/legacy tuples — take their values from the spec via the new
+      `layout::window_silhouette_radius()` scalar, which `radii_for` also uses). A/B
+      revision: the original "AE=0 each" predates 7b-1's discovery that migrating IS a
+      correction — every app moved off the un-spanned radius, so corners change by
+      design. Verified: seven apps diff ONLY within 120px corner squares; the eighth
+      (system-interface, hardcoded r=12 → silhouette, the largest jump) also shifts the
+      perimeter roll's edge gradient, eyeball-confirmed as the arc correction.
+      Authenticator is values-only verification (never launch it in a shadow — it claims
+      the PolicyKit D-Bus name). SKIPPED deliberately: cce-cloud (overlay popup windows —
+      whether they share the decorated-window silhouette is an open question for 7c) and
+      cce-test-interface's `Backplate` gallery shim (a legacy-lookalike test fixture;
+      migrating it would defeat its purpose). Designer pane EMISSION: radii and the
+      nested-blur sentinel already flow from spec-derived values; full spec-OBJECT
+      emission is deferred into 7c, because pane plates carry focus tint and
+      widget-driven bevel styling `PlateSpec` does not yet model — detach will dictate
+      whether the spec grows those fields or the widget hooks stay authoritative.
+      7c builds on the role flip.
   - **7c — Detach/dock generalization.** Lift the designer's plate-corner control, collapse,
     and dock-drag onto `PlateSpec` so any app can offer them. The detached-window PROCESS model
     and sync channel (`default_project.json` polling) remain app policy — the toolkit provides
diff --git a/src/layout.rs b/src/layout.rs
index 6740ee2..fd739d0 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -1613,6 +1613,16 @@ pub fn window_corner_radius() -> f32 {
 /// ~1.5·r along the edge). Exactly 1 at n = 2. Applied to window-scale corners
 /// only — `Prim::Plate` and the renderer's window-corner clip — never to
 /// widget-scale radii, which must match the nominal-radius squircles around them.
+/// The window silhouette's EFFECTIVE corner radius: the shared nominal value
+/// widened by the corner-span factor — exactly the arc the compositor clips
+/// every decorated window with, and the radius a root plate's corners must
+/// wear (RFC Phase 7b; `PlateSpec::radii_for` uses it for window-flagged
+/// corners). Apps drawing root-surface geometry through non-Plate prims read
+/// this scalar directly.
+pub fn window_silhouette_radius() -> f32 {
+    window_corner_radius() * corner_span_factor()
+}
+
 pub fn corner_span_factor() -> f32 {
     let n = corner_shape();
     if n > 2.001 {
diff --git a/src/scene/paint.rs b/src/scene/paint.rs
index 71513d8..85ba269 100644
--- a/src/scene/paint.rs
+++ b/src/scene/paint.rs
@@ -84,8 +84,7 @@ impl PlateSpec {
     /// `plate_corner_radius`.
     pub fn radii_for(flags: (bool, bool, bool, bool)) -> Radii {
         let nominal = crate::layout::plate_corner_radius();
-        let window_r =
-            crate::layout::window_corner_radius() * crate::layout::corner_span_factor();
+        let window_r = crate::layout::window_silhouette_radius();
         let (tl, tr, br, bl) = flags;
         let pick = |on: bool| if on { window_r } else { nominal };
         (pick(tl), pick(tr), pick(br), pick(bl))