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

commitb4686cebbe38ea1c8fa25637dbe6e10e4fb32554
parent1f0329eb62
authorLucas Galante <[email protected]>
date2026-06-30 14:58
Dynamically disable window backdrop blur and grid fade layers during active zoom/pan

 src/server/output.rs         |  3 ++-
 src/server/window.rs         |  3 +++
 src/server/window_manager.rs | 35 ++++++++++++++++++++++++++++++++---
 3 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/src/server/output.rs b/src/server/output.rs
index 61db63c..43f0233 100644
--- a/src/server/output.rs
+++ b/src/server/output.rs
@@ -636,7 +636,8 @@ impl Output {
                         continue;
                     }
 
-                    if cell_fade_inset <= 0 {
+                    let draw_fade = cell_fade_inset > 0 && !draw_low_res;
+                    if !draw_fade {
                         let cell_rect = ffi::wlr_scene_rect_create(
                             self.grid_tree,
                             rw,
diff --git a/src/server/window.rs b/src/server/window.rs
index 01ee937..733426b 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -1844,6 +1844,9 @@ impl Window {
             ffi::river_scene_node_set_position_if_changed(self.tree as *mut ffi::wlr_scene_node, self.box_geom.x, self.box_geom.y);
             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);
+
             self.scale_only_render_finish();
             self.draw_borders();
         }
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 0a08107..5bfd7b6 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -113,6 +113,10 @@ pub struct WindowManager {
     pub animation_timer: *mut ffi::wl_event_source,
     pub has_restored_focused_window: bool,
     pub restored_focused_window_mapped: bool,
+    pub last_viewport_zoom: f64,
+    pub last_viewport_pan_x: f64,
+    pub last_viewport_pan_y: f64,
+    pub viewport_is_active: bool,
 }
 
 impl WindowManager {
@@ -1389,14 +1393,39 @@ fn get_closest_tag(x: f64, y: f64) -> i32 {
     }
 
     pub unsafe fn update_viewport_local(&mut self) {
+        let zoom_changed = self.desk_zoom != self.last_viewport_zoom;
+        let pan_changed = self.desk_pan_x != self.last_viewport_pan_x || self.desk_pan_y != self.last_viewport_pan_y;
+        let active = zoom_changed || pan_changed;
+
+        self.last_viewport_zoom = self.desk_zoom;
+        self.last_viewport_pan_x = self.desk_pan_x;
+        self.last_viewport_pan_y = self.desk_pan_y;
+
+        let was_active = self.viewport_is_active;
+        self.viewport_is_active = active;
+
         self.arrange_views();
         // Clear rendering dirty flag so we don't trigger the idle callback's IPC handshake
         self.rendering_scheduled.dirty = false;
         self.remove_dirty_idle();
 
-        for &window in self.windows.iter() {
-            if !window.is_null() {
-                (*window).render_viewport_update();
+        if active {
+            for &window in self.windows.iter() {
+                if !window.is_null() {
+                    (*window).render_viewport_update();
+                }
+            }
+        } else if was_active {
+            for &window in self.windows.iter() {
+                if !window.is_null() {
+                    (*window).render_finish();
+                }
+            }
+        } else {
+            for &window in self.windows.iter() {
+                if !window.is_null() {
+                    (*window).render_viewport_update();
+                }
             }
         }