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

commit54e81d27475004b8109afbda0be392ad80855e9e
parent60d504c01a
authorLucas Galante <[email protected]>
date2026-07-30 12:07
refactor: relief material lives at style.surface.relief; add section depth key

bevel_depth / bevel_width move out of the compositor's window_manager
domain (which never consumed them) to style.surface.relief.depth/.width,
joining the other surface material styling; the old spellings stay
accepted as compat aliases. New style.container.section.depth (default
1.0) scales the params pane's section-well carve — wall width and channel
cap together — so sections can read deeper or shallower than the DE-wide
relief; past 1.0 the roll crosses the control groove by explicit choice.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/layout.rs                         | 20 ++++++++++++++++++--
 src/widget/container/parameters_bg.rs | 20 ++++++++++++++++----
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/src/layout.rs b/src/layout.rs
index b23155e..720c0b9 100644
--- a/src/layout.rs
+++ b/src/layout.rs
@@ -114,8 +114,13 @@ fn flatten_json_to_flat_props(val: &serde_json::Value, prefix: &str, flat_props:
                 "style.control.toggle.border_color" => "toggle_border_color",
                 "style.control.toggle.corner_radius" => "toggle_corner_radius",
                 "window_manager.light_source_position" => "light_source_position",
-                "window_manager.bevel_depth" => "bevel_depth",
-                "window_manager.bevel_width" => "bevel_width",
+                // The DE's relief material: canonical home style.surface.relief
+                // (these shade every bevel/boss/recess in the toolkit — the
+                // compositor never read them, so the old window_manager
+                // spelling survives only as a compat alias).
+                "style.surface.relief.depth" | "window_manager.bevel_depth" => "bevel_depth",
+                "style.surface.relief.width" | "window_manager.bevel_width" => "bevel_width",
+                "style.container.section.depth" => "section_depth",
                 "window_manager.bevel_shader" => "bevel_shader",
                 "window_manager.control_relief" => "control_relief",
                 "window_manager.corner_shape" => "corner_shape",
@@ -1404,6 +1409,17 @@ pub fn set_control_panel_gap(gap: f32) {
     }
 }
 
+/// The section carves' depth multiplier (`style.container.section.depth`,
+/// default 1.0): scales the params pane's section-well wall — width and step
+/// together — relative to the DE-wide relief material, so sections can read
+/// deeper or shallower than the controls around them. Values past 1.0 let the
+/// roll widen across the channel groove between the well wall and its packed
+/// controls; tune to taste.
+pub fn section_depth() -> f32 {
+    lazy_init_style_registry();
+    get_style_registry().read().unwrap().get_float("section_depth").unwrap_or(1.0)
+}
+
 pub fn section_padding() -> f32 {
     use std::sync::Once;
     static INIT: Once = Once::new();
diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index c13f9dd..de2a302 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -78,6 +78,16 @@ const SCROLL_ACTIVE_HOLD: f32 = 0.7;
 /// reliefs on either side (control bevel, section wall) shade the channel into a
 /// narrow 3D groove.
 const CHANNEL: f32 = 3.0;
+
+/// The section carve's wall width: the DE relief scaled by the section depth
+/// multiplier (`style.container.section.depth`), capped against the row height
+/// (safety) and the control channel — the channel cap scales WITH the
+/// multiplier, so deepening sections is an explicit choice to let the roll
+/// cross the groove.
+fn section_carve_depth(h: f32) -> f32 {
+    let sd = crate::layout::section_depth().max(0.0);
+    (crate::layout::bevel_width() * sd).min(h * 0.2).min(CHANNEL * sd)
+}
 /// Vertical pitch between consecutive rows — one channel; rows abut.
 const ROW_GAP: f32 = CHANNEL;
 /// How far a section's title box overhangs its header row upward, and the box's height.
@@ -1030,8 +1040,10 @@ impl ParametersBg {
             if let Some((cx, cy, cw, ch)) = content {
                 // Capped at the channel: the well's wall must roll off inside the
                 // groove between it and the controls packed one CHANNEL inside,
-                // not shade across their faces.
-                let depth = crate::layout::bevel_width().min(ch * 0.2).min(CHANNEL);
+                // not shade across their faces. `section_depth` scales wall and
+                // channel cap together — past 1.0 the roll crosses the groove
+                // by choice.
+                let depth = section_carve_depth(ch);
                 // Tab strip: the title box itself, sitting flush on the body's top
                 // edge (the header row above it stays plain plate), bottom open.
                 // A wall FADES OUT over the carve width approaching a suppressed
@@ -1075,7 +1087,7 @@ impl ParametersBg {
                     }
                 }
             } else {
-                let depth = crate::layout::bevel_width().min(th * 0.2).min(CHANNEL);
+                let depth = section_carve_depth(th);
                 out.push((tx, ty, tw, th, r4(SECTION_R), depth, false, all));
             }
         }
@@ -1193,7 +1205,7 @@ impl ParametersBg {
         for (title, content) in self.section_boxes() {
             let (tx, _ty, tw, _th) = title;
             if let Some((cx, cy, cw, ch)) = content {
-                let depth = crate::layout::bevel_width().min(ch * 0.2).min(CHANNEL);
+                let depth = section_carve_depth(ch);
                 let throat_r = tx + tw;
                 if cx + cw > throat_r + 2.0 * SECTION_FILLET_R {
                     out.push((