GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
feat: complementary shadow tint on focused carves; app-drivable rim flag
The focused well's shadow walls counter-tint with the complement of the
highlight accent (1 - rgb, at ~38%, alpha boosted like the highlight) —
the painter's warm-light/cool-shadow pairing, so the focused rim opposes
in hue as well as value. Untinted carves keep pure black shadows.
TreeList::focused goes pub: an app whose inline editors float over tree
rows (cce-data-editor) overrides it per input event with a focus-within
computation, since those editors take ctx focus while remaining visually
part of the tree pane.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/vk/shader2d.wgsl | 14 +++++++++-----
src/widget/container/treelist.rs | 9 ++++++---
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/src/vk/shader2d.wgsl b/src/vk/shader2d.wgsl
index 5031ab6..1f35dca 100644
--- a/src/vk/shader2d.wgsl
+++ b/src/vk/shader2d.wgsl
@@ -418,15 +418,19 @@ fn plate_shade(frag: vec2f, vcol: vec4f) -> vec4f {
let host_d = min(hb.z - abs(frag.x - hb.x), hb.w - abs(frag.y - hb.y));
let att = clamp(host_d / t, 0.0, 1.0) * wedge;
let v = (diff / flat_shade - 1.0 + curv + spec) * strength * att;
+ // p_spec_tint.w = 1 marks a tinted carve (a focused well); plates leave w at 0.
+ let tw = rrect_clip.p_spec_tint.w;
if (v >= 0.0) {
- // p_spec_tint.w = 1 marks a tinted carve (a focused well): the white
- // highlight screen mixes toward the tint color, slightly boosted so the
- // accent reads at the rim's low alphas. Plates leave w at 0.
- let tw = rrect_clip.p_spec_tint.w;
+ // Highlight: the white screen mixes toward the tint color, slightly
+ // boosted so the accent reads at the rim's low alphas.
let hl = mix(vec3f(1.0), rrect_clip.p_spec_tint.rgb, tw);
return vec4f(hl, min(v * (1.0 + 0.5 * tw), 1.0));
}
- return vec4f(0.0, 0.0, 0.0, min(-v, 1.0));
+ // Shadow: the complementary counter-tint (warm against a cool accent) at
+ // ~38%, so the focused rim's two sides oppose in hue as well as value —
+ // the painter's warm-light/cool-shadow trick. Untinted carves stay black.
+ let sh = (vec3f(1.0) - rrect_clip.p_spec_tint.rgb) * 0.38 * tw;
+ return vec4f(sh, min(-v * (1.0 + 0.5 * tw), 1.0));
}
struct VertexOutput {
diff --git a/src/widget/container/treelist.rs b/src/widget/container/treelist.rs
index 7eaa46b..d679622 100644
--- a/src/widget/container/treelist.rs
+++ b/src/widget/container/treelist.rs
@@ -179,9 +179,12 @@ pub struct TreeList {
pub right_clicked_section: Option<String>,
pub last_scroll_y: f32,
pub scrollbar_activity_timer: f32,
- /// Mirrors ctx focus (FocusIn/FocusOut + the grab in `mouse_body`) so `paint` —
- /// which has no UiContext — can light the recess rim when the tree is focused.
- focused: bool,
+ /// Lights the recess rim (`paint` has no UiContext, so this mirrors focus).
+ /// Driven by FocusIn/FocusOut by default; an app whose inline editors float
+ /// over the tree (cce-data-editor) overrides it per input event with its own
+ /// focus-within computation — those editors take ctx focus away from the
+ /// tree while still being, visually, part of the tree pane.
+ pub focused: bool,
pub deleted_key_path: Option<String>,
pub edit_box: crate::widget::Adapted<TextBox>,
pub editing_key_idx: Option<usize>,