diff options
Diffstat (limited to 'crates')
| -rw-r--r-- | crates/wayland/src/udev/render.rs | 26 | ||||
| -rw-r--r-- | crates/wayland/src/winit/render.rs | 7 |
2 files changed, 30 insertions, 3 deletions
diff --git a/crates/wayland/src/udev/render.rs b/crates/wayland/src/udev/render.rs index c2899ae..a2cf367 100644 --- a/crates/wayland/src/udev/render.rs +++ b/crates/wayland/src/udev/render.rs @@ -315,10 +315,17 @@ impl CompState { let Some(dwindow) = self.id_to_window.get(&id) else { continue }; let Some(surface) = crate::elements::window_wl_surface(dwindow) else { continue }; let geom = self.window_anims.get(&id).map(crate::state::WindowAnim::current_rect).unwrap_or(w.geometry); + // Content is positioned from `frame`, not `geom`, for + // the same reason as the Pixman loop's own content + // push below: `geom` is the live drag target and + // moves a frame ahead of the client, so content drawn + // from it slides out from under the decoration drawn + // around it. + let frame = crate::state::CompState::effective_frame_of(&self.wm, &self.id_to_window, &self.pending_size_configure, id, geom); let band = if w.decorated { srdwm_core::TITLEBAR_HEIGHT as i32 } else { 0 }; let raw_offset = dwindow.geometry().loc; let content_offset = Point::<i32, Logical>::from((raw_offset.x.max(0), raw_offset.y.max(0))); - let pos = (geom.x - origin.x - content_offset.x, geom.y + band - origin.y - content_offset.y); + let pos = (frame.x - origin.x - content_offset.x, frame.y + band - origin.y - content_offset.y); elements.extend(crate::elements::surface_content_elements(&mut gpu.renderer, &surface, pos, w.opacity)); // Border strips (top/bottom) and the titlebar bitmap, // reusing the exact same cached `MemoryRenderBuffer`s @@ -1005,7 +1012,22 @@ impl CompState { // exactly on this same real content top-left -- // the margin has already been compensated for // once, inside the buffer itself. - let content_pos = (geom.x - origin.x, geom.y + band - origin.y); + // `frame`, not `geom`: `geom` is the live drag + // target, which moves with the pointer on the + // very frame the pointer moves, while every + // decoration around it is drawn from `frame` -- + // the committed size anchored to the edge the + // drag is not holding. Drawing content from one + // and its frame from the other is what made a + // titlebar look detached from its own window + // while resizing, and made dragging a left edge + // look like it moved the right one: the stale + // buffer slid left with the pointer, carrying + // its old width, while the border stayed put. + // Outside a resize the two are identical -- + // `committed_frame` only ever corrects the far + // edge - so this changes nothing else. + let content_pos = (frame.x - origin.x, frame.y + band - origin.y); // Only for the *fallback* path below // (`surface_content_elements`, pushed when // masking is off or fails): that renders the diff --git a/crates/wayland/src/winit/render.rs b/crates/wayland/src/winit/render.rs index d49351f..02ee322 100644 --- a/crates/wayland/src/winit/render.rs +++ b/crates/wayland/src/winit/render.rs @@ -489,7 +489,12 @@ impl WaylandPlatform { // shift content away from the border instead of into it. let raw_offset = dwindow.geometry().loc; let content_offset = smithay::utils::Point::<i32, smithay::utils::Logical>::from((raw_offset.x.max(0), raw_offset.y.max(0))); - let pos = (geom.x - content_offset.x, geom.y + band - content_offset.y); + // `frame`, not `geom` - see the matching comment in + // `udev/render.rs`'s own content push: content and the + // decoration around it have to come from the same rect, + // or they visibly disagree for as long as a resize drag + // is ahead of the client. + let pos = (frame.x - content_offset.x, frame.y + band - content_offset.y); let rounded = rounded_corners_enabled.then_some(self.state.rounded_corners_program.as_ref()).flatten().and_then(|program| { let corners = if w.decorated { crate::rounded_corners::RoundedCorners::BOTTOM_ONLY } else { crate::rounded_corners::RoundedCorners::ALL }; crate::rounded_corners::rounded_content_element(renderer, program, &surface, pos, w.opacity, w.corner_radius as f32, corners) |