Wayland compositor (wlroots)
git clone https://git.lucas.co/cce-compositor.git
fix(resize): render_finish sizes from current committed geometry mid-resize
Root cause of the residual resize jitter, confirmed by tracing: the WM
render transaction snapshots the window size at render_start
(rendering_sent), but the client keeps committing while the
transaction is in flight, and the anchored position
(rendering_requested.x, updated per commit) tracks the newest commit.
render_finish then paired last commit's width with this commit's
position and clipped the surface to the stale width — bouncing the
anchored edge by the commit lag every cycle (state cycled through
TimedOut, so the Acked-arm size refresh never ran).
While resize_edges is active, render_finish now takes box_geom
dimensions from the toplevel's current committed geometry — the same
source the position was computed from — so size, clip, borders, and
position always describe the same commit. Snapshot behavior is
unchanged outside resizes.
Co-Authored-By: Claude Fable 5 <[email protected]>
src/server/window.rs | 27 +++++++++++++++++++++++----
1 file changed, 23 insertions(+), 4 deletions(-)
diff --git a/src/server/window.rs b/src/server/window.rs
index 918fc9a..835ccb3 100644
--- a/src/server/window.rs
+++ b/src/server/window.rs
@@ -1858,11 +1858,30 @@ impl Window {
self.last_applied_scale = self.scale;
}
- if self.rendering_sent.width > 0 {
- self.box_geom.width = self.rendering_sent.width as i32;
+ // During an interactive resize, size the box from the client's
+ // CURRENT committed geometry instead of the render-start snapshot
+ // (rendering_sent): commits land between render_start and
+ // render_finish, and the anchored position (rendering_requested.x,
+ // updated by the commit handler) always tracks the newest commit.
+ // Pairing it with the older snapshot size clips the surface short
+ // and makes the anchored edge bounce every cycle.
+ let mut resize_synced = false;
+ if self.resize_edges.is_some() {
+ if let WindowImpl::Toplevel(toplevel) = self.impl_type {
+ if !toplevel.is_null() {
+ self.box_geom.width = (*toplevel).geometry.width;
+ self.box_geom.height = (*toplevel).geometry.height;
+ resize_synced = true;
+ }
+ }
}
- if self.rendering_sent.height > 0 {
- self.box_geom.height = self.rendering_sent.height as i32;
+ if !resize_synced {
+ if self.rendering_sent.width > 0 {
+ self.box_geom.width = self.rendering_sent.width as i32;
+ }
+ if self.rendering_sent.height > 0 {
+ self.box_geom.height = self.rendering_sent.height as i32;
+ }
}
let mut clip = requested.clip;