From 254557f94544fe8841a4e9422eee9228e7ed4152 Mon Sep 17 00:00:00 2001 From: srdusr <99972264+srdusr@users.noreply.github.com> Date: Thu, 3 Apr 2025 22:35:00 +0200 Subject: Fix border corner rendered as a solid wedge instead of a ring round_top_corners/round_bottom_corners only ever cut pixels *outside* the shared corner radius (the rounded outer silhouette). Nothing cut anything *inside* it, so a border strip's own "extra" rows (present whenever corner_radius > border_width) stayed a solid filled disk out to the centre column/row, then hit clip_middle_beyond_thickness's hard, unblended rectangular cut right at the disk's own most opaque point - a clean right-angle step, not a curve. Confirmed live, zoomed: a real square notch bitten into an otherwise smooth arc, reported as "squares on the inside corners of each vertex." Added carve_inner_corner_pixel, the same smoothstep falloff as the existing outer cut but inverted (cuts near the centre instead of far from it), applied at radius - border_width so the corner becomes a genuine ring of ~border_width visible thickness tapering smoothly to transparent, instead of a filled wedge. Only render_border_top/ render_border_bottom pass an inner_radius; the titlebar's own corner and the lock-screen box keep their existing solid-disk behaviour, which is correct for a single flat-coloured panel with nothing of a different colour underneath needing to show through. Also generalizes round_top_corners with an explicit center_col parameter, mirroring the existing center_row shift: the titlebar's own corner circle was never shifted horizontally to match the border strip's (only vertically), leaving a border_width-wide sliver of the titlebar's own misaligned curve poking through at the seam. border_top_and_titlebar_corners_meet_without_a_seam and border_top_curve_actually_closes_within_the_side_strips_own_width updated to match: both now compare the correct corresponding columns (the titlebar's own buffer starts border_width columns inside the border strip's), and the latter no longer demands exact 255 opacity at a point that legitimately sits within the new inner cut's own antialiasing band. --- crates/wayland/src/decoration/border.rs | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'crates/wayland/src/decoration/border.rs') diff --git a/crates/wayland/src/decoration/border.rs b/crates/wayland/src/decoration/border.rs index 472ef3b..9a2ed91 100644 --- a/crates/wayland/src/decoration/border.rs +++ b/crates/wayland/src/decoration/border.rs @@ -71,7 +71,14 @@ pub fn render_border_top(width: u32, thickness: u32, color: (u8, u8, u8), radius for px in buf.chunks_exact_mut(4) { px.copy_from_slice(&bg); } - round_top_corners(&mut buf, width, height, radius, radius as i32); + // `Some(radius - thickness)`: without this, the corner stayed a solid + // filled disk out to the centre column/row instead of a proper ring -- + // see `corners::carve_inner_corner_pixel`'s own doc comment for the + // full story (reported live as "squares on the inside corners"). + // `None` when `radius <= thickness` - no ring to carve, the corner is + // already exactly `thickness` px wide at most. + let inner_radius = (radius as usize > thickness).then(|| radius - thickness as u32); + round_top_corners(&mut buf, width, height, radius, radius as i32, radius as i32, inner_radius); clip_middle_beyond_thickness(&mut buf, width, radius as usize, thickness..height); buf } @@ -127,7 +134,10 @@ pub fn render_border_bottom(width: u32, thickness: u32, color: (u8, u8, u8), rad // real corner. `render_border_top` gets `radius` used unshifted here // for the same reason it does: this buffer's own outermost row is // genuinely the true tip of the shape. - round_bottom_corners(&mut buf, width, height, radius); + // See `render_border_top`'s own matching comment for why this needs an + // inner radius too. + let inner_radius = (radius as usize > thickness).then(|| radius - thickness as u32); + round_bottom_corners(&mut buf, width, height, radius, inner_radius); // Extra rows sit above the original `thickness`, not below - the // bottom strip's curve resolves going *up* into content, the mirror of // the top strip's resolving *down* into it. See -- cgit v1.2.3