srdusr
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crates/wayland/src/udev/render.rs67
1 files changed, 63 insertions, 4 deletions
diff --git a/crates/wayland/src/udev/render.rs b/crates/wayland/src/udev/render.rs
index f9dc739..6bf2979 100644
--- a/crates/wayland/src/udev/render.rs
+++ b/crates/wayland/src/udev/render.rs
@@ -415,7 +415,18 @@ impl CompState {
// built at, or `rounded_content_buffer`'s cache would
// never consider one stale after a resize.
let content_will_be_masked = if rounded_corners_enabled && self.wm.borrow().resizing_window() != Some(id) {
- let content_offset = self.id_to_window.get(&id).map(|dw| dw.geometry().loc).unwrap_or_default();
+ // Clamped to non-negative - see the matching clamp
+ // on the real content push's own `content_offset`
+ // further down for why: a real CSD shadow margin is
+ // never negative, but a live Firefox window was
+ // observed reporting `loc = (-10, -10)` despite the
+ // tiled-state hint telling it to reserve no margin
+ // at all (`TEMP-DIAG5`, confirmed live). Treating
+ // that raw negative value as a real offset shifts
+ // this mask's own origin the *wrong* way - away
+ // from alignment with the border, not toward it.
+ let raw_offset = self.id_to_window.get(&id).map(|dw| dw.geometry().loc).unwrap_or_default();
+ let content_offset = Point::<i32, Logical>::from((raw_offset.x.max(0), raw_offset.y.max(0)));
let band = if w.decorated { srdwm_core::TITLEBAR_HEIGHT as i32 } else { 0 };
let content_size = (frame.width as i32, (frame.height as i32 - band).max(0));
let loc = (-content_offset.x, -content_offset.y);
@@ -706,8 +717,56 @@ impl CompState {
// over each window" - confirmed by diffing a
// corner crop against the real wallpaper at
// that exact screen position, pixel for pixel.
- let content_offset = dwindow.geometry().loc;
- let pos = (geom.x - origin.x - content_offset.x, geom.y + band - origin.y - content_offset.y);
+ //
+ // Clamped to non-negative: a real shadow margin
+ // is never negative, but a live Firefox window
+ // was observed reporting `loc = (-10, -10)`
+ // despite `sync_geometry`'s tiled-state hint
+ // telling it to reserve no margin at all
+ // (`TEMP-DIAG5`, confirmed live). Subtracting
+ // that raw negative value shifts content the
+ // *wrong* way - further from the border this
+ // window's own `frame`/`effective_frame_of`
+ // (which already clamps this same value the
+ // same way for its own size calc) draws around,
+ // not toward it - reported live as Firefox's
+ // border sitting visibly detached, up and to
+ // the left, from its own real content.
+ let raw_offset = dwindow.geometry().loc;
+ let content_offset = Point::<i32, Logical>::from((raw_offset.x.max(0), raw_offset.y.max(0)));
+ // Where the window's real, margin-excluded
+ // visible content belongs on screen - what the
+ // masked/rounded buffer below is placed at,
+ // since `rounded_content_buffer`'s own `loc`
+ // parameter (`-content_offset`, just below)
+ // already renders that buffer's surface tree
+ // shifted so the buffer's *own* `(0, 0)` lands
+ // 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);
+ // Only for the *fallback* path below
+ // (`surface_content_elements`, pushed when
+ // masking is off or fails): that renders the
+ // client's raw surface tree directly, with no
+ // prior margin compensation of its own, so it's
+ // the one place `content_offset` still needs
+ // subtracting here. Reusing `content_pos` for
+ // both (what an earlier version of this did)
+ // double-applied the shift for the masked
+ // buffer - its own internal `loc`-based
+ // compensation, then this `pos` subtracting the
+ // same margin a second time - landing the
+ // masked buffer `content_offset` px too far up
+ // and left of the border wrapping it. Confirmed
+ // live via pixel sampling a real Firefox window
+ // (`raw_offset = (10, 10)`): its own chrome
+ // rendered starting 10px above where the
+ // border's nominal top edge began, fully
+ // exposed, square, with no border over it at
+ // all - reported as "border isn't correctly
+ // over the window."
+ let pos = (content_pos.0 - content_offset.x, content_pos.1 - content_offset.y);
let mut rounded_elem = None;
// Skipped for whichever window is being
// interactively resized right now, specifically
@@ -762,7 +821,7 @@ impl CompState {
let loc = (-content_offset.x, -content_offset.y);
let masked = crate::elements::rounded_content_buffer(&mut self.rounded_content_buffers, &mut udev.renderer, epoch, id, &surface, loc, content_size, w.corner_radius as f32, corners);
if let Some(buffer) = masked {
- match MemoryRenderBufferRenderElement::from_buffer(&mut udev.renderer, (pos.0 as f64, pos.1 as f64), buffer, Some(w.opacity), None, None, Kind::Unspecified) {
+ match MemoryRenderBufferRenderElement::from_buffer(&mut udev.renderer, (content_pos.0 as f64, content_pos.1 as f64), buffer, Some(w.opacity), None, None, Kind::Unspecified) {
Ok(elem) => rounded_elem = Some(elem),
Err(e) => log::warn!("udev: failed to import rounded content buffer: {e}"),
}