GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
refactor: retire the plate.bevel_width override — every roll is relief.width
`style.surface.plate.bevel_width` was the pane roll's width of its own
until this morning's one-roll-width change, then an explicit override
for the rest of the day so a config carrying it kept its look. An
override that keeps working is a second width by another name, so the
loader no longer reads it: `plate_bevel_width()` is `layout::bevel_width`
and nothing else (the getter survives as the name the plate painters
call), the Option static and its setter are gone, and a config still
carrying the key is reported by path with the retired frost keys —
`retired_frost_keys` is `retired_surface_keys` now, and its warning
names both spellings. cce-relief's Save removes the key on migration.
The two material fixtures drop it; `the_pane_roll_is_the_relief_width`
loads a config that carries it and asserts the roll did not move.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
CLAUDE.md | 21 +++++------
src/bin/cce-relief.rs | 2 +-
src/color.rs | 99 ++++++++++++++++++++++-----------------------------
src/scene/material.rs | 8 ++---
4 files changed, 59 insertions(+), 71 deletions(-)
diff --git a/CLAUDE.md b/CLAUDE.md
index d627086..daf069a 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -407,7 +407,7 @@ What this buys, and where the code is heading:
(bool)false` off. The four keys it replaced (`blur` as the switch,
`radius`, `backdrop_compression`, `refraction`) were aliases for the rest
of that day and are RETIRED: the loader reports one it finds
- (`color::retired_frost_keys`, a warning naming the path) and does not read
+ (`color::retired_surface_keys`, a warning naming the path) and does not read
it — so a config with `blur=true` and no block is sharp, and the warning
is what says why. A material's `frost` child spells its compression
`compression` too; its `backdrop_compression` alias went with them.
@@ -570,8 +570,7 @@ Spellings that are NOT current, and what the loader does with each:
| `relief.height` / `.profile`, `relief.edge_height` / `.edge_profile` | aliases of `wall.*` / `edge.*`; the node wins when both are present |
| `window_manager.bevel_width` | alias of `relief.width` |
| `param.color` (+ top-level `plate_opacity`) | alias of `plate.pane.color`, multiplied by the opacity line |
-| `plate.bevel_width` | a legacy OVERRIDE of the roll width that still wins, reported once at load; unit-blind |
-| `plate.blur` / `.radius` / `.backdrop_compression` / `.refraction`, `frost.backdrop_compression` | RETIRED: reported by path, not read |
+| `plate.blur` / `.radius` / `.backdrop_compression` / `.refraction`, `frost.backdrop_compression`, `plate.bevel_width` | RETIRED: reported by path (`color::retired_surface_keys`), not read |
| `relief.wall.knobs` / `edge.knobs`, `profile_knobs` / `edge_knobs` | not style: cce-relief's own state (`~/.config/cce/cce-relief/state.kdl`); read once as a seed, removed on its next Save |
Where each rule is argued, by its lead-in: **Frost is one block** and
@@ -580,8 +579,8 @@ editor's knobs are not a style key** and **There is one roll width** under
"Units" (the geometry is unit-aware, which is why they sit there); the
`menu` block under "The context menu draws in its own popup surface".
`prefer_relief_spellings` in `layout.rs` is the one place the alias
-precedence is decided, `color::retired_frost_keys` the one place a retired
-key is named, and cce-relief's Save is the migration for all of it: it
+precedence is decided, `color::retired_surface_keys` the one place a retired
+key is named (`retired_surface_keys`), and cce-relief's Save is the migration for all of it: it
writes the current spellings and removes every superseded one it finds.
## The standard app — root plate, rungs, and the spacing ladder
@@ -815,11 +814,13 @@ pane plate, a bordered widget plate under relief (`append_widget_plate`, via
width of its own — `style.surface.plate.bevel_width`, default 6 against the
relief's 9.3 — so two pane plates in one window rolled over different widths
depending on which painter drew them, and no single key made a pane match the
-window lip. `plate_bevel_width()` now returns the relief width; the old key is
-an explicit override for a config that still carries it (reported once at
-load, and unit-blind where the relief width resolves lengths), and the test
-`the_pane_roll_is_the_relief_width_unless_a_legacy_key_overrides_it` pins the
-fallback.
+window lip. `plate_bevel_width()` now returns the relief width and nothing
+else: the old key was an explicit override for the rest of that day (so a
+config carrying it kept its look through the change) and is RETIRED — a
+config still carrying it is reported by path with the other retired surface
+keys and the key is not read, since an override that keeps working is a
+second width by another name. `the_pane_roll_is_the_relief_width` pins it,
+and cce-relief's Save removes the key.
**And the relief can leave the screen.** `scene/heightfield.rs` integrates the
height curves the shader only differentiates and samples a frame's plates into a
diff --git a/src/bin/cce-relief.rs b/src/bin/cce-relief.rs
index 8b78b1b..7bb39a2 100644
--- a/src/bin/cce-relief.rs
+++ b/src/bin/cce-relief.rs
@@ -1169,7 +1169,7 @@ impl BevelPopup {
// a retired key had it read as the seed (below) and loses it
// here, so a config migrates on its first save.
let frosted = self.material_frosted;
- let migrated = ["blur", "radius", "backdrop_compression", "refraction"]
+ let migrated = ["blur", "radius", "backdrop_compression", "refraction", "bevel_width"]
.iter()
.all(|k| cce_ui::config::remove_config_value(p, &format!("style.surface.plate.{k}")));
w("style.surface.relief.spec", &spec)
diff --git a/src/color.rs b/src/color.rs
index efd3a10..7e4aea2 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -659,18 +659,6 @@ fn parse_and_set_colors(content: &str) {
if let Some(t) = val.pointer("/style/surface/plate/border_thickness").and_then(|v| v.as_f64()) {
if let Ok(mut lock) = PLATE_BORDER_THICKNESS.write() { *lock = t as f32; }
}
- // The pane roll's OVERRIDE, not its width: absent (the shipped state), the
- // roll is `style.surface.relief.width` like every other roll. Read as an
- // Option so a key removed from config clears the override on reload.
- {
- let t = val.pointer("/style/surface/plate/bevel_width").and_then(|v| v.as_f64()).map(|t| t as f32);
- if t.is_some() {
- log::warn!(
- "style.surface.plate.bevel_width is a legacy override: the pane roll follows style.surface.relief.width when it is unset"
- );
- }
- if let Ok(mut lock) = PLATE_BEVEL_WIDTH.write() { *lock = t; }
- }
if let Some(c) = get_color("/style/surface/param/color") {
if let Ok(mut lock) = PARAM_BG_COLOR.write() { *lock = c; }
if let Ok(mut lock) = PANE_COLOR_WHOLE.write() { *lock = false; }
@@ -688,14 +676,14 @@ fn parse_and_set_colors(content: &str) {
// keys it replaced on 2026-09-28 (`blur` as the switch, `radius`,
// `backdrop_compression`, `refraction`) were read as aliases for the rest
// of that day and are retired: a config still carrying one is reported
- // (`retired_frost_keys`) and the key does nothing, because an alias that
+ // (`retired_surface_keys`) and the key does nothing, because an alias that
// keeps working is a second spelling forever. The block is absent → not
// frosted, which is what `blur=true` alone now amounts to; the report
// is what tells the user why their plates went sharp.
- let retired = retired_frost_keys(&val);
+ let retired = retired_surface_keys(&val);
if !retired.is_empty() {
log::warn!(
- "retired frost keys in config: {} — spell the frost as `plate {{ frost radius= compression= refraction= }}` (or a material's `frost` child with `compression`)",
+ "retired style.surface keys in config: {} — the frost is `plate {{ frost radius= compression= refraction= }}` (a material's `frost` child spells `compression`), and every roll's width is `relief width=`",
retired.join(", ")
);
}
@@ -779,14 +767,17 @@ fn parse_and_set_colors(content: &str) {
}
}
-/// The retired frost spellings a parsed config still carries, as the dotted
-/// paths a user would grep for: the four flat keys under `plate` (`blur`,
-/// `radius`, `backdrop_compression`, `refraction`) and `backdrop_compression`
-/// inside any `frost` child (the plate's, or a named material's), whose one
-/// name is `compression`. Empty for a clean config.
-pub fn retired_frost_keys(val: &serde_json::Value) -> Vec<String> {
+/// The retired `style.surface` spellings a parsed config still carries, as
+/// the dotted paths a user would grep for: the four flat frost keys under
+/// `plate` (`blur`, `radius`, `backdrop_compression`, `refraction`),
+/// `backdrop_compression` inside any `frost` child (the plate's, or a named
+/// material's), whose one name is `compression`, and `plate.bevel_width`,
+/// the pane roll's former width of its own (an override for the rest of
+/// 2026-09-28, retired that evening: every roll is `relief.width`). Empty
+/// for a clean config.
+pub fn retired_surface_keys(val: &serde_json::Value) -> Vec<String> {
let mut found = Vec::new();
- for k in ["blur", "radius", "backdrop_compression", "refraction"] {
+ for k in ["blur", "radius", "backdrop_compression", "refraction", "bevel_width"] {
if val.pointer(&format!("/style/surface/plate/{k}")).is_some() {
found.push(format!("style.surface.plate.{k}"));
}
@@ -1835,11 +1826,6 @@ pub fn set_root_plate_statusbar_blur(b: bool) {
static PLATE_COLOR: RwLock<Option<[f32; 4]>> = RwLock::new(Some([0.15, 0.15, 0.2, 0.95]));
static PLATE_BORDER_COLOR: RwLock<Option<[f32; 4]>> = RwLock::new(Some([0.3, 0.3, 0.4, 1.0]));
static PLATE_BORDER_THICKNESS: RwLock<f32> = RwLock::new(1.0);
-/// A legacy override of the pane plate's roll width
-/// (`style.surface.plate.bevel_width`); `None`, the shipped state, means the
-/// roll is [`crate::layout::bevel_width`]. See [`plate_bevel_width`].
-static PLATE_BEVEL_WIDTH: RwLock<Option<f32>> = RwLock::new(None);
-
pub fn plate_color() -> Option<[f32; 4]> {
load_colors_once();
style_read(&PLATE_COLOR)
@@ -1878,17 +1864,13 @@ pub fn set_plate_border_thickness(t: f32) {
/// pane plate rolled over different widths in one window, the designer's
/// panes could not be made to match its own window lip by editing one key,
/// and the edge height was expressed against a width the panes did not use.
-/// The old key survives as an explicit override for a config that still
-/// carries it, reported once at load; it is unit-blind (a bare number) where
-/// the relief width resolves lengths through the metric.
+/// The old key was an explicit override for the rest of that day and is
+/// RETIRED: a config still carrying it is reported by path
+/// (`retired_surface_keys`) and the key is not read. The getter survives
+/// as the name the plate painters call, so a caller need not know which
+/// registry key a roll is.
pub fn plate_bevel_width() -> f32 {
- load_colors_once();
- style_read(&PLATE_BEVEL_WIDTH).unwrap_or_else(crate::layout::bevel_width)
-}
-
-/// Install (or with `None` clear) the legacy pane-roll override.
-pub fn set_plate_bevel_width(t: Option<f32>) {
- style_write(&PLATE_BEVEL_WIDTH, t);
+ crate::layout::bevel_width()
}
/// How hard a frosted plate pulls its backdrop's LUMINANCE toward its own key
@@ -2238,42 +2220,47 @@ mod tests {
}
/// Rim refraction defaults OFF and clamps, like its neighbour.
- /// The pane plates roll over the relief width — the one roll width — and
- /// the legacy `plate.bevel_width` key is an override, not a second width.
+ /// The pane plates roll over the relief width — the one roll width —
+ /// and nothing, a loaded `plate.bevel_width` included, moves them off it.
#[test]
- fn the_pane_roll_is_the_relief_width_unless_a_legacy_key_overrides_it() {
- set_plate_bevel_width(None);
- assert_eq!(plate_bevel_width(), crate::layout::bevel_width(), "unset: the relief width");
- set_plate_bevel_width(Some(12.0));
- assert_eq!(plate_bevel_width(), 12.0, "the legacy key still wins while a config carries it");
- set_plate_bevel_width(None);
- assert_eq!(plate_bevel_width(), crate::layout::bevel_width(), "cleared: back to the relief width");
- }
-
- /// The four flat frost keys and the `backdrop_compression` spelling
- /// inside a `frost` child are reported by path; the block itself and a
- /// material's `compression` are not.
+ fn the_pane_roll_is_the_relief_width() {
+ let _lock = test_color_state_lock();
+ crate::layout::lazy_init_style_registry();
+ let _ = plate_blur();
+ reload_colors("style {\n surface {\n plate bevel_width=(f64)12.0\n }\n}\n");
+ assert_eq!(plate_bevel_width(), crate::layout::bevel_width(), "a retired key moves nothing");
+ assert_eq!(
+ retired_surface_keys(&crate::config::parse_kdl_to_json("style {\n surface {\n plate bevel_width=(f64)12.0\n }\n}\n")),
+ vec!["style.surface.plate.bevel_width"]
+ );
+ reload_colors("");
+ }
+
+ /// The four flat frost keys, the `backdrop_compression` spelling inside
+ /// a `frost` child and `plate.bevel_width` are reported by path; the
+ /// block itself and a material's `compression` are not.
#[test]
- fn retired_frost_keys_are_named_by_path_and_the_block_is_not() {
+ fn retired_surface_keys_are_named_by_path_and_the_block_is_not() {
let clean: serde_json::Value = serde_json::json!({ "style": { "surface": {
"plate": { "frost": { "radius": 5.5, "compression": 0.0, "refraction": 0.0 }, "color": "#6c6c7bf2" },
"material": { "glass": { "frost": { "compression": 0.6 } } }
} } });
- assert!(retired_frost_keys(&clean).is_empty());
+ assert!(retired_surface_keys(&clean).is_empty());
let old: serde_json::Value = serde_json::json!({ "style": { "surface": {
"plate": { "blur": true, "radius": 1.5, "backdrop_compression": 0.85, "refraction": 0.3,
- "frost": { "backdrop_compression": 0.2 } },
+ "bevel_width": 12.0, "frost": { "backdrop_compression": 0.2 } },
"material": { "glass": { "frost": { "backdrop_compression": 0.6 } } }
} } });
- assert_eq!(retired_frost_keys(&old), vec![
+ assert_eq!(retired_surface_keys(&old), vec![
"style.surface.plate.blur",
"style.surface.plate.radius",
"style.surface.plate.backdrop_compression",
"style.surface.plate.refraction",
+ "style.surface.plate.bevel_width",
"style.surface.plate.frost.backdrop_compression",
"style.surface.material.glass.frost.backdrop_compression",
]);
- assert!(retired_frost_keys(&serde_json::json!({})).is_empty());
+ assert!(retired_surface_keys(&serde_json::json!({})).is_empty());
}
#[test]
diff --git a/src/scene/material.rs b/src/scene/material.rs
index d4fb58c..1604e26 100644
--- a/src/scene/material.rs
+++ b/src/scene/material.rs
@@ -628,7 +628,7 @@ mod tests {
style {
surface {
param color=(rgba)"#05050840"
- plate bevel_width=(f64)12.0 {
+ plate {
frost compression=(f64)0.6 refraction=(f64)0.3
root corner_radius=(i64)24
}
@@ -646,7 +646,7 @@ mod tests {
frost compression=(f64)0.6 refraction=(f64)0.3
}
}
- plate material="glass" bevel_width=(f64)12.0 {
+ plate material="glass" {
root corner_radius=(i64)24
}
relief depth=(f64)0.08
@@ -700,7 +700,7 @@ mod tests {
/// (bool)false` is not. The four scattered keys it replaced (`blur`,
/// `radius`, `backdrop_compression`, `refraction`) are RETIRED, not
/// aliases: a config carrying one is reported by path
- /// (`color::retired_frost_keys`) and the key does nothing — `blur=true`
+ /// (`color::retired_surface_keys`) and the key does nothing — `blur=true`
/// alone is sharp, a flat `radius` moves nothing, and the old knob name
/// inside the block is ignored too.
#[test]
@@ -713,7 +713,7 @@ mod tests {
crate::color::reload_colors(&doc(plate));
(crate::color::plate_blur(), Frost::from_style())
};
- let retired = |plate: &str| crate::color::retired_frost_keys(&crate::config::parse_kdl_to_json(&doc(plate)));
+ let retired = |plate: &str| crate::color::retired_surface_keys(&crate::config::parse_kdl_to_json(&doc(plate)));
let frosted = |c: f32, r: f32, rad: f32| Frost::Frosted { compression: c, refraction: r, radius: rad };
assert_eq!(load("frost radius=(f64)3.0 compression=(f64)0.4 refraction=(f64)0.1"), (true, frosted(0.4, 0.1, 3.0)));
assert!(retired("frost radius=(f64)3.0 compression=(f64)0.4 refraction=(f64)0.1").is_empty());