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

commite09fca562c895ed10494b9af853c389a8c7ffafe
parent79c96e1f54
authorLucas Galante <[email protected]>
date2026-06-05 20:13
feat: implement set_blur request for window and decoration interfaces

 Makefile                                | 14 ++++++++++
 build.rs                                |  1 +
 protocol/river-window-management-v1.xml | 20 +++++++++++++++
 src/window.rs                           | 45 ++++++++++++++++++++++++++++++++-
 4 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..88ebfc3
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+.PHONY: build install run clean
+
+build:
+	cargo build --release
+
+install: build
+	mkdir -p ~/.local/bin
+	install -m 755 target/release/clear-computing-environment-server ~/.local/bin/clear-computing-environment-server
+
+run:
+	cargo run
+
+clean:
+	cargo clean
diff --git a/build.rs b/build.rs
index 81003c0..5c94b3f 100644
--- a/build.rs
+++ b/build.rs
@@ -4,6 +4,7 @@ use std::path::PathBuf;
 fn main() {
     println!("cargo:rerun-if-changed=src/wlroots_log_wrapper.c");
     println!("cargo:rerun-if-changed=wrapper.h");
+    println!("cargo:rerun-if-changed=protocol/river-window-management-v1.xml");
 
     // Probe system libraries
     let scenefx = pkg_config::Config::new()
diff --git a/protocol/river-window-management-v1.xml b/protocol/river-window-management-v1.xml
index 60040b2..cbc1015 100644
--- a/protocol/river-window-management-v1.xml
+++ b/protocol/river-window-management-v1.xml
@@ -1139,6 +1139,16 @@
       </description>
       <arg name="circular" type="uint" summary="1 if circular, 0 otherwise"/>
     </request>
+
+    <request name="set_blur" since="4">
+      <description summary="set whether backdrop blur is enabled">
+        Set whether backdrop blur should be enabled for this window.
+        1 to enable, 0 to disable.
+        This request modifies rendering state and may only be made as part of a
+        render sequence, see the river_window_manager_v1 description.
+      </description>
+      <arg name="blur" type="uint" summary="1 to enable, 0 to disable"/>
+    </request>
   </interface>
 
   <interface name="river_decoration_v1" version="4">
@@ -1195,6 +1205,16 @@
         render sequence, see the river_window_manager_v1 description.
       </description>
     </request>
+
+    <request name="set_blur" since="4">
+      <description summary="set whether backdrop blur is enabled">
+        Set whether backdrop blur should be enabled for this decoration.
+        1 to enable, 0 to disable.
+        This request modifies rendering state and may only be made as part of a
+        render sequence, see the river_window_manager_v1 description.
+      </description>
+      <arg name="blur" type="uint" summary="1 to enable, 0 to disable"/>
+    </request>
   </interface>
 
   <interface name="river_shell_surface_v1" version="4">
diff --git a/src/window.rs b/src/window.rs
index c40ea0b..35d28f0 100644
--- a/src/window.rs
+++ b/src/window.rs
@@ -183,6 +183,7 @@ pub struct WindowRenderingRequested {
     pub content_clip: ffi::wlr_box,
     pub opacity: f32,
     pub circular: bool,
+    pub blur: bool,
 }
 
 pub struct Window {
@@ -343,6 +344,7 @@ impl Window {
                 content_clip: ffi::wlr_box { x: 0, y: 0, width: 0, height: 0 },
                 opacity: 1.0f32,
                 circular: false,
+                blur: false,
             },
             box_geom: ffi::wlr_box { x: 0, y: 0, width: 0, height: 0 },
             foreign_toplevel_handle: std::ptr::null_mut(),
@@ -688,6 +690,7 @@ impl Window {
                     content_clip: ffi::wlr_box { x: 0, y: 0, width: 0, height: 0 },
                     opacity: 1.0f32,
                     circular: false,
+                    blur: false,
                 };
 
                 wl_list_remove(&mut self.node.link as *mut ffi::wl_list as *mut WlList);
@@ -1138,7 +1141,7 @@ impl Window {
         ffi::wlr_scene_node_set_enabled(self.popup_tree as *mut ffi::wlr_scene_node, enabled);
 
         if enabled {
-            ffi::river_scene_node_enable_blur(self.surfaces.tree as *mut ffi::wlr_scene_node, true);
+            ffi::river_scene_node_enable_blur(self.surfaces.tree as *mut ffi::wlr_scene_node, requested.blur);
             ffi::river_scene_node_set_opacity(self.tree as *mut ffi::wlr_scene_node, requested.opacity);
 
             let radius = if requested.circular {
@@ -1841,6 +1844,22 @@ unsafe extern "C" fn window_set_circular(
     (*window).rendering_requested.circular = circular != 0;
 }
 
+unsafe extern "C" fn window_set_blur(
+    _client: *mut ffi::wl_client,
+    resource: *mut ffi::wl_resource,
+    blur: u32,
+) {
+    let window = ffi::wl_resource_get_user_data(resource) as *mut Window;
+    if window.is_null() {
+        return;
+    }
+    let server = (*window).server;
+    if !(*server).wm.ensure_rendering() {
+        return;
+    }
+    (*window).rendering_requested.blur = blur != 0;
+}
+
 // river_window_v1 implementation
 static WINDOW_INTERFACE: ffi::river_window_v1_interface = ffi::river_window_v1_interface {
     destroy: Some(window_destroy),
@@ -1869,6 +1888,7 @@ static WINDOW_INTERFACE: ffi::river_window_v1_interface = ffi::river_window_v1_i
     set_dimension_bounds: Some(window_set_dimension_bounds),
     set_opacity: Some(window_set_opacity),
     set_circular: Some(window_set_circular),
+    set_blur: Some(window_set_blur),
 };
 
 static INERT_WINDOW_INTERFACE: ffi::river_window_v1_interface = ffi::river_window_v1_interface {
@@ -1898,6 +1918,7 @@ static INERT_WINDOW_INTERFACE: ffi::river_window_v1_interface = ffi::river_windo
     set_dimension_bounds: None,
     set_opacity: None,
     set_circular: None,
+    set_blur: None,
 };
 
 unsafe extern "C" fn handle_destroy_resource(resource: *mut ffi::wl_resource) {
@@ -1927,6 +1948,7 @@ pub struct DecorationRenderingRequested {
     pub offset_x: i32,
     pub offset_y: i32,
     pub sync_next_commit: bool,
+    pub blur: bool,
 }
 
 pub struct Decoration {
@@ -1987,6 +2009,7 @@ impl Decoration {
                 offset_x: 0,
                 offset_y: 0,
                 sync_next_commit: false,
+                blur: false,
             },
         });
         let raw = Box::into_raw(dec);
@@ -2041,6 +2064,8 @@ impl Decoration {
 
         self.surfaces.drop_saved();
 
+        ffi::river_scene_node_enable_blur(self.surfaces.tree as *mut ffi::wlr_scene_node, self.rendering_requested.blur);
+
         ffi::wlr_scene_node_set_position(self.tree as *mut ffi::wlr_scene_node, self.rendering_requested.offset_x, self.rendering_requested.offset_y);
 
         let children_head = ffi::river_scene_tree_get_children(self.surfaces.tree) as *mut WlList;
@@ -2121,16 +2146,34 @@ unsafe extern "C" fn dec_sync_next_commit(
     (*dec).rendering_requested.sync_next_commit = true;
 }
 
+unsafe extern "C" fn dec_set_blur(
+    _client: *mut ffi::wl_client,
+    resource: *mut ffi::wl_resource,
+    blur: u32,
+) {
+    let dec = ffi::wl_resource_get_user_data(resource) as *mut Decoration;
+    if dec.is_null() {
+        return;
+    }
+    let server = (*(*dec).window).server;
+    if !(*server).wm.ensure_rendering() {
+        return;
+    }
+    (*dec).rendering_requested.blur = blur != 0;
+}
+
 static DECORATION_INTERFACE: ffi::river_decoration_v1_interface = ffi::river_decoration_v1_interface {
     destroy: Some(dec_destroy),
     set_offset: Some(dec_set_offset),
     sync_next_commit: Some(dec_sync_next_commit),
+    set_blur: Some(dec_set_blur),
 };
 
 static INERT_DECORATION_INTERFACE: ffi::river_decoration_v1_interface = ffi::river_decoration_v1_interface {
     destroy: Some(dec_destroy),
     set_offset: None,
     sync_next_commit: None,
+    set_blur: None,
 };
 
 unsafe extern "C" fn handle_dec_destroy_resource(resource: *mut ffi::wl_resource) {