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

commit092b91e9e5a673c92e94743ddcc253ef295ecf53
parent2fecf8a22e
authorLucas Galante <[email protected]>
date2026-06-30 19:46
fix: enable blur effect on window backplate and sync corner radius

 scenefx/render/fx_renderer/fx_pass.c               |  15 +-
 .../render/fx_renderer/shaders/corner_alpha.frag   |   6 +-
 scenefx/render/fx_renderer/shaders/quad_round.frag |  55 ++++----
 scenefx/types/scene/wlr_scene.c                    |  50 ++++++-
 src/server/config.rs                               |  48 ++++++-
 src/server/cursor.rs                               |  33 +++--
 src/server/output.rs                               | 115 ++++++++++++----
 src/server/output_manager.rs                       |   3 +
 src/server/seat.rs                                 |   4 +-
 src/server/window.rs                               |  52 ++++---
 src/server/window_manager.rs                       | 153 +++++++++++++++++++--
 src/server/wlroots_log_wrapper.c                   |  83 +++++++----
 src/server/xdg_toplevel.rs                         |  26 +++-
 13 files changed, 484 insertions(+), 159 deletions(-)

diff --git a/scenefx/render/fx_renderer/fx_pass.c b/scenefx/render/fx_renderer/fx_pass.c
index e0a7774..d7d0f4c 100644
--- a/scenefx/render/fx_renderer/fx_pass.c
+++ b/scenefx/render/fx_renderer/fx_pass.c
@@ -690,7 +690,7 @@ void fx_render_pass_add_rounded_rect(struct fx_gles_render_pass *pass,
 
 	struct fx_corner_fradii corners = fx_options->corners;
 	uniform_corner_radii_set(&shader.radius, &corners);
-	glUniform1f(shader.fade_inset, fx_options->fade_inset);
+	glUniform1f(shader.fade_inset, (float)fx_options->fade_inset / 1000.0f);
 
 	render(&box, &clip_region, renderer->shaders.quad_round.pos_attrib);
 	pixman_region32_fini(&clip_region);
@@ -805,7 +805,7 @@ void fx_render_pass_add_box_shadow(struct fx_gles_render_pass *pass,
 	// blending will practically always be needed (unless we have a madman
 	// who uses opaque shadows with zero sigma), so just enable it
 	setup_blending(WLR_RENDER_BLEND_MODE_PREMULTIPLIED);
-	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
 
 	glUseProgram(renderer->shaders.box_shadow.program);
 
@@ -825,7 +825,7 @@ void fx_render_pass_add_box_shadow(struct fx_gles_render_pass *pass,
 	render(&box, &clip_region, renderer->shaders.box_shadow.pos_attrib);
 	pixman_region32_fini(&clip_region);
 
-	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+	glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
 
 	pop_fx_debug(renderer);
 	TRACY_BOTH_ZONES_END;
@@ -1260,6 +1260,11 @@ void fx_render_pass_read_to_buffer(struct fx_gles_render_pass *pass,
 		goto done;
 	}
 
+	float saved_projection_matrix[9];
+	memcpy(saved_projection_matrix, pass->projection_matrix, sizeof(saved_projection_matrix));
+	matrix_projection(pass->projection_matrix, dst_buffer->buffer->width, dst_buffer->buffer->height,
+			WL_OUTPUT_TRANSFORM_NORMAL);
+
 	// Draw onto the dst_buffer
 	fx_framebuffer_bind(dst_buffer);
 	wlr_render_pass_add_texture(&pass->base, &(struct wlr_render_texture_options) {
@@ -1282,6 +1287,8 @@ void fx_render_pass_read_to_buffer(struct fx_gles_render_pass *pass,
 	});
 	wlr_texture_destroy(src_tex);
 
+	memcpy(pass->projection_matrix, saved_projection_matrix, sizeof(saved_projection_matrix));
+
 	// Bind back to the main WLR buffer
 	fx_framebuffer_bind(pass->buffer);
 
@@ -1350,7 +1357,7 @@ struct fx_gles_render_pass *fx_begin_buffer_pass(struct fx_framebuffer *buffer,
 	glBindFramebuffer(GL_FRAMEBUFFER, fbo);
 
 	glViewport(0, 0, wlr_buffer->width, wlr_buffer->height);
-	glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+	glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
 	glDisable(GL_SCISSOR_TEST);
 
 	pop_fx_debug(renderer);
diff --git a/scenefx/render/fx_renderer/shaders/corner_alpha.frag b/scenefx/render/fx_renderer/shaders/corner_alpha.frag
index 42c1413..c3f78fa 100644
--- a/scenefx/render/fx_renderer/shaders/corner_alpha.frag
+++ b/scenefx/render/fx_renderer/shaders/corner_alpha.frag
@@ -14,9 +14,10 @@ float corner_alpha(vec2 size, vec2 position, bool is_cutout,
 	}
 
 	vec2 relative_pos = (gl_FragCoord.xy - position);
+	relative_pos.y = size.y - relative_pos.y;
 
-	if (relative_pos.x < 0.0 || relative_pos.y < 0.0
-			|| relative_pos.x > size.x || relative_pos.y > size.y) {
+	if (relative_pos.x < -0.5 || relative_pos.y < -0.5
+			|| relative_pos.x > size.x + 0.5 || relative_pos.y > size.y + 0.5) {
 		if (is_cutout) {
 			return 1.0;
 		}
@@ -59,6 +60,7 @@ float corner_alpha(vec2 size, vec2 position, bool is_cutout,
 float corner_dist(vec2 size, vec2 position,
 		float radius_tl, float radius_tr, float radius_bl, float radius_br) {
 	vec2 relative_pos = (gl_FragCoord.xy - position);
+	relative_pos.y = size.y - relative_pos.y;
 
 	vec2 top_left = abs(relative_pos - size) - size + radius_tl;
 	vec2 top_right = abs(relative_pos - vec2(0, size.y)) - size + radius_tr;
diff --git a/scenefx/render/fx_renderer/shaders/quad_round.frag b/scenefx/render/fx_renderer/shaders/quad_round.frag
index 3e80e26..fb41842 100644
--- a/scenefx/render/fx_renderer/shaders/quad_round.frag
+++ b/scenefx/render/fx_renderer/shaders/quad_round.frag
@@ -1,8 +1,4 @@
-#ifdef GL_FRAGMENT_PRECISION_HIGH
 precision highp float;
-#else
-precision mediump float;
-#endif
 
 varying vec4 v_color;
 varying vec2 v_texcoord;
@@ -22,22 +18,39 @@ uniform float clip_radius_top_right;
 uniform float clip_radius_bottom_left;
 uniform float clip_radius_bottom_right;
 
+float get_dist(vec2 q, float radius);
 float corner_alpha(vec2 size, vec2 position, bool is_cutout,
 		float radius_tl, float radius_tr, float radius_bl, float radius_br);
-float corner_dist(vec2 size, vec2 position,
-		float radius_tl, float radius_tr, float radius_bl, float radius_br);
 
 void main() {
-	float quad_corner_alpha = corner_alpha(
-		size - 1.0,
-		position + 0.5,
-		false,
-		radius_top_left,
-		radius_top_right,
-		radius_bottom_left,
-		radius_bottom_right
+	vec2 relative_pos = (gl_FragCoord.xy - (position + 0.5));
+	relative_pos.y = size.y - relative_pos.y;
+
+	// Bounding box check
+	/* if (relative_pos.x < -0.5 || relative_pos.y < -0.5
+			|| relative_pos.x > size.x - 0.5 || relative_pos.y > size.y - 0.5) {
+		discard;
+	} */
+
+	float r_tl = radius_top_left > 0.0 ? radius_top_left + fade_inset : 0.0;
+	float r_tr = radius_top_right > 0.0 ? radius_top_right + fade_inset : 0.0;
+	float r_bl = radius_bottom_left > 0.0 ? radius_bottom_left + fade_inset : 0.0;
+	float r_br = radius_bottom_right > 0.0 ? radius_bottom_right + fade_inset : 0.0;
+
+	// Calculate corner distance
+	vec2 top_left = abs(relative_pos - (size - 1.0)) - (size - 1.0) + r_tl;
+	vec2 top_right = abs(relative_pos - vec2(0.0, size.y - 1.0)) - (size - 1.0) + r_tr;
+	vec2 bottom_left = abs(relative_pos - vec2(size.x - 1.0, 0.0)) - (size - 1.0) + r_bl;
+	vec2 bottom_right = abs(relative_pos) - (size - 1.0) + r_br;
+
+	float dist = max(
+		max(get_dist(top_left, r_tl), get_dist(top_right, r_tr)),
+		max(get_dist(bottom_left, r_bl), get_dist(bottom_right, r_br))
 	);
 
+	float result = smoothstep(-0.5, 0.5, dist);
+	float quad_corner_alpha = 1.0 - result;
+
 	// Clipping
 	float clip_corner_alpha = corner_alpha(
 		clip_size - 1.0,
@@ -51,19 +64,7 @@ void main() {
 
 	vec4 final_color = v_color;
 	if (fade_inset > 0.0) {
-		float r_tl = radius_top_left > 0.0 ? radius_top_left + fade_inset : 0.0;
-		float r_tr = radius_top_right > 0.0 ? radius_top_right + fade_inset : 0.0;
-		float r_bl = radius_bottom_left > 0.0 ? radius_bottom_left + fade_inset : 0.0;
-		float r_br = radius_bottom_right > 0.0 ? radius_bottom_right + fade_inset : 0.0;
-		float d = corner_dist(
-			size - 1.0,
-			position + 0.5,
-			r_tl,
-			r_tr,
-			r_bl,
-			r_br
-		);
-		float inside_dist = -d;
+		float inside_dist = 0.5 - dist;
 		float fade_factor = clamp(inside_dist / fade_inset, 0.0, 1.0);
 		final_color *= fade_factor;
 	}
diff --git a/scenefx/types/scene/wlr_scene.c b/scenefx/types/scene/wlr_scene.c
index 6ceefd5..aa3e1cd 100644
--- a/scenefx/types/scene/wlr_scene.c
+++ b/scenefx/types/scene/wlr_scene.c
@@ -40,6 +40,13 @@
 #define DMABUF_FEEDBACK_DEBOUNCE_FRAMES  30
 #define HIGHLIGHT_DAMAGE_FADEOUT_TIME   250
 
+#define CURSOR_HISTORY_SIZE 16
+static struct {
+	int x, y, w, h;
+	bool valid;
+} g_cursor_history[CURSOR_HISTORY_SIZE];
+static int g_cursor_history_index = 0;
+
 struct wlr_scene_tree *wlr_scene_tree_from_node(struct wlr_scene_node *node) {
 	assert(node->type == WLR_SCENE_NODE_TREE);
 	struct wlr_scene_tree *tree = wl_container_of(node, tree, node);
@@ -2028,7 +2035,7 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
 					.a = scene_rect->color[3],
 				},
 				.clip = &render_region,
-				.blend_mode = scene_rect->color[3] == 1.0f ?
+				.blend_mode = (scene_rect->color[3] == 1.0f && fx_corner_radii_is_empty(&rect_corners) && scene_rect->fade_inset == 0) ?
 					WLR_RENDER_BLEND_MODE_NONE : WLR_RENDER_BLEND_MODE_PREMULTIPLIED,
 			},
 			.clipped_region = {
@@ -2175,8 +2182,7 @@ static void scene_entry_render(struct render_list_entry *entry, const struct ren
 		struct wlr_scene_optimized_blur *scene_blur = wlr_scene_optimized_blur_from_node(node);
 		// Re-render the optimized blur buffer when needed. Retry rendering
 		// until there's a visible blur_node.
-		if (fx_pass->has_blur && is_scene_blur_enabled(&scene->blur_data)
-				&& scene_blur->dirty) {
+		if (fx_pass->has_blur && is_scene_blur_enabled(&scene->blur_data)) {
 			const float opacity = 1.0f;
 			enum wl_output_transform transform =
 				wlr_output_transform_invert(data->transform);
@@ -3350,7 +3356,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
 
 			if (apply_blur_region(node, &blur_data, &render_data, state,
 						&original_damage, &blur_padding_region)) {
-				should_compensate_blur = true;
+				should_compensate_blur = false;
 				fx_pass->has_blur = true;
 			}
 		}
@@ -3370,6 +3376,42 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
 			pixman_region32_intersect_rect(&render_data.damage, &render_data.damage,
 					0, 0, output->width, output->height);
 
+			// Add current software cursors to the history
+			struct wlr_output_cursor *cursor;
+			wl_list_for_each(cursor, &output->cursors, link) {
+				if (!cursor->enabled || !cursor->visible) {
+					continue;
+				}
+				double scale = output->scale;
+				int cx = (cursor->x - cursor->hotspot_x) * scale;
+				int cy = (cursor->y - cursor->hotspot_y) * scale;
+				int cw = cursor->width;
+				int ch = cursor->height;
+
+				g_cursor_history[g_cursor_history_index].x = cx;
+				g_cursor_history[g_cursor_history_index].y = cy;
+				g_cursor_history[g_cursor_history_index].w = cw;
+				g_cursor_history[g_cursor_history_index].h = ch;
+				g_cursor_history[g_cursor_history_index].valid = true;
+				g_cursor_history_index = (g_cursor_history_index + 1) % CURSOR_HISTORY_SIZE;
+			}
+
+			// Subtract all historical cursor regions from the blur padding region
+			for (int i = 0; i < CURSOR_HISTORY_SIZE; i++) {
+				if (!g_cursor_history[i].valid) {
+					continue;
+				}
+				pixman_region32_t cursor_reg;
+				pixman_region32_init_rect(&cursor_reg,
+						g_cursor_history[i].x - 16,
+						g_cursor_history[i].y - 16,
+						g_cursor_history[i].w + 32,
+						g_cursor_history[i].h + 32);
+				pixman_region32_subtract(&fx_pass->blur_padding_region,
+						&fx_pass->blur_padding_region, &cursor_reg);
+				pixman_region32_fini(&cursor_reg);
+			}
+
 			// Copy the surrounding content where the blur would display artifacts
 			// and draw it above the artifacts. Otherwise The old rendered
 			// content would be included into the new blur. This means that
diff --git a/src/server/config.rs b/src/server/config.rs
index 27e9977..481260b 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -47,6 +47,8 @@ pub struct Layout {
     pub desktop_gap_width: i32,
     pub desktop_cell_corner_radius: i32,
     pub desktop_cell_fade_inset: i64,
+    pub desktop_enable_solid_color: bool,
+    pub desktop_solid_color: [f32; 4],
     pub scenefx_optimized_blur: bool,
     pub status_backdrop_blur_ignore_transparent: bool,
     pub window_backdrop_blur_ignore_transparent: bool,
@@ -90,11 +92,13 @@ impl Default for Layout {
             desktop_gap_color: "#000000".to_string(),
             transparency_opacity: 0.9,
             window_opacity: true,
-            desktop_cell_color: [1.0, 1.0, 1.0, 0.05],
+            desktop_cell_color: [0.05, 0.05, 0.05, 0.05],
             desktop_grid_scale: 100.0,
             desktop_gap_width: 1,
             desktop_cell_corner_radius: 0,
             desktop_cell_fade_inset: 0,
+            desktop_enable_solid_color: false,
+            desktop_solid_color: [0.0, 0.0, 0.0, 1.0],
             scenefx_optimized_blur: true,
             status_backdrop_blur_ignore_transparent: true,
             window_backdrop_blur_ignore_transparent: true,
@@ -281,6 +285,10 @@ pub struct SurfacesConfig {
     pub desktop_cell_corner_radius: i64,
     #[serde(default = "default_desktop_cell_fade_inset")]
     pub desktop_cell_fade_inset: i64,
+    #[serde(default = "default_desktop_enable_solid_color")]
+    pub desktop_enable_solid_color: bool,
+    #[serde(default = "default_desktop_solid_color")]
+    pub desktop_solid_color: String,
     #[serde(default = "default_backplate_color")]
     pub backplate_color: String,
     #[serde(default = "default_backplate_blur")]
@@ -298,11 +306,13 @@ impl Default for SurfacesConfig {
             desktop_gap_width: default_desktop_gap_width(),
             desktop_cell_corner_radius: default_desktop_cell_corner_radius(),
             desktop_cell_fade_inset: default_desktop_cell_fade_inset(),
+            desktop_enable_solid_color: default_desktop_enable_solid_color(),
+            desktop_solid_color: default_desktop_solid_color(),
             backplate_color: default_backplate_color(),
             backplate_blur: default_backplate_blur(),
             backplate_corner_radius: default_backplate_corner_radius(),
         }
-    }
+     }
 }
 
 fn default_desktop_gap_color() -> String {
@@ -329,6 +339,14 @@ fn default_desktop_cell_fade_inset() -> i64 {
     0
 }
 
+fn default_desktop_enable_solid_color() -> bool {
+    false
+}
+
+fn default_desktop_solid_color() -> String {
+    "#000000".to_string()
+}
+
 fn default_backplate_color() -> String {
     "#151520e6".to_string()
 }
@@ -502,11 +520,12 @@ pub fn parse_hex_color_rgba(hex_str: &str) -> [f32; 4] {
             u8::from_str_radix(&hex[4..6], 16),
             u8::from_str_radix(&hex[6..8], 16),
         ) {
+            let alpha = a as f32 / 255.0;
             return [
-                r as f32 / 255.0,
-                g as f32 / 255.0,
-                b as f32 / 255.0,
-                a as f32 / 255.0,
+                (r as f32 / 255.0) * alpha,
+                (g as f32 / 255.0) * alpha,
+                (b as f32 / 255.0) * alpha,
+                alpha,
             ];
         }
     } else if hex.len() == 6 {
@@ -523,7 +542,7 @@ pub fn parse_hex_color_rgba(hex_str: &str) -> [f32; 4] {
             ];
         }
     }
-    [1.0, 1.0, 1.0, 0.05] // fallback default (5% white)
+    [0.05, 0.05, 0.05, 0.05] // fallback default (5% white)
 }
 
 pub fn parse_tiling_mode(s: &str) -> TilingMode {
@@ -1212,6 +1231,16 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
                                             surfaces.desktop_cell_fade_inset = val;
                                         }
                                     }
+                                    "enable_solid_color" => {
+                                        if let Some(val) = entry.value().as_bool() {
+                                            surfaces.desktop_enable_solid_color = val;
+                                        }
+                                    }
+                                    "solid_color" => {
+                                        if let Some(val) = entry.value().as_string() {
+                                            surfaces.desktop_solid_color = val.to_string();
+                                        }
+                                    }
                                     _ => {}
                                 }
                             }
@@ -1254,6 +1283,8 @@ fn parse_kdl_config(content: &str) -> Result<Config, String> {
             surfaces.desktop_gap_width = get_child_arg_i64(node, "desktop_gap_width", default_desktop_gap_width());
             surfaces.desktop_cell_corner_radius = get_child_arg_i64(node, "desktop_cell_corner_radius", default_desktop_cell_corner_radius());
             surfaces.desktop_cell_fade_inset = get_child_arg_i64(node, "desktop_cell_fade_inset", default_desktop_cell_fade_inset());
+            surfaces.desktop_enable_solid_color = get_child_arg_bool(node, "desktop_enable_solid_color", default_desktop_enable_solid_color());
+            surfaces.desktop_solid_color = get_child_arg_string(node, "desktop_solid_color", &default_desktop_solid_color());
             surfaces.backplate_color = get_child_arg_string(node, "backplate_color", &default_backplate_color());
             surfaces.backplate_blur = get_child_arg_f64(node, "backplate_blur", default_backplate_blur());
             surfaces.backplate_corner_radius = get_child_arg_i64(node, "backplate_corner_radius", default_backplate_corner_radius());
@@ -1321,6 +1352,8 @@ pub fn parse_config(path: &str, state: &mut crate::window_manager::WindowManager
     state.layout.desktop_gap_width = config.surfaces.desktop_gap_width as i32;
     state.layout.desktop_cell_corner_radius = config.surfaces.desktop_cell_corner_radius as i32;
     state.layout.desktop_cell_fade_inset = config.surfaces.desktop_cell_fade_inset;
+    state.layout.desktop_enable_solid_color = config.surfaces.desktop_enable_solid_color;
+    state.layout.desktop_solid_color = parse_hex_color_rgba(&config.surfaces.desktop_solid_color);
 
     state.layout.border_font_size = 11;
     state.layout.transition_duration = config.layout.transition_duration as i32;
@@ -1555,6 +1588,7 @@ mod tests {
             assert_eq!(server.wm.layout.desktop_gap_color, "#a5cfc2");
             assert_eq!(server.wm.layout.desktop_gap_width, 24);
             assert_eq!(server.wm.layout.desktop_cell_corner_radius, 8);
+            assert_eq!(server.wm.layout.desktop_enable_solid_color, true);
             println!("TEST_WM_STARTUP: {:?}", server.wm.startup);
             println!("TEST_WM_PATH: {:?}", std::env::var("PATH"));
         }
diff --git a/src/server/cursor.rs b/src/server/cursor.rs
index 933c980..f9b8d5f 100644
--- a/src/server/cursor.rs
+++ b/src/server/cursor.rs
@@ -468,10 +468,12 @@ impl Cursor {
             let mut is_window = false;
             match result.data {
                 SceneNodeDataVal::Window(window) => {
-                    if !(*window).is_status_bar() {
+                    if !(*window).is_status_bar() && !(*window).is_wallpaper() {
                         is_window = true;
                     }
-                    if (*window).tiling_mode != crate::tiling::TilingMode::Popup
+                    if !(*window).is_status_bar()
+                        && !(*window).is_wallpaper()
+                        && (*window).tiling_mode != crate::tiling::TilingMode::Popup
                         && (*window).tiling_mode != crate::tiling::TilingMode::Fullscreen
                         && (*window).tiling_mode != crate::tiling::TilingMode::Status
                         && (*server).wm.mode == crate::window_manager::WindowManagerMode::Normal
@@ -587,7 +589,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
     if let Some(result) = (*server).scene.at(lx, ly) {
         match result.data {
             SceneNodeDataVal::Window(window) => {
-                if !(*window).is_status_bar() {
+                if !(*window).is_status_bar() && !(*window).is_wallpaper() {
                     is_app_surface = true;
                     if (*window).tiling_mode == crate::tiling::TilingMode::Overlay {
                         is_overlay_window = true;
@@ -629,7 +631,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
                 }
             }
 
-            if !clicked_win.is_null() && !(*clicked_win).is_status_bar() {
+            if !clicked_win.is_null() && !(*clicked_win).is_status_bar() && !(*clicked_win).is_wallpaper() {
                 (*server).wm.stop_panning_animation();
                 let cursor_x = (*cursor.wlr_cursor).x;
                 let cursor_y = (*cursor.wlr_cursor).y;
@@ -670,7 +672,12 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
             let mut clicked_interactive = false;
             if let Some(result) = (*server).scene.at(lx, ly) {
                 match result.data {
-                    SceneNodeDataVal::Window(_) | SceneNodeDataVal::LayerSurface(_) | SceneNodeDataVal::ShellSurface(_) | SceneNodeDataVal::LockSurface(_) | SceneNodeDataVal::OverrideRedirect(_) => {
+                    SceneNodeDataVal::Window(window) => {
+                        if !(*window).is_wallpaper() {
+                            clicked_interactive = true;
+                        }
+                    }
+                    SceneNodeDataVal::LayerSurface(_) | SceneNodeDataVal::ShellSurface(_) | SceneNodeDataVal::LockSurface(_) | SceneNodeDataVal::OverrideRedirect(_) => {
                         clicked_interactive = true;
                     }
                 }
@@ -709,7 +716,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
                 }
             }
             
-            if !target_win.is_null() && !(*target_win).is_status_bar() {
+            if !target_win.is_null() && !(*target_win).is_status_bar() && !(*target_win).is_wallpaper() {
                 if (*target_win).tiling_mode != crate::tiling::TilingMode::Floating
                     && (*target_win).tiling_mode != crate::tiling::TilingMode::Popup
                     && (*target_win).tiling_mode != crate::tiling::TilingMode::Fullscreen
@@ -795,7 +802,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
             }
         }
 
-        if !border_target_win.is_null() && !(*border_target_win).is_status_bar() && (
+        if !border_target_win.is_null() && !(*border_target_win).is_status_bar() && !(*border_target_win).is_wallpaper() && (
             (*border_target_win).tiling_mode != crate::tiling::TilingMode::Popup
             && (*border_target_win).tiling_mode != crate::tiling::TilingMode::Fullscreen
         ) {
@@ -978,7 +985,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
             match result.data {
                 SceneNodeDataVal::Window(window) => {
                     clicked_something = true;
-                    if !(*window).is_status_bar() {
+                    if !(*window).is_status_bar() && !(*window).is_wallpaper() {
                         if !seat.object.is_null() {
                             if !(*window).object.is_null() {
                                 ffi::wl_resource_post_event(seat.object, 4, (*window).object);
@@ -1020,7 +1027,7 @@ unsafe extern "C" fn handle_button(listener: *mut ffi::wl_listener, data: *mut s
                     (*win_ptr).mode_locked = op.start_mode_locked;
                     
                     let server = seat.server;
-                    if !(*win_ptr).closed && !(*win_ptr).is_status_bar() {
+                    if !(*win_ptr).closed && !(*win_ptr).is_status_bar() && !(*win_ptr).is_wallpaper() {
                         let mut viewport_w = 1920.0;
                         let mut viewport_h = 1080.0;
                         let outputs_list = &mut (*server).om.outputs as *mut ffi::wl_list as *mut WlList;
@@ -1360,7 +1367,7 @@ unsafe extern "C" fn handle_touch_down(listener: *mut ffi::wl_listener, data: *m
         let mut is_overlay_window = false;
         match result.data {
             SceneNodeDataVal::Window(window) => {
-                if !(*window).is_status_bar() {
+                if !(*window).is_status_bar() && !(*window).is_wallpaper() {
                     is_app_surface = true;
                     if (*window).tiling_mode == crate::tiling::TilingMode::Overlay {
                         is_overlay_window = true;
@@ -1429,7 +1436,7 @@ unsafe extern "C" fn handle_touch_motion(listener: *mut ffi::wl_listener, data:
             let mut is_overlay_window = false;
             match result.data {
                 SceneNodeDataVal::Window(window) => {
-                    if !(*window).is_status_bar() {
+                    if !(*window).is_status_bar() && !(*window).is_wallpaper() {
                         is_app_surface = true;
                         if (*window).tiling_mode == crate::tiling::TilingMode::Overlay {
                             is_overlay_window = true;
@@ -1482,7 +1489,7 @@ unsafe extern "C" fn handle_touch_up(listener: *mut ffi::wl_listener, data: *mut
         if let Some(result) = (*server).scene.at(lx, ly) {
             match result.data {
                 SceneNodeDataVal::Window(window) => {
-                    if !(*window).is_status_bar() {
+                    if !(*window).is_status_bar() && !(*window).is_wallpaper() {
                         is_app_surface = true;
                         if (*window).tiling_mode == crate::tiling::TilingMode::Overlay {
                             is_overlay_window = true;
@@ -1682,7 +1689,7 @@ unsafe extern "C" fn handle_swipe_update(listener: *mut ffi::wl_listener, data:
                     hovered_win = window;
                 }
             }
-            if !hovered_win.is_null() && !(*hovered_win).is_status_bar() {
+            if !hovered_win.is_null() && !(*hovered_win).is_status_bar() && !(*hovered_win).is_wallpaper() {
                 seat.focus(Focus::Window(hovered_win));
                 if !seat.object.is_null() && !(*hovered_win).object.is_null() {
                     ffi::wl_resource_post_event(seat.object, 4, (*hovered_win).object);
diff --git a/src/server/output.rs b/src/server/output.rs
index 5f6039b..d3d844f 100644
--- a/src/server/output.rs
+++ b/src/server/output.rs
@@ -167,7 +167,9 @@ pub struct Output {
     pub last_grid_cell_fade_inset: i64,
     pub last_grid_gap_color: String,
     pub grid_is_low_res: bool,
+    pub last_grid_enable_solid_color: bool,
     pub grid_rect_pool: Vec<*mut ffi::wlr_scene_rect>,
+    pub grid_force_redraw_frames: u8,
 
     pub destroy: ffi::wl_listener,
     pub request_state: ffi::wl_listener,
@@ -418,7 +420,9 @@ impl Output {
             last_grid_cell_fade_inset: 0,
             last_grid_gap_color: String::new(),
             grid_is_low_res: false,
+            last_grid_enable_solid_color: false,
             grid_rect_pool: Vec::new(),
+            grid_force_redraw_frames: 0,
             destroy: std::mem::zeroed(),
             request_state: std::mem::zeroed(),
             frame: std::mem::zeroed(),
@@ -551,6 +555,24 @@ impl Output {
         }
 
         let wm = &(*self.server).wm;
+        if wm.layout.desktop_enable_solid_color {
+            ffi::wlr_scene_node_set_enabled(self.grid_tree as *mut ffi::wlr_scene_node, false);
+            for &rect in &self.grid_rect_pool {
+                ffi::wlr_scene_node_set_enabled(rect as *mut ffi::wlr_scene_node, false);
+            }
+            if !self.last_grid_enable_solid_color {
+                self.last_grid_enable_solid_color = true;
+            }
+            return;
+        }
+
+        ffi::wlr_scene_node_set_enabled(self.grid_tree as *mut ffi::wlr_scene_node, true);
+
+        if self.last_grid_enable_solid_color {
+            self.last_grid_enable_solid_color = false;
+            self.grid_force_redraw_frames = 3;
+        }
+
         let (viewport_w, viewport_h) = self.current.dimensions();
         let zoom = wm.desk_zoom;
 
@@ -570,22 +592,63 @@ impl Output {
         let cell_fade_inset = wm.layout.desktop_cell_fade_inset;
         let gap_color = wm.layout.desktop_gap_color.clone();
 
-        let structure_changed = self.last_grid_viewport_w != viewport_w
-            || self.last_grid_viewport_h != viewport_h
-            || self.last_grid_zoom != zoom
-            || self.last_grid_spacing != cell_size
-            || self.last_grid_gap_width != gap_size as i32
-            || self.last_grid_cell_color != cell_color
-            || self.last_grid_cell_corner_radius != cell_corner_radius
-            || self.last_grid_cell_fade_inset != cell_fade_inset
-            || self.last_grid_gap_color != gap_color;
+        if self.last_grid_zoom == 0.0 {
+            self.last_grid_zoom = zoom;
+        }
+
+        let c_w = self.last_grid_viewport_w != viewport_w;
+        let c_h = self.last_grid_viewport_h != viewport_h;
+        let c_z = self.last_grid_zoom != zoom;
+        let c_s = self.last_grid_spacing != cell_size;
+        let c_g = self.last_grid_gap_width != gap_size as i32;
+        let c_cc = self.last_grid_cell_color != cell_color;
+        let c_cr = self.last_grid_cell_corner_radius != cell_corner_radius;
+        let c_fi = self.last_grid_cell_fade_inset != cell_fade_inset;
+        let c_gc = self.last_grid_gap_color != gap_color;
+
+        let structure_changed = c_w || c_h || c_z || c_s || c_g || c_cc || c_cr || c_fi || c_gc;
+        if structure_changed {
+            self.grid_force_redraw_frames = 3;
+        }
 
-        let force_high_res = !structure_changed && self.grid_is_low_res;
+        let force_redraw = self.grid_force_redraw_frames > 0;
 
         let period_pixels = period * zoom;
 
-        if structure_changed || force_high_res {
+        // Apply modulo translation to the grid tree based on panning
+        let shift_x = -((wm.desk_pan_x * zoom).rem_euclid(period_pixels));
+        let shift_y = -((wm.desk_pan_y * zoom).rem_euclid(period_pixels));
+
+        let dest_x = self.sent.x + shift_x.round() as i32;
+        let dest_y = self.sent.y + shift_y.round() as i32;
+
+        log::debug!(
+            "draw_grid: structure_changed={}, force_redraw={}, force_redraw_frames={}, grid_is_low_res={}, last_zoom={}, zoom={}, dest=({}, {}), shift=({}, {}), pan=({}, {}), spacing={}, cell_size={}, fade_inset={}, cell_fade_inset={}",
+            structure_changed,
+            force_redraw,
+            self.grid_force_redraw_frames,
+            self.grid_is_low_res,
+            self.last_grid_zoom,
+            zoom,
+            dest_x,
+            dest_y,
+            shift_x,
+            shift_y,
+            wm.desk_pan_x,
+            wm.desk_pan_y,
+            self.last_grid_spacing,
+            cell_size,
+            self.last_grid_cell_fade_inset,
+            cell_fade_inset
+        );
+
+        if force_redraw {
+            if self.grid_force_redraw_frames > 0 {
+                self.grid_force_redraw_frames -= 1;
+            }
+
             let draw_low_res = self.last_grid_zoom != zoom;
+            log::debug!("Entering redraw block: draw_low_res={}, force_redraw_frames_left={}", draw_low_res, self.grid_force_redraw_frames);
 
             // Cache current parameters (excluding pan coordinates)
             self.last_grid_viewport_w = viewport_w;
@@ -622,6 +685,7 @@ impl Output {
                 if !rect.is_null() {
                     ffi::wlr_scene_node_set_position(rect as *mut ffi::wlr_scene_node, x, y);
                     ffi::river_scene_rect_set_corner_radius(rect, r);
+                    ffi::wlr_scene_rect_set_fade_inset(rect, 0);
                 }
                 pool_idx += 1;
                 rect
@@ -629,8 +693,8 @@ impl Output {
 
             // Draw the base level background rect (gap color)
             // Sized larger to allow shifting by up to one period
-            let bg_w = viewport_w + period_pixels.ceil() as i32;
-            let bg_h = viewport_h + period_pixels.ceil() as i32;
+            let bg_w = viewport_w + period_pixels.ceil().round() as i32;
+            let bg_h = viewport_h + period_pixels.ceil().round() as i32;
             let gap_color_arr = crate::config::parse_hex_color_rgba(&self.last_grid_gap_color);
             let _bg_rect = get_rect(bg_w, bg_h, gap_color_arr.as_ptr(), 0, 0, 0);
 
@@ -639,27 +703,22 @@ impl Output {
             let rows = (viewport_h as f64 / period_pixels).ceil() as i32 + 1;
 
             for col in 0..=cols {
-                let rel_x = (col as f64 * period_pixels) as i32;
-                let rw = (cell_size * zoom) as i32;
+                let rel_x = (col as f64 * period_pixels).round() as i32;
+                let rw = (cell_size * zoom).round() as i32;
                 if rw <= 0 {
                     continue;
                 }
 
                 for row in 0..=rows {
-                    let rel_y = (row as f64 * period_pixels) as i32;
-                    let rh = (cell_size * zoom) as i32;
+                    let rel_y = (row as f64 * period_pixels).round() as i32;
+                    let rh = (cell_size * zoom).round() as i32;
                     if rh <= 0 {
                         continue;
                     }
-                    let draw_fade = cell_fade_inset > 0 && !draw_low_res;
-                    let scaled_corner_radius = (cell_corner_radius as f64 * zoom) as i32;
+                    let scaled_corner_radius = (cell_corner_radius as f64 * zoom).round() as i32;
                     let cell_rect = get_rect(rw, rh, cell_color.as_ptr(), rel_x, rel_y, scaled_corner_radius);
                     if !cell_rect.is_null() {
-                        let inset_scaled = if draw_fade {
-                            (cell_fade_inset as f64 * zoom) as i32
-                        } else {
-                            0
-                        };
+                        let inset_scaled = (cell_fade_inset as f64 * zoom * 1000.0).round() as i32;
                         ffi::wlr_scene_rect_set_fade_inset(cell_rect, inset_scaled);
                     }
                 }
@@ -671,14 +730,10 @@ impl Output {
             }
         }
 
-        // Apply modulo translation to the grid tree based on panning
-        let shift_x = -((wm.desk_pan_x * zoom).rem_euclid(period_pixels));
-        let shift_y = -((wm.desk_pan_y * zoom).rem_euclid(period_pixels));
-
         ffi::river_scene_node_set_position_if_changed(
             self.grid_tree as *mut ffi::wlr_scene_node,
-            shift_x as i32,
-            shift_y as i32,
+            dest_x,
+            dest_y,
         );
 
         self.last_grid_pan_x = wm.desk_pan_x;
diff --git a/src/server/output_manager.rs b/src/server/output_manager.rs
index 4a1bd13..b43e0da 100644
--- a/src/server/output_manager.rs
+++ b/src/server/output_manager.rs
@@ -234,6 +234,9 @@ impl OutputManager {
                                 output.sent.x,
                                 output.sent.y,
                             );
+                            if (*server).wm.layout.desktop_enable_solid_color {
+                                ffi::wlr_scene_node_set_enabled(output.grid_tree as *mut ffi::wlr_scene_node, false);
+                            }
                         }
                     }
                     OutputStateValue::DisabledHard => {
diff --git a/src/server/seat.rs b/src/server/seat.rs
index dd00fd9..cda9ebd 100644
--- a/src/server/seat.rs
+++ b/src/server/seat.rs
@@ -304,8 +304,8 @@ impl Seat {
 
     pub unsafe fn focus(&mut self, new_focus: Focus) {
         if let Focus::Window(window) = new_focus {
-            if !window.is_null() && (*window).is_status_bar() {
-                log::info!("[FocusDebug] Seat::focus blocking focus to status bar window");
+            if !window.is_null() && ((*window).is_status_bar() || (*window).is_wallpaper()) {
+                log::info!("[FocusDebug] Seat::focus blocking focus to status bar/wallpaper window");
                 return;
             }
         }
diff --git a/src/server/window.rs b/src/server/window.rs
index 425faa8..9bc1d1f 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -274,6 +274,10 @@ impl Window {
         self.get_app_id_string().as_deref().map_or(false, |id| id.starts_with("cce-status"))
     }
 
+    pub unsafe fn is_wallpaper(&self) -> bool {
+        self.get_app_id_string().as_deref() == Some("cce-wallpaper")
+    }
+
 
     pub unsafe fn create(impl_type: WindowImpl, server: *mut Server) -> Result<*mut Self, &'static str> {
         let hidden_tree = (*server).scene.hidden_tree;
@@ -632,7 +636,7 @@ impl Window {
             return;
         }
         let app_id_str = self.get_app_id_string().unwrap_or_default();
-        if app_id_str.is_empty() || app_id_str.starts_with("cce-status") {
+        if app_id_str.is_empty() || app_id_str.starts_with("cce-status") || app_id_str == "cce-wallpaper" {
             return;
         }
         let title_str = self.get_title_string().unwrap_or_default();
@@ -697,14 +701,14 @@ impl Window {
         }
 
         let app_id_ptr = self.get_app_id();
-        let is_status_bar = if !app_id_ptr.is_null() {
+        let (is_status_bar, is_wallpaper) = if !app_id_ptr.is_null() {
             let app_id = std::ffi::CStr::from_ptr(app_id_ptr).to_string_lossy();
-            app_id.starts_with("cce-status")
+            (app_id.starts_with("cce-status"), app_id.as_ref() == "cce-wallpaper")
         } else {
-            false
+            (false, false)
         };
 
-        if is_status_bar {
+        if is_status_bar || is_wallpaper {
             self.tiling_mode = crate::tiling::TilingMode::Status;
         } else {
             let mut should_focus = true;
@@ -1490,7 +1494,8 @@ impl Window {
 
     pub unsafe fn notify_app_id(&mut self) {
         self.wm_scheduled.dirty_app_id = true;
-        if self.get_app_id_string().as_deref().map_or(false, |id| id.starts_with("cce-status")) {
+        let app_id_str = self.get_app_id_string();
+        if app_id_str.as_deref().map_or(false, |id| id.starts_with("cce-status") || id == "cce-wallpaper") {
             self.tiling_mode = crate::tiling::TilingMode::Status;
         }
         self.try_restore();
@@ -1539,24 +1544,23 @@ impl Window {
             if app_id.starts_with("cce-status") {
                 ignore_transparent = (*self.server).wm.layout.status_backdrop_blur_ignore_transparent;
             }
-            let scale = self.scale;
-            let geom_x = (self.rendering_requested.x as f64 * scale) as i32;
-            let geom_y = (self.rendering_requested.y as f64 * scale) as i32;
-            let geom_w = (self.rendering_sent.width as f64 * scale) as i32;
-            let geom_h = (self.rendering_sent.height as f64 * scale) as i32;
+            let width = (self.rendering_sent.width as f64 * self.scale) as i32;
+            let height = (self.rendering_sent.height as f64 * self.scale) as i32;
             ffi::river_scene_node_enable_blur(
-                self.surfaces.tree as *mut ffi::wlr_scene_node,
+                self.tree as *mut ffi::wlr_scene_node,
                 blur_enabled,
                 (*self.server).wm.layout.scenefx_optimized_blur,
                 ignore_transparent,
-                geom_x,
-                geom_y,
-                geom_w,
-                geom_h,
+                0,
+                0,
+                width,
+                height,
             );
             ffi::river_scene_node_set_opacity(self.tree as *mut ffi::wlr_scene_node, requested.opacity);
 
-            let radius = if requested.circular {
+            let radius = if self.is_fullscreen() {
+                0
+            } else if requested.circular {
                 let w = self.rendering_sent.width as i32;
                 let h = self.rendering_sent.height as i32;
                 w.min(h) / 2
@@ -1570,6 +1574,10 @@ impl Window {
                 self.surfaces.tree as *mut ffi::wlr_scene_node,
                 radius,
             );
+            ffi::river_scene_rect_set_corner_radius(
+                self.window_background,
+                radius,
+            );
 
             struct ScaleData {
                 scale: f64,
@@ -1674,14 +1682,14 @@ impl Window {
             self.box_geom.y = (*output).sent.y;
 
             let app_id_ptr = self.get_app_id();
-            let is_status_bar = if !app_id_ptr.is_null() {
+            let (is_status_bar, is_wallpaper) = if !app_id_ptr.is_null() {
                 let app_id = std::ffi::CStr::from_ptr(app_id_ptr).to_string_lossy();
-                app_id.starts_with("cce-status")
+                (app_id.starts_with("cce-status"), app_id.as_ref() == "cce-wallpaper")
             } else {
-                false
+                (false, false)
             };
 
-            ffi::wlr_scene_node_set_enabled(self.fullscreen_background as *mut ffi::wlr_scene_node, !is_status_bar);
+            ffi::wlr_scene_node_set_enabled(self.fullscreen_background as *mut ffi::wlr_scene_node, !is_status_bar && !is_wallpaper);
             let (width, height) = (*output).sent.dimensions();
             ffi::wlr_scene_rect_set_size(self.fullscreen_background, width as i32, height as i32);
             clip = ffi::wlr_box { x: 0, y: 0, width: width as i32, height: height as i32 };
@@ -1861,7 +1869,7 @@ impl Window {
             ffi::river_scene_node_set_position_if_changed(self.popup_tree as *mut ffi::wlr_scene_node, self.box_geom.x, self.box_geom.y);
 
             // Disable backdrop blur during active viewport zoom/pan for maximum performance
-            ffi::river_scene_node_enable_blur(self.surfaces.tree as *mut ffi::wlr_scene_node, false, (*self.server).wm.layout.scenefx_optimized_blur, true, 0, 0, 0, 0);
+            ffi::river_scene_node_enable_blur(self.tree as *mut ffi::wlr_scene_node, false, (*self.server).wm.layout.scenefx_optimized_blur, true, 0, 0, 0, 0);
 
             self.scale_only_render_finish();
             self.draw_borders();
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 9905a7e..b987752 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -265,7 +265,7 @@ impl WindowManager {
             if w.is_null() || (*w).closed || matches!((*w).state, crate::window::WindowState::Closing | crate::window::WindowState::Init) {
                 continue;
             }
-            if (*w).is_status_bar() {
+            if (*w).is_status_bar() || (*w).is_wallpaper() {
                 continue;
             }
             
@@ -738,7 +738,10 @@ impl WindowManager {
                             ffi::wlr_scene_node_reparent((*window).popup_tree as *mut _, (*self.server).scene.hidden_tree);
                         } else {
                             ffi::wlr_scene_node_reparent((*window).popup_tree as *mut _, (*self.server).scene.layers.popups);
-                            if rendered_fullscreen(window) {
+                            if (*window).get_app_id_string().as_deref() == Some("cce-wallpaper") {
+                                ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.background);
+                                ffi::wlr_scene_node_lower_to_bottom((*window).tree as *mut _);
+                            } else if rendered_fullscreen(window) {
                                 ffi::wlr_scene_node_reparent((*window).tree as *mut _, (*self.server).scene.layers.fullscreen);
                                 ffi::wlr_scene_node_raise_to_top((*window).tree as *mut _);
                                 found_fullscreen = true;
@@ -953,6 +956,13 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
             return;
         }
 
+        let has_wallpaper = self.windows.iter().any(|&w| !w.is_null() && !(*w).closed && (*w).get_app_id_string().as_deref() == Some("cce-wallpaper"));
+        for &output in &active_outputs {
+            if !(*output).background_rect.is_null() {
+                ffi::wlr_scene_node_set_enabled((*output).background_rect as *mut ffi::wlr_scene_node, !has_wallpaper);
+            }
+        }
+
         let mut focused_window: *mut Window = std::ptr::null_mut();
         let seats_list = &mut (*self.server).input_manager.seats as *mut ffi::wl_list as *mut WlList;
         let mut curr_seat = (*seats_list).next;
@@ -1002,20 +1012,31 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
 
                 let app_id = (*win_ptr).get_app_id_string();
                 let is_status_bar = app_id.as_deref().map_or(false, |id| id.starts_with("cce-status"));
+                let is_wallpaper = app_id.as_deref() == Some("cce-wallpaper");
                 
-                if is_status_bar {
+                if is_wallpaper {
                     (*win_ptr).tiling_mode = crate::tiling::TilingMode::Status;
-                    let bar_h = self.layout.bar_height as u32;
-                    (*win_ptr).rendering_requested.x = wlr_box.x;
-                    (*win_ptr).rendering_requested.y = wlr_box.y;
+                    (*win_ptr).wm_requested.tiled = 0;
+                    (*win_ptr).wm_requested.ssd = false;
+                    (*win_ptr).scale = 1.0;
+                    ffi::wlr_scene_node_set_enabled((*win_ptr).tree as *mut ffi::wlr_scene_node, true);
+                    (*win_ptr).rendering_requested.hidden = false;
+                    (*win_ptr).rendering_requested.blur = false;
+                    (*win_ptr).rendering_requested.x = phys_x;
+                    (*win_ptr).rendering_requested.y = phys_y;
                     (*win_ptr).wm_requested.dimensions = Some(crate::window::Dimensions {
-                        width: wlr_box.width as u32,
-                        height: bar_h,
+                        width: phys_w as u32,
+                        height: phys_h as u32,
                     });
                     (*win_ptr).wm_requested.bounds = crate::window::Dimensions {
-                        width: wlr_box.width as u32,
-                        height: bar_h,
+                        width: phys_w as u32,
+                        height: phys_h as u32,
                     };
+                    continue;
+                }
+
+                if is_status_bar {
+                    (*win_ptr).tiling_mode = crate::tiling::TilingMode::Status;
                     (*win_ptr).wm_requested.tiled = 0;
                     (*win_ptr).wm_requested.ssd = false;
                     (*win_ptr).scale = 1.0;
@@ -1361,6 +1382,101 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
                     if !self.layout.window_opacity { 1.0f32 } else { 0.90f32 }
                 };
             }
+
+            // Position status bar windows on this output
+            let mut left_status = Vec::new();
+            let mut right_status = Vec::new();
+            let mut full_status = Vec::new();
+
+            for &win_ptr in self.windows.iter() {
+                if win_ptr.is_null() || (*win_ptr).closed {
+                    continue;
+                }
+                if matches!((*win_ptr).state, crate::window::WindowState::Closing | crate::window::WindowState::Init) {
+                    continue;
+                }
+                if let Some(app_id) = (*win_ptr).get_app_id_string() {
+                    if app_id.starts_with("cce-status-left-") {
+                        left_status.push(win_ptr);
+                    } else if app_id.starts_with("cce-status-right-") {
+                        right_status.push(win_ptr);
+                    } else if app_id.starts_with("cce-status") {
+                        full_status.push(win_ptr);
+                    }
+                }
+            }
+
+            const LEFT_ORDER: &[&str] = &["viewport", "window"];
+            const RIGHT_ORDER: &[&str] = &["tray", "cpu", "memory", "brightness", "volume", "battery", "clock"];
+
+            left_status.sort_by_key(|&w| unsafe {
+                let app_id = (*w).get_app_id_string().unwrap_or_default();
+                let name = app_id.trim_start_matches("cce-status-left-");
+                LEFT_ORDER.iter().position(|&m| m == name).unwrap_or(99)
+            });
+
+            right_status.sort_by_key(|&w| unsafe {
+                let app_id = (*w).get_app_id_string().unwrap_or_default();
+                let name = app_id.trim_start_matches("cce-status-right-");
+                RIGHT_ORDER.iter().position(|&m| m == name).unwrap_or(99)
+            });
+
+            let bar_h = self.layout.bar_height as u32;
+            let spacing = 12;
+            let margin = 12;
+
+            // Layout Left status windows
+            let mut cur_left_x = wlr_box.x + margin;
+            for win_ptr in left_status {
+                let w = if (*win_ptr).box_geom.width > 0 { (*win_ptr).box_geom.width as u32 } else { 100 };
+                let app_id = (*win_ptr).get_app_id_string().unwrap_or_default();
+                log::info!("[ArrangeStatus] Left module app_id={} x={} y={} w={}", app_id, cur_left_x, wlr_box.y, w);
+                (*win_ptr).rendering_requested.x = cur_left_x;
+                (*win_ptr).rendering_requested.y = wlr_box.y;
+                (*win_ptr).wm_requested.dimensions = Some(crate::window::Dimensions {
+                    width: w,
+                    height: bar_h,
+                });
+                (*win_ptr).wm_requested.bounds = crate::window::Dimensions {
+                    width: w,
+                    height: bar_h,
+                };
+                cur_left_x += w as i32 + spacing;
+            }
+
+            // Layout Right status windows (right-to-left)
+            let mut cur_right_x = wlr_box.x + wlr_box.width - margin;
+            for win_ptr in right_status.into_iter().rev() {
+                let w = if (*win_ptr).box_geom.width > 0 { (*win_ptr).box_geom.width as u32 } else { 100 };
+                let x = cur_right_x - w as i32;
+                let app_id = (*win_ptr).get_app_id_string().unwrap_or_default();
+                log::info!("[ArrangeStatus] Right module app_id={} x={} y={} w={}", app_id, x, wlr_box.y, w);
+                (*win_ptr).rendering_requested.x = x;
+                (*win_ptr).rendering_requested.y = wlr_box.y;
+                (*win_ptr).wm_requested.dimensions = Some(crate::window::Dimensions {
+                    width: w,
+                    height: bar_h,
+                });
+                (*win_ptr).wm_requested.bounds = crate::window::Dimensions {
+                    width: w,
+                    height: bar_h,
+                };
+                cur_right_x = x - spacing;
+            }
+
+            // Layout Full/Legacy status windows
+            for win_ptr in full_status {
+                (*win_ptr).rendering_requested.x = wlr_box.x;
+                (*win_ptr).rendering_requested.y = wlr_box.y;
+                (*win_ptr).wm_requested.dimensions = Some(crate::window::Dimensions {
+                    width: wlr_box.width as u32,
+                    height: bar_h,
+                });
+                (*win_ptr).wm_requested.bounds = crate::window::Dimensions {
+                    width: wlr_box.width as u32,
+                    height: bar_h,
+                };
+            }
         }
         // If the focused window is no longer visible, refocus
         let seats_list = &mut (*self.server).input_manager.seats as *mut ffi::wl_list as *mut WlList;
@@ -1526,7 +1642,8 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
             if !w.is_null() && !(*w).closed && !(*w).minimized && matches!((*w).state, crate::window::WindowState::Mapped) {
                 let app_id = (*w).get_app_id_string();
                 let is_status_bar = app_id.as_deref().map_or(false, |id| id.starts_with("cce-status"));
-                if !is_status_bar {
+                let is_wallpaper = app_id.as_deref() == Some("cce-wallpaper");
+                if !is_status_bar && !is_wallpaper {
                     next_focus = w;
                     break;
                 }
@@ -1537,7 +1654,8 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
                 if !w.is_null() && !(*w).closed && !(*w).minimized && matches!((*w).state, crate::window::WindowState::Mapped) {
                     let app_id = (*w).get_app_id_string();
                     let is_status_bar = app_id.as_deref().map_or(false, |id| id.starts_with("cce-status"));
-                    if !is_status_bar {
+                    let is_wallpaper = app_id.as_deref() == Some("cce-wallpaper");
+                    if !is_status_bar && !is_wallpaper {
                         next_focus = w;
                     }
                 }
@@ -1995,7 +2113,8 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
 
                         let app_id = (*win_ptr).get_app_id_string();
                         let is_status_bar = app_id.as_deref().map_or(false, |id| id.starts_with("cce-status"));
-                        if is_status_bar {
+                        let is_wallpaper = app_id.as_deref() == Some("cce-wallpaper");
+                        if is_status_bar || is_wallpaper {
                             continue;
                         }
 
@@ -2415,6 +2534,14 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
                             self.layout.desktop_cell_fade_inset = v;
                         }
                     }
+                    "desktop_enable_solid_color" => {
+                        if let Ok(v) = val.parse::<bool>() {
+                            self.layout.desktop_enable_solid_color = v;
+                        }
+                    }
+                    "desktop_solid_color" => {
+                        self.layout.desktop_solid_color = crate::config::parse_hex_color_rgba(val);
+                    }
                     "gap" => { if let Ok(v) = val.parse::<i32>() { self.layout.gap = v; } }
                     "gap_top" => { if let Ok(v) = val.parse::<i32>() { self.layout.gap_top = v; } }
                     "gap_left" => { if let Ok(v) = val.parse::<i32>() { self.layout.gap_left = v; } }
diff --git a/src/server/wlroots_log_wrapper.c b/src/server/wlroots_log_wrapper.c
index 90e5734..9ea316d 100644
--- a/src/server/wlroots_log_wrapper.c
+++ b/src/server/wlroots_log_wrapper.c
@@ -655,7 +655,17 @@ void river_wlr_keyboard_init(struct wlr_keyboard *keyboard,
 static struct wlr_scene_node *find_blur_node(struct wlr_scene_tree *tree) {
 	struct wlr_scene_node *child;
 	wl_list_for_each(child, &tree->children, link) {
-		if (child->type == WLR_SCENE_NODE_BLUR || child->type == WLR_SCENE_NODE_OPTIMIZED_BLUR) {
+		if (child->type == WLR_SCENE_NODE_BLUR) {
+			return child;
+		}
+	}
+	return NULL;
+}
+
+static struct wlr_scene_node *find_optimized_blur_node(struct wlr_scene_tree *tree) {
+	struct wlr_scene_node *child;
+	wl_list_for_each(child, &tree->children, link) {
+		if (child->type == WLR_SCENE_NODE_OPTIMIZED_BLUR) {
 			return child;
 		}
 	}
@@ -676,11 +686,15 @@ void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled, boo
 		return;
 	}
 	struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
-	struct wlr_scene_node *blur_node = find_blur_node(tree);
+	struct wlr_scene_node *opt_blur_node = find_optimized_blur_node(tree);
+	struct wlr_scene_node *std_blur_node = find_blur_node(tree);
 
 	if (!enabled) {
-		if (blur_node) {
-			wlr_scene_node_destroy(blur_node);
+		if (opt_blur_node) {
+			wlr_scene_node_destroy(opt_blur_node);
+		}
+		if (std_blur_node) {
+			wlr_scene_node_destroy(std_blur_node);
 		}
 		return;
 	}
@@ -695,42 +709,55 @@ void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled, boo
 	}
 
 	if (width <= 0 || height <= 0) {
-		width = 1920; // Fallback defaults
-		height = 1080;
-	}
-
-	enum wlr_scene_node_type expected_type = optimized ? WLR_SCENE_NODE_OPTIMIZED_BLUR : WLR_SCENE_NODE_BLUR;
-	if (blur_node && blur_node->type != expected_type) {
-		wlr_scene_node_destroy(blur_node);
-		blur_node = NULL;
+		if (opt_blur_node) {
+			wlr_scene_node_destroy(opt_blur_node);
+		}
+		if (std_blur_node) {
+			wlr_scene_node_destroy(std_blur_node);
+		}
+		return;
 	}
 
-	if (!blur_node) {
-		if (optimized) {
+	if (optimized) {
+		if (!opt_blur_node) {
 			struct wlr_scene_optimized_blur *opt_blur = wlr_scene_optimized_blur_create(tree, width, height);
 			if (opt_blur) {
-				blur_node = &opt_blur->node;
+				opt_blur_node = &opt_blur->node;
 			}
 		} else {
-			struct wlr_scene_blur *std_blur = wlr_scene_blur_create(tree, width, height);
-			if (std_blur) {
-				wlr_scene_blur_set_should_only_blur_bottom_layer(std_blur, true);
-				blur_node = &std_blur->node;
-			}
+			wlr_scene_optimized_blur_set_size((struct wlr_scene_optimized_blur *)opt_blur_node, width, height);
 		}
-		if (blur_node) {
-			wlr_scene_node_lower_to_bottom(blur_node);
+		if (opt_blur_node) {
+			wlr_scene_node_set_position(opt_blur_node, x, y);
 		}
 	} else {
-		if (optimized) {
-			wlr_scene_optimized_blur_set_size((struct wlr_scene_optimized_blur *)blur_node, width, height);
-		} else {
-			wlr_scene_blur_set_size((struct wlr_scene_blur *)blur_node, width, height);
+		if (opt_blur_node) {
+			wlr_scene_node_destroy(opt_blur_node);
+			opt_blur_node = NULL;
 		}
 	}
 
-	if (blur_node) {
-		wlr_scene_node_set_position(blur_node, x, y);
+	if (!std_blur_node) {
+		struct wlr_scene_blur *std_blur = wlr_scene_blur_create(tree, width, height);
+		if (std_blur) {
+			std_blur_node = &std_blur->node;
+			wlr_scene_blur_set_should_only_blur_bottom_layer(std_blur, optimized);
+		}
+	} else {
+		wlr_scene_blur_set_should_only_blur_bottom_layer((struct wlr_scene_blur *)std_blur_node, optimized);
+		wlr_scene_blur_set_size((struct wlr_scene_blur *)std_blur_node, width, height);
+	}
+
+	if (std_blur_node) {
+		wlr_scene_node_set_position(std_blur_node, x, y);
+	}
+
+	// Ensure correct stack order (from back to front): opt_blur_node -> std_blur_node -> window content
+	if (std_blur_node) {
+		wlr_scene_node_lower_to_bottom(std_blur_node);
+	}
+	if (opt_blur_node) {
+		wlr_scene_node_lower_to_bottom(opt_blur_node);
 	}
 }
 
diff --git a/src/server/xdg_toplevel.rs b/src/server/xdg_toplevel.rs
index 43bbe9b..3fda19f 100644
--- a/src/server/xdg_toplevel.rs
+++ b/src/server/xdg_toplevel.rs
@@ -414,17 +414,15 @@ unsafe extern "C" fn handle_commit(listener: *mut ffi::wl_listener, _data: *mut
         ignore_transparent = (*(*window).server).wm.layout.status_backdrop_blur_ignore_transparent;
     }
     let scale = (*window).scale;
-    let geom_x = ((*window).rendering_requested.x as f64 * scale) as i32;
-    let geom_y = ((*window).rendering_requested.y as f64 * scale) as i32;
     let geom_w = ((*window).rendering_sent.width as f64 * scale) as i32;
     let geom_h = ((*window).rendering_sent.height as f64 * scale) as i32;
     ffi::river_scene_node_enable_blur(
-        (*window).surfaces.tree as *mut ffi::wlr_scene_node,
+        (*window).tree as *mut ffi::wlr_scene_node,
         (*window).rendering_requested.blur,
         (*(*window).server).wm.layout.scenefx_optimized_blur,
         ignore_transparent,
-        geom_x,
-        geom_y,
+        0,
+        0,
         geom_w,
         geom_h,
     );
@@ -454,7 +452,7 @@ unsafe extern "C" fn handle_commit(listener: *mut ffi::wl_listener, _data: *mut
         return;
     }
 
-    if (*window).state != crate::window::WindowState::Mapped {
+    if (*window).state != crate::window::WindowState::Mapped && (*window).state != crate::window::WindowState::Ready {
         return;
     }
 
@@ -472,10 +470,15 @@ unsafe extern "C" fn handle_commit(listener: *mut ffi::wl_listener, _data: *mut
                     "client initiated size change: {}x{} -> {}x{}",
                     old_geometry.width, old_geometry.height, new_geometry.width, new_geometry.height
                 );
-                if matches!((*window).tiling_mode, crate::tiling::TilingMode::Floating | crate::tiling::TilingMode::Popup) {
+                let is_status = (*window).tiling_mode == crate::tiling::TilingMode::Status || 
+                                (*window).get_app_id_string().map_or(false, |id| id.starts_with("cce-status"));
+                if matches!((*window).tiling_mode, crate::tiling::TilingMode::Floating | crate::tiling::TilingMode::Popup) || is_status {
                     (*window).set_dimensions(new_geometry.width as u32, new_geometry.height as u32);
                     (*window).configure_sent.width = Some(new_geometry.width as u32);
                     (*window).configure_sent.height = Some(new_geometry.height as u32);
+                    if is_status {
+                        (*(*window).server).wm.dirty_windowing();
+                    }
                 } else {
                     (*window).render_finish();
                 }
@@ -494,6 +497,15 @@ unsafe extern "C" fn handle_commit(listener: *mut ffi::wl_listener, _data: *mut
             (*window).rendering_scheduled.width = new_geometry.width as u32;
             (*window).rendering_scheduled.height = new_geometry.height as u32;
 
+            let is_status = (*window).tiling_mode == crate::tiling::TilingMode::Status || 
+                            (*window).get_app_id_string().map_or(false, |id| id.starts_with("cce-status"));
+            if matches!((*window).tiling_mode, crate::tiling::TilingMode::Floating | crate::tiling::TilingMode::Popup) || is_status {
+                (*window).set_dimensions(new_geometry.width as u32, new_geometry.height as u32);
+                if is_status {
+                    (*(*window).server).wm.dirty_windowing();
+                }
+            }
+
             let (dec_w, dec_h) = (*window).get_decorations_size();
             if dec_w != (*window).last_decor_w || dec_h != (*window).last_decor_h {
                 (*window).last_decor_w = dec_w;