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

commitaa8cb143a39f6a054d234d0ad5a00205c55adf44
parent611d9cea7b
authorLucas Galante <[email protected]>
date2026-06-27 15:37
fix(server): resolve lagging and duplicating window shadows during resize scaling

 src/server/window.rs             | 40 ++++++++++++++++++++++++++++++++++++++++
 src/server/wlroots_log_wrapper.c | 24 ++++++++++++++++++++----
 wrapper.h                        |  2 ++
 3 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/src/server/window.rs b/src/server/window.rs
index 61b9bbb..1c08ca8 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -1606,6 +1606,17 @@ impl Window {
                 } else if data.scale == 1.0 {
                     ffi::river_scene_buffer_set_dest_size_if_changed(buffer, 0, 0);
                     ffi::river_scene_node_set_position_if_changed(node, sx, sy);
+                } else {
+                    let w = ffi::river_scene_buffer_get_width(buffer);
+                    let h = ffi::river_scene_buffer_get_height(buffer);
+                    let dest_w = (w as f64 * data.scale) as i32;
+                    let dest_h = (h as f64 * data.scale) as i32;
+                    ffi::river_scene_buffer_set_dest_size_if_changed(buffer, dest_w, dest_h);
+
+                    let (px, py) = get_parent_position_relative_to(node, data.ancestor);
+                    let dest_x = (px as f64 * (data.scale - 1.0)) as i32;
+                    let dest_y = (py as f64 * (data.scale - 1.0)) as i32;
+                    ffi::river_scene_node_set_position_if_changed(node, dest_x, dest_y);
                 }
             }
 
@@ -1615,6 +1626,15 @@ impl Window {
                 Some(set_expose_scale_iterator),
                 &scale_data_surfaces as *const ScaleData as *mut std::ffi::c_void,
             );
+
+            if self.surfaces.saved {
+                let scale_data_saved = ScaleData { scale: self.scale, ancestor: self.surfaces.saved_tree as *mut ffi::wlr_scene_node };
+                ffi::wlr_scene_node_for_each_buffer(
+                    self.surfaces.saved_tree as *mut ffi::wlr_scene_node,
+                    Some(set_expose_scale_iterator),
+                    &scale_data_saved as *const ScaleData as *mut std::ffi::c_void,
+                );
+            }
             
             let scale_data_popup = ScaleData { scale: self.scale, ancestor: self.popup_tree as *mut ffi::wlr_scene_node };
             ffi::wlr_scene_node_for_each_buffer(
@@ -2694,6 +2714,17 @@ impl Decoration {
             } else if data.scale == 1.0 {
                 ffi::river_scene_buffer_set_dest_size_if_changed(buffer, 0, 0);
                 ffi::river_scene_node_set_position_if_changed(node, sx, sy);
+            } else {
+                let w = ffi::river_scene_buffer_get_width(buffer);
+                let h = ffi::river_scene_buffer_get_height(buffer);
+                let dest_w = (w as f64 * data.scale) as i32;
+                let dest_h = (h as f64 * data.scale) as i32;
+                ffi::river_scene_buffer_set_dest_size_if_changed(buffer, dest_w, dest_h);
+
+                let (px, py) = get_parent_position_relative_to(node, data.ancestor);
+                let dest_x = (px as f64 * (data.scale - 1.0)) as i32;
+                let dest_y = (py as f64 * (data.scale - 1.0)) as i32;
+                ffi::river_scene_node_set_position_if_changed(node, dest_x, dest_y);
             }
         }
 
@@ -2704,6 +2735,15 @@ impl Decoration {
             &scale_data as *const ScaleData as *mut std::ffi::c_void,
         );
 
+        if self.surfaces.saved {
+            let scale_data_saved = ScaleData { scale, ancestor: self.surfaces.saved_tree as *mut ffi::wlr_scene_node };
+            ffi::wlr_scene_node_for_each_buffer(
+                self.surfaces.saved_tree as *mut ffi::wlr_scene_node,
+                Some(set_expose_scale_iterator),
+                &scale_data_saved as *const ScaleData as *mut std::ffi::c_void,
+            );
+        }
+
         let children_head = ffi::river_scene_tree_get_children(self.surfaces.tree) as *mut WlList;
         if (*children_head).next != children_head {
             ffi::wlr_scene_subsurface_tree_set_clip(self.surfaces.tree as *mut ffi::wlr_scene_node, std::ptr::null());
diff --git a/src/server/wlroots_log_wrapper.c b/src/server/wlroots_log_wrapper.c
index 45c5114..6d7a13b 100644
--- a/src/server/wlroots_log_wrapper.c
+++ b/src/server/wlroots_log_wrapper.c
@@ -102,11 +102,17 @@ struct wl_signal *river_scene_node_get_destroy_signal(struct wlr_scene_node *nod
 
 static void save_surface_tree_iter(struct wlr_scene_buffer *buffer, int sx, int sy, void *user_data) {
 	struct wlr_scene_tree *saved_tree = user_data;
-	struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_create(saved_tree, buffer->buffer);
+	struct wlr_scene_tree *buffer_tree = wlr_scene_tree_create(saved_tree);
+	if (!buffer_tree) {
+		return;
+	}
+	wlr_scene_node_set_position(&buffer_tree->node, sx, sy);
+	struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_create(buffer_tree, buffer->buffer);
 	if (!scene_buffer) {
+		wlr_scene_node_destroy(&buffer_tree->node);
 		return;
 	}
-	wlr_scene_node_set_position(&scene_buffer->node, sx, sy);
+	wlr_scene_node_set_position(&scene_buffer->node, 0, 0);
 	wlr_scene_buffer_set_dest_size(scene_buffer, buffer->dst_width, buffer->dst_height);
 	wlr_scene_buffer_set_source_box(scene_buffer, &buffer->src_box);
 	wlr_scene_buffer_set_transform(scene_buffer, buffer->transform);
@@ -692,6 +698,16 @@ void river_scene_rect_set_size_if_changed(struct wlr_scene_rect *rect, int width
 	}
 }
 
+int river_scene_buffer_get_width(struct wlr_scene_buffer *scene_buffer) {
+	if (scene_buffer->buffer) {
+		return scene_buffer->buffer->width;
+	}
+	return scene_buffer->dst_width;
+}
 
-
-
+int river_scene_buffer_get_height(struct wlr_scene_buffer *scene_buffer) {
+	if (scene_buffer->buffer) {
+		return scene_buffer->buffer->height;
+	}
+	return scene_buffer->dst_height;
+}
diff --git a/wrapper.h b/wrapper.h
index 19e6311..715b85f 100644
--- a/wrapper.h
+++ b/wrapper.h
@@ -262,6 +262,8 @@ void river_scene_node_enable_blur(struct wlr_scene_node *node, bool enabled);
 void river_scene_node_set_opacity(struct wlr_scene_node *node, float opacity);
 
 void river_scene_buffer_set_dest_size_if_changed(struct wlr_scene_buffer *scene_buffer, int width, int height);
+int river_scene_buffer_get_width(struct wlr_scene_buffer *scene_buffer);
+int river_scene_buffer_get_height(struct wlr_scene_buffer *scene_buffer);
 
 void river_scene_node_set_position_if_changed(struct wlr_scene_node *node, int x, int y);