Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix(snap): route both resize-size computations through snap::resize_axis
Resize snapping never showed on screen: the seat op computed a snapped
size, but get_active_resize_dimensions independently recomputed an
UNSNAPPED size for the arrange snapshot, and arrange's configure won
every manage cycle. Both paths now call snap::resize_axis (via the new
Layout::snap_params helper), so they cannot diverge.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/server/config.rs | 14 +++++++++++++
src/server/seat.rs | 48 +++++++++++++-------------------------------
src/server/window_manager.rs | 26 +++++++++++-------------
3 files changed, 40 insertions(+), 48 deletions(-)
diff --git a/src/server/config.rs b/src/server/config.rs
index b182916..44d004f 100644
--- a/src/server/config.rs
+++ b/src/server/config.rs
@@ -70,6 +70,20 @@ pub struct Layout {
pub cloud_position_default: Option<[i32; 2]>,
}
+impl Layout {
+ /// Snap parameters for interactive ops. A zero threshold (snap
+ /// disabled) makes every snap function a no-op.
+ pub fn snap_params(&self) -> crate::policy::snap::SnapParams {
+ crate::policy::snap::SnapParams {
+ cell_size: self.desktop_grid_scale,
+ gap_width: self.desktop_gap_width as f64,
+ cell_inset: self.desktop_cell_fade_inset as f64,
+ threshold: if self.desktop_snap { self.desktop_snap_threshold } else { 0.0 },
+ border_width: self.border_width as f64,
+ }
+ }
+}
+
impl Default for Layout {
fn default() -> Self {
Layout {
diff --git a/src/server/seat.rs b/src/server/seat.rs
index 4924f64..2f07f72 100644
--- a/src/server/seat.rs
+++ b/src/server/seat.rs
@@ -944,16 +944,8 @@ impl Seat {
}
/// Snap parameters for interactive ops, from the current layout config.
- /// A zero threshold (snap disabled) makes every snap function a no-op.
unsafe fn snap_params(&self) -> crate::policy::snap::SnapParams {
- let layout = &(*self.server).wm.layout;
- crate::policy::snap::SnapParams {
- cell_size: layout.desktop_grid_scale,
- gap_width: layout.desktop_gap_width as f64,
- cell_inset: layout.desktop_cell_fade_inset as f64,
- threshold: if layout.desktop_snap { layout.desktop_snap_threshold } else { 0.0 },
- border_width: layout.border_width as f64,
- }
+ (*self.server).wm.layout.snap_params()
}
pub unsafe fn op_update(&mut self, x: i32, y: i32) {
@@ -1196,31 +1188,19 @@ impl Seat {
(*win).resize_edges = Some(edges);
}
- // Magnetic grid snap pulls the dragged edge onto grid
- // lines; the anchored edge is untouched.
- if edges.left {
- let left = crate::policy::snap::snap_low_edge(op.start_win_virtual_x + virtual_dx, &sp);
- let anchor_right = op.start_win_virtual_x + op.start_win_w as f64;
- new_w = std::cmp::max(50, (anchor_right - left) as i32) as u32;
- } else if edges.right {
- let right = crate::policy::snap::snap_high_edge(
- op.start_win_virtual_x + op.start_win_w as f64 + virtual_dx,
- &sp,
- );
- new_w = std::cmp::max(50, (right - op.start_win_virtual_x) as i32) as u32;
- }
-
- if edges.top {
- let top = crate::policy::snap::snap_low_edge(op.start_win_virtual_y + virtual_dy, &sp);
- let anchor_bottom = op.start_win_virtual_y + op.start_win_h as f64;
- new_h = std::cmp::max(50, (anchor_bottom - top) as i32) as u32;
- } else if edges.bottom {
- let bottom = crate::policy::snap::snap_high_edge(
- op.start_win_virtual_y + op.start_win_h as f64 + virtual_dy,
- &sp,
- );
- new_h = std::cmp::max(50, (bottom - op.start_win_virtual_y) as i32) as u32;
- }
+ // Magnetic grid snap pulls the dragged edge onto the
+ // visible cell edges; the anchored edge is untouched.
+ // Must match get_active_resize_dimensions, which
+ // recomputes this for the arrange snapshot — both go
+ // through snap::resize_axis.
+ new_w = crate::policy::snap::resize_axis(
+ op.start_win_virtual_x, op.start_win_w as f64, virtual_dx,
+ edges.left, edges.right, 50.0, &sp,
+ ) as u32;
+ new_h = crate::policy::snap::resize_axis(
+ op.start_win_virtual_y, op.start_win_h as f64, virtual_dy,
+ edges.top, edges.bottom, 50.0, &sp,
+ ) as u32;
(*win).virtual_x = vx;
(*win).virtual_y = vy;
diff --git a/src/server/window_manager.rs b/src/server/window_manager.rs
index 7f0579a..835d201 100644
--- a/src/server/window_manager.rs
+++ b/src/server/window_manager.rs
@@ -1030,20 +1030,18 @@ impl WindowManager {
let dy = op.y - op.start_y;
let virtual_dx = dx as f64 / scale;
let virtual_dy = dy as f64 / scale;
- let mut new_w = op.start_win_w;
- let mut new_h = op.start_win_h;
-
- if edges.left {
- new_w = std::cmp::max(50, (op.start_win_w as f64 - virtual_dx) as i32) as u32;
- } else if edges.right {
- new_w = std::cmp::max(50, (op.start_win_w as f64 + virtual_dx) as i32) as u32;
- }
-
- if edges.top {
- new_h = std::cmp::max(50, (op.start_win_h as f64 - virtual_dy) as i32) as u32;
- } else if edges.bottom {
- new_h = std::cmp::max(50, (op.start_win_h as f64 + virtual_dy) as i32) as u32;
- }
+ // Same math (and snapping) as the seat op's Resize
+ // arm — this recomputation feeds the arrange
+ // snapshot and must not diverge from it.
+ let sp = self.layout.snap_params();
+ let new_w = crate::policy::snap::resize_axis(
+ op.start_win_virtual_x, op.start_win_w as f64, virtual_dx,
+ edges.left, edges.right, 50.0, &sp,
+ ) as u32;
+ let new_h = crate::policy::snap::resize_axis(
+ op.start_win_virtual_y, op.start_win_h as f64, virtual_dy,
+ edges.top, edges.bottom, 50.0, &sp,
+ ) as u32;
return Some((new_w, new_h));
}
}