git.lucas.co / cce-compositor
Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git

commit0ef29013f8db40a30d20b4ce8d8ef1b63ccb3e82
parent2256982f93
authorLucas Galante <[email protected]>
date2026-08-25 13:11
config: accept the canonical plate.root spelling for the root-plate style

cce-ui RFC Phase 7a (cce-ui@c8e0ab3): style.surface.plate.root.* is the
canonical spelling of what config.kdl called backplate. The compositor
reads the SILHOUETTE values (corner radius, color/opacity, blur) from that
block, so it must accept both spellings or a canonically-migrated config
silently breaks window clipping. Canonical wins when both are present;
legacy-only configs parse unchanged. Tested both ways.

 src/server/config.rs | 48 +++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 47 insertions(+), 1 deletion(-)

diff --git a/src/server/config.rs b/src/server/config.rs
index fba11e7..a319304 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -1897,7 +1897,22 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
                             }
                         }
                     }
-                    if let Some(backplate_node) = surface_children.nodes().iter().find(|n| n.name().value() == "backplate") {
+                    // RFC Phase 7a (cce-ui): `plate { root ... }` is the
+                    // CANONICAL spelling of the root-plate style; `backplate`
+                    // is its legacy read-alias. The compositor reads the
+                    // silhouette values from this block, so it must accept
+                    // both spellings or a canonically-migrated config.kdl
+                    // silently breaks window clipping. Canonical wins.
+                    let root_plate_node = surface_children
+                        .nodes()
+                        .iter()
+                        .find(|n| n.name().value() == "plate")
+                        .and_then(|n| n.children())
+                        .and_then(|c| c.nodes().iter().find(|n| n.name().value() == "root"))
+                        .or_else(|| {
+                            surface_children.nodes().iter().find(|n| n.name().value() == "backplate")
+                        });
+                    if let Some(backplate_node) = root_plate_node {
                         found_nested = true;
                         for entry in backplate_node.entries() {
                             if let Some(id) = entry.name() {
@@ -2556,6 +2571,37 @@ mod tests {
         }
     }
 
+    /// RFC Phase 7a: the canonical `plate { root ... }` spelling feeds the
+    /// same silhouette values as the legacy `backplate` node, and wins when
+    /// both are present.
+    #[test]
+    fn test_plate_root_canonical_spelling() {
+        let canonical = r##"
+style {
+    surface {
+        plate {
+            root color="#11223344" blur=0.5 corner_radius=21
+        }
+        backplate color="#ffffffff" blur=0.9 corner_radius=7
+    }
+}
+"##;
+        let config = parse_kdl_config(canonical).unwrap();
+        assert_eq!(config.surface.backplate_corner_radius, 21, "canonical wins");
+        assert_eq!(config.surface.backplate_color, "#11223344");
+
+        let legacy = r##"
+style {
+    surface {
+        backplate color="#55667788" corner_radius=9
+    }
+}
+"##;
+        let config = parse_kdl_config(legacy).unwrap();
+        assert_eq!(config.surface.backplate_corner_radius, 9, "legacy still reads");
+        assert_eq!(config.surface.backplate_color, "#55667788");
+    }
+
     #[test]
     fn test_parse_rgba() {
         let color = parse_hex_color_rgba("#a5cfc2");