srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/state/geometry.rs
diff options
context:
space:
mode:
authorsrdusr <[email protected]>2025-08-09 00:57:00 +0200
committersrdusr <[email protected]>2025-08-09 00:57:00 +0200
commit61d01bb79c6882c950f45a1176ba1f30fbbd4824 (patch)
treeeb2a24c7f301f74f987f954b62d768c9cb789fef /crates/wayland/src/state/geometry.rs
parent9e811d2f2f1037ba4ec08ab0e05b350e6cf69e66 (diff)
downloadsrdwm-61d01bb79c6882c950f45a1176ba1f30fbbd4824.tar.gz
srdwm-61d01bb79c6882c950f45a1176ba1f30fbbd4824.zip
Fix interactive-resize border/shadow lag without the OOB risk that sank the first attempt
effective_frame_of now returns the live drag target while a window is being interactively resized (same change as the reverted first attempt), but two things make it safe this time instead of reintroducing the out-of-bounds texture sample that reversion was for: - Every src crop rect built from a window's frame width in udev/render.rs and winit/render.rs (titlebar, top border strip, bottom border strip) is now clamped against DecorationSignature's own recorded width/ border_width - the bitmap's actual last-built size - before reaching MemoryRenderBufferRenderElement::from_buffer, which does not itself validate src against the real texture size. This is a structural floor independent of timing, not a repeat of the previous unsafe approach. - handle_pointer_position now calls redraw_decoration_buffer once per resize motion event (throttled to 60Hz via a new CompState::resize_redraw_at), closing the lag at its source instead of only catching up on the next real client commit. This also fixes the shadow bitmap's identical commit-vs-live-position gap for free, since redraw_decoration_buffer rebuilds all three bitmaps together. Updates the TODO.md entry for this bug with the full before/after.
Diffstat (limited to 'crates/wayland/src/state/geometry.rs')
-rw-r--r--crates/wayland/src/state/geometry.rs43
1 files changed, 31 insertions, 12 deletions
diff --git a/crates/wayland/src/state/geometry.rs b/crates/wayland/src/state/geometry.rs
index b537412..26c23fe 100644
--- a/crates/wayland/src/state/geometry.rs
+++ b/crates/wayland/src/state/geometry.rs
@@ -46,22 +46,41 @@ impl CompState {
// in a more important way - every caller of this function that
// reads a *bitmap*-backed element (the titlebar, the top/bottom
// border strip's own rounded-corner bitmap, both built by `redraw_
- // decoration_buffer`, itself only called on a real client *commit*,
- // not on every resize step) uses this rect's width/height to size
- // the `src` crop rectangle it samples that bitmap with. Making this
+ // decoration_buffer`) uses this rect's width/height to size the
+ // `src` crop rectangle it samples that bitmap with. Making this
// function return the *live* drag target while the underlying
// bitmap was still sized for whatever the *last commit* actually
- // was means that crop can end up larger than the real bitmap's own
- // stored dimensions - `MemoryRenderBufferRenderElement::from_
+ // was meant that crop could end up larger than the real bitmap's
+ // own stored dimensions - `MemoryRenderBufferRenderElement::from_
// buffer` does not validate `src` against the texture's real size,
// so an oversized crop reads as an out-of-bounds texture sample
- // (stretched/repeated/garbage pixels, not a clean error) for as
- // long as a fast resize keeps outrunning the client's own recommit
- // rate - a worse, more visibly broken failure mode than the
- // one-frame-stale lag it replaced. Fixing the lag properly needs
- // `redraw_decoration_buffer` itself rebuilding on every resize
- // step, not just on commit, which is real, separate scope - not
- // yet done.
+ // (stretched/repeated/garbage pixels, not a clean error).
+ //
+ // Now reinstated, safely: this returns the *live* drag target
+ // (`geom`, unmodified) while a resize of this specific window is
+ // active, same as the reverted attempt did - but two things are
+ // different this time, together closing the gap that made it
+ // unsafe rather than just re-taking the risk:
+ // 1. `input::pointer::handle_pointer_position` now calls
+ // `redraw_decoration_buffer` on every resize motion tick (see
+ // its own doc comment), not just on a real client commit, so
+ // the bitmap itself keeps catching up to this same live value
+ // almost every frame instead of staying pinned to the last
+ // commit for the resize's whole duration.
+ // 2. Independent of how well-synced that keeps the two, every
+ // render-loop call site that turns this rect's width/height
+ // into a `src` crop now clamps it against `decoration_
+ // signatures`' own recorded `(width, height)` - the bitmap's
+ // own *actual* last-built size, tracked there already for
+ // unrelated caching reasons - before handing it to `from_
+ // buffer`. That clamp is what actually prevents the out-of-
+ // bounds read now, structurally, regardless of any remaining
+ // timing gap between this function and the next rebuild; this
+ // branch existing is what keeps that gap small in practice
+ // rather than a full commit-cycle wide.
+ if wm.borrow().resizing_window() == Some(id) {
+ return geom;
+ }
let Some(w) = wm.borrow().window(id).cloned() else { return geom };
let Some(dwindow) = id_to_window.get(&id) else { return geom };
// `dwindow.geometry()` - `xdg_surface::set_window_geometry` - is,