From e81e787e1abd669c47f6ae6dfc4d4bdf8ba49d3e Mon Sep 17 00:00:00 2001 From: En-En <39373446+En-En-Code@users.noreply.github.com> Date: Sun, 14 Dec 2025 01:15:50 +0000 Subject: [PATCH] fix: dragging pop-ups causes them to stutter Dragging a pop-up surface around regularly updates it via `SurfaceEvents::xdg_event`. This called `XConnection::set_window_dims`, which was enqueueing many `ConfigureRequest` events. These outdated events would still be processed by XWayland and responded to with `ConfigureNotify`, which updated the surface to an old position, resulting in glitchy behavior. This fix replaces the call of `set_window_dims` in `xdg_event`, instead inserting the new position of the window into the ECS. Then, after all Wayland events have been read, the pending position is popped from the ECS and used to call `set_window_dims` for each window with it. A solution to the issue posed in #314. --- src/server/event.rs | 17 +++++++---------- src/server/mod.rs | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/src/server/event.rs b/src/server/event.rs index fb82da9..55ed56c 100644 --- a/src/server/event.rs +++ b/src/server/event.rs @@ -330,23 +330,20 @@ impl SurfaceEvents { } } - connection.set_window_dims( - window, - PendingSurfaceState { - x, - y, - width: width as _, - height: height as _, - }, - ); window_data.attrs.dims = WindowDims { x: x as i16, y: y as i16, width, height, }; - + let pending = PendingSurfaceState { + x, + y, + width: width as _, + height: height as _, + }; drop(query); + state.world.insert_one(target, pending).unwrap(); update_surface_viewport(&state.world, state.world.query_one(target).unwrap()); } diff --git a/src/server/mod.rs b/src/server/mod.rs index 56dde09..4de3a7d 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -613,6 +613,24 @@ impl ServerState { event.handle(target, self); } + let query = self + .world + .query_mut::<(&PendingSurfaceState,)>() + .into_iter() + .map(|(e, _)| e) + .collect::>(); + for entity in query { + let dims = self + .world + .remove_one::(entity) + .unwrap(); + let entity = self.world.entity(entity).unwrap(); + let mut query = entity.query::<(&x::Window,)>(); + let window = *query.get().unwrap().0; + drop(query); + self.connection.set_window_dims(window, dims); + } + if self.global_offset_updated { if self.global_output_offset.x.owner.is_none() || self.global_output_offset.y.owner.is_none()