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

commit3d5b4cf177401788cfae81499767b0ae6ea91346
parent11f3bfd72f
authorLucas Galante <[email protected]>
date2026-07-28 15:46
fix: every normal window casts the DE shadow, not just cce/ssd ones

The remaining "shadows aren't appearing properly" on claude-desktop:
after the ghost bugs were fixed there was simply NO shadow left — the
compositor gated want_shadow on ssd || cce-*, and claude (frameless
Electron) reserves CSD shadow margins in its buffer but leaves them
fully transparent, so it sat flat and hard-edged next to shadowed cce
siblings. want_shadow now keys on !status && !fullscreen only, giving
non-cce clients (claude, keepassxc, foot) the same scenefx drop shadow.
Verified in the nested harness: foot casts a soft down-right shadow
over the grid gaps.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/server/window.rs | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/src/server/window.rs b/src/server/window.rs
index 582bcdb..d81dcda 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -1949,7 +1949,11 @@ impl Window {
                 // (cf. the window_background rect, which scales it the same way).
                 (radius as f64 * self.scale) as i32,
             );
-            let want_shadow = !is_status && (self.wm_requested.ssd || is_cce_app) && !self.is_fullscreen();
+            // Every normal window casts the DE shadow. CSD apps don't draw
+            // their own here (frameless Electron reserves shadow margins but
+            // leaves them transparent), so without this, non-cce windows sat
+            // flat and shadowless next to shadowed cce siblings.
+            let want_shadow = !is_status && !self.is_fullscreen();
             self.update_shadow(width, height, radius, want_shadow);
             ffi::river_scene_node_set_opacity(self.tree as *mut ffi::wlr_scene_node, requested.opacity);
 
@@ -2326,7 +2330,11 @@ impl Window {
                     height,
                     (radius as f64 * self.scale) as i32,
                 );
-                let want_shadow = !is_status && (self.wm_requested.ssd || is_cce_app) && !self.is_fullscreen();
+                // Every normal window casts the DE shadow. CSD apps don't draw
+            // their own here (frameless Electron reserves shadow margins but
+            // leaves them transparent), so without this, non-cce windows sat
+            // flat and shadowless next to shadowed cce siblings.
+            let want_shadow = !is_status && !self.is_fullscreen();
                 self.update_shadow(width, height, radius, want_shadow);
             } else {
                 // Tearing the blur down: radius is irrelevant, the nodes are destroyed.