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

commit85e52d9fd7d971efc0aa352aef80b42c735bba1e
parenta1ed4a201c
authorLucas Galante <[email protected]>
date2026-09-04 10:35
fix(pan): round the grid-patch latch and restore-placeholder positions like the arrange pass

The two remaining virtual->screen conversions outside the policy crate
still truncated; with cce-window-manager now rounding placement, these
would have put the latched client patch and the restore placeholders a
pixel off everything else.

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

 src/server/window_manager.rs | 4 ++--
 src/server/xdg_toplevel.rs   | 7 +++++--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 84108d2..badcb1d 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -686,8 +686,8 @@ impl WindowManager {
         let zoom = self.desk_zoom;
         let radius = (self.layout.backplate_corner_radius as f64 * zoom) as i32;
         for p in &self.restore_placeholders {
-            let x = out_x + ((p.vx - self.desk_pan_x) * zoom) as i32;
-            let y = out_y + ((p.vy - self.desk_pan_y) * zoom) as i32;
+            let x = out_x + ((p.vx - self.desk_pan_x) * zoom).round() as i32;
+            let y = out_y + ((p.vy - self.desk_pan_y) * zoom).round() as i32;
             ffi::river_scene_node_set_position_if_changed(p.rect as *mut ffi::wlr_scene_node, x, y);
             ffi::river_scene_rect_set_size_if_changed(
                 p.rect,
diff --git a/src/server/xdg_toplevel.rs b/src/server/xdg_toplevel.rs
index ce6fc40..2bdc676 100644
--- a/src/server/xdg_toplevel.rs
+++ b/src/server/xdg_toplevel.rs
@@ -591,8 +591,11 @@ unsafe extern "C" fn handle_commit(listener: *mut ffi::wl_listener, _data: *mut
                 curr_out = (*curr_out).next;
             }
             if patch.scale > 0.0 {
-                let sx = ox + ((patch.x - wm.desk_pan_x) * zoom) as i32;
-                let sy = oy + ((patch.y - wm.desk_pan_y) * zoom) as i32;
+                // Rounded like every other virtual->screen placement (the
+                // arrange pass and the fallback lattice); truncation here put
+                // the latched patch a pixel off the lattice it replaces.
+                let sx = ox + ((patch.x - wm.desk_pan_x) * zoom).round() as i32;
+                let sy = oy + ((patch.y - wm.desk_pan_y) * zoom).round() as i32;
                 (*window).rendering_requested.x = sx;
                 (*window).rendering_requested.y = sy;
                 (*window).scale = zoom / patch.scale;