Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
refactor: one window corner radius — the border's dead key is gone
`style.surface.border.corner_radius` was read into
Layout::border_corner_radius, copied onto DecorationSpec and then
window::Border, and read by nothing: the content clip, the root plate,
the border ring, the frame and the corner discs all derive from
`style.surface.plate.root.corner_radius` (Window::root_plate_radius_base),
and the desktop grid's cells take the same value. A config could set the
border key to 8 against a root radius of 24 and nothing changed, which
made it look like a second knob that did not work. The field, its
default, both parse spellings, the Layout mapping and the two struct
fields are removed; the key is now ignored like any unknown one, and the
doc on `root_plate_corner_radius` says it is the one radius.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
src/server/config.rs | 36 +++++++++++++++++-------------------
src/server/window.rs | 4 +---
src/server/window_manager.rs | 2 --
3 files changed, 18 insertions(+), 24 deletions(-)
diff --git a/src/server/config.rs b/src/server/config.rs
index 39c05894..2663dd14 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -26,7 +26,6 @@ pub struct Layout {
/// Border color while the pointer hovers the border (the grab surface);
/// defaults to a lightened `border_color_focused`.
pub border_color_hover: [f32; 4],
- pub border_corner_radius: i32,
/// Visual gap between the 8 border zone segments.
pub border_segment_gap: i32,
/// How thin the resize-handle ring gets at the corners, as a fraction of
@@ -69,6 +68,15 @@ pub struct Layout {
pub grid_gap: i32,
pub border_blur: bool,
pub window_blur: bool,
+ /// THE window corner radius, logical px before span widening —
+ /// `style.surface.plate.root.corner_radius`, the same key cce-ui's
+ /// root plates and `window_corner_radius` read. Every rounded thing a
+ /// window has derives from it (`Window::root_plate_radius_base`): the
+ /// content clip, the root plate, the border ring, frame and corner
+ /// discs, and the desktop grid's cells (`background_spec`), so a tiled
+ /// window's arc sits on its cell's. There is no second radius: the
+ /// border's own `corner_radius` key was dead config and was removed
+ /// on 2026-09-28.
pub root_plate_corner_radius: i32,
pub overlay_behavior: String,
pub overlay_width: i32,
@@ -217,7 +225,6 @@ impl Default for Layout {
border_color: [62.0 / 255.0, 62.0 / 255.0, 62.0 / 255.0, 1.0],
border_color_focused: [62.0 / 255.0, 62.0 / 255.0, 62.0 / 255.0, 1.0],
border_color_hover: lighten_premultiplied([62.0 / 255.0, 62.0 / 255.0, 62.0 / 255.0, 1.0], HOVER_LIGHTEN),
- border_corner_radius: 0,
border_segment_gap: 4,
border_taper: 0.35,
border_handle_width: 32.0,
@@ -606,8 +613,6 @@ pub struct SurfaceConfig {
/// `None` falls back to a lightened `border_color_focused`.
#[serde(default)]
pub border_color_hover: Option<String>,
- #[serde(default = "default_border_corner_radius")]
- pub border_corner_radius: i64,
#[serde(default = "default_border_segment_gap")]
pub border_segment_gap: i64,
#[serde(default = "default_border_taper")]
@@ -723,7 +728,6 @@ impl Default for SurfaceConfig {
border_color: default_border_color(),
border_color_focused: None,
border_color_hover: None,
- border_corner_radius: default_border_corner_radius(),
border_segment_gap: default_border_segment_gap(),
border_taper: default_border_taper(),
border_handle_width: default_border_handle_width(),
@@ -834,10 +838,6 @@ fn default_border_color() -> String {
"#3e3e3e".to_string()
}
-fn default_border_corner_radius() -> i64 {
- 0
-}
-
fn default_border_taper() -> f64 { 0.35 }
fn default_border_handle_width() -> f64 { 32.0 }
fn default_border_overlap_opacity() -> f64 { 0.4 }
@@ -2239,11 +2239,13 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
surface.border_color_hover = Some(val.to_string());
}
}
- "corner_radius" => {
- if let Some(val) = entry.value().as_i64() {
- surface.border_corner_radius = val;
- }
- }
+ // No `corner_radius` here: the border
+ // ring, its discs and the frame take the
+ // ONE window radius, `plate.root.
+ // corner_radius` (see `Layout::
+ // root_plate_corner_radius`). The key was
+ // read into dead config until 2026-09-28
+ // and is ignored now, like any unknown one.
"segment_gap" => {
if let Some(val) = entry.value().as_i64() {
surface.border_segment_gap = val;
@@ -2436,7 +2438,6 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
surface.border_color = get_child_arg_string(node, "border_color", &default_border_color());
surface.border_color_focused = get_child_arg_string_opt(node, "border_color_focused");
surface.border_color_hover = get_child_arg_string_opt(node, "border_color_hover");
- surface.border_corner_radius = get_child_arg_i64(node, "border_corner_radius", default_border_corner_radius());
surface.border_segment_gap = get_child_arg_i64(node, "border_segment_gap", default_border_segment_gap());
surface.border_corner_length = get_child_arg_i64(node, "border_corner_length", 0);
surface.cloud_position_default = get_child_arg_vec2i_opt(node, "cloud_position_default");
@@ -2635,7 +2636,6 @@ pub fn parse_config(path: &str, state: &mut crate::window_manager::WindowManager
.as_deref()
.map(parse_hex_color_rgba)
.unwrap_or_else(|| lighten_premultiplied(state.layout.border_color_focused, HOVER_LIGHTEN));
- state.layout.border_corner_radius = config.surface.border_corner_radius as i32;
state.layout.border_segment_gap = config.surface.border_segment_gap.max(0) as i32;
// Clamped at 1: past that the corners would be THICKER than the middle,
// which is the moulding inside out.
@@ -3261,7 +3261,7 @@ style {
let content = r##"
style {
surface {
- border width=2 color="#ff8800" color_focused="#00ff88" color_hover="#88ffcc" corner_radius=10 segment_gap=6 corner_length=24
+ border width=2 color="#ff8800" color_focused="#00ff88" color_hover="#88ffcc" segment_gap=6 corner_length=24
}
}
"##;
@@ -3270,7 +3270,6 @@ style {
assert_eq!(config.surface.border_color, "#ff8800");
assert_eq!(config.surface.border_color_focused, Some("#00ff88".to_string()));
assert_eq!(config.surface.border_color_hover, Some("#88ffcc".to_string()));
- assert_eq!(config.surface.border_corner_radius, 10);
assert_eq!(config.surface.border_segment_gap, 6);
assert_eq!(config.surface.border_corner_length, 24);
@@ -3278,7 +3277,6 @@ style {
// and the hover color to a lightened focused color.
let config = parse_kdl_config("").unwrap();
assert_eq!(config.surface.border_width, 0);
- assert_eq!(config.surface.border_corner_radius, 0);
assert_eq!(config.surface.border_color_focused, None);
assert_eq!(config.surface.border_color_hover, None);
assert_eq!(config.surface.border_segment_gap, 4);
diff --git a/src/server/window.rs b/src/server/window.rs
index 571d07ea..61c294ea 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -104,12 +104,11 @@ pub struct Border {
pub color: [f32; 4],
/// Color while the pointer hovers the border (the grab surface).
pub hover_color: [f32; 4],
- pub corner_radius: i32,
}
impl Border {
pub fn none() -> Self {
- Self { edges: Edges::new(), width: 0, color: [0.0; 4], hover_color: [0.0; 4], corner_radius: 0 }
+ Self { edges: Edges::new(), width: 0, color: [0.0; 4], hover_color: [0.0; 4] }
}
}
@@ -4873,7 +4872,6 @@ unsafe extern "C" fn window_set_borders(
color,
// Protocol-set borders don't participate in hover highlighting.
hover_color: color,
- corner_radius: 0,
};
}
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index bd0b4a1e..ed9e9329 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -3898,7 +3898,6 @@ impl WindowManager {
decoration: crate::policy::api::DecorationSpec {
border_width: self.layout.border_width,
border_color: crate::policy::api::Rgba(self.layout.border_color),
- corner_radius: self.layout.border_corner_radius,
},
border_color_focused: crate::policy::api::Rgba(self.layout.border_color_focused),
overlay: crate::policy::arrange::OverlayParams {
@@ -4038,7 +4037,6 @@ impl WindowManager {
width: dec.border_width.max(0) as u32,
color: dec.border_color.0,
hover_color: self.layout.border_color_hover,
- corner_radius: dec.corner_radius.max(0),
};
}
if let Some(blur) = wp.blur {