GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git
fix(tessellate): floor the plate/bevel corner cap at zero
`plate_push_raised` and `push_bevel_edge_vertices_banded` clamp their
radii (and the bevel thickness) to `min(width, height) / 2`. A rect that
has already been shrunk past its padding — a window dragged narrower than
its layout can hold — arrives with a NEGATIVE extent, and `f32::clamp`
with min 0 and a negative max panics rather than yielding a zero radius.
cce-data-editor died this way mid-resize at ~250px wide ("min > max, or
either was NaN. min = 0.0, max = -5.55"), with the frame inlined into
tessellate_display_list.
Floored, a degenerate rect degrades to a square, ringless plate. The
compositor now also refuses to configure a client below its xdg minimum
(cce-compositor), so the trigger is gone from interactive resizes; this
is the guard for every other path that can hand the tessellator a
negative rect.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
src/backend/window_runner.rs | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/src/backend/window_runner.rs b/src/backend/window_runner.rs
index 2a3c1f5..a503754 100644
--- a/src/backend/window_runner.rs
+++ b/src/backend/window_runner.rs
@@ -1308,7 +1308,9 @@ pub fn push_bevel_edge_vertices_banded(
kind: EdgeKind,
out: &mut Vec<Vertex>,
) {
- let cap = ww.min(h) * 0.5;
+ // Floored for the same reason as `plate_push_raised`'s cap: a negative
+ // extent must degrade to no ring, not panic in `clamp`.
+ let cap = (ww.min(h) * 0.5).max(0.0);
let (tl, tr, br, bl) = (
radii.0.clamp(0.0, cap),
radii.1.clamp(0.0, cap),
@@ -2623,7 +2625,10 @@ fn plate_push_raised(
material: [f32; 4],
scale_corners: bool,
) -> crate::vk::PlatePush {
- let cap = rect.width.min(rect.height) * 0.5;
+ // Floored: a rect already shrunk past its padding (a window dragged
+ // below what its layout can hold) has a NEGATIVE extent here, and
+ // `clamp(0.0, cap)` with a negative cap is a panic, not a zero radius.
+ let cap = (rect.width.min(rect.height) * 0.5).max(0.0);
let shape = crate::layout::corner_shape();
// For PLATES (`scale_corners`), widen the corner span by the
// curvature-match factor (see `layout::corner_span_factor`): the diagonal