srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland/src/state
diff options
context:
space:
mode:
Diffstat (limited to 'crates/wayland/src/state')
-rw-r--r--crates/wayland/src/state/geometry.rs53
1 files changed, 38 insertions, 15 deletions
diff --git a/crates/wayland/src/state/geometry.rs b/crates/wayland/src/state/geometry.rs
index 774eabc..b537412 100644
--- a/crates/wayland/src/state/geometry.rs
+++ b/crates/wayland/src/state/geometry.rs
@@ -84,21 +84,44 @@ impl CompState {
// settling and any reasonable commit-throttle window), until an
// unrelated maximize/restore cycle on the same window happened to
// prompt Firefox into resending a fresh hint and self-correcting.
- // `bbox()` - the real bounding box of the window's current surface
- // tree - updates on every commit unconditionally, independent of
- // whether the client also chose to resend the optional hint, so it
- // has no equivalent staleness window. The one thing this gives up
- // is excluding a CSD client's own invisible drop-shadow margin from
- // the border/content area - but `sync_geometry` already
- // unconditionally tells every window it is tiled on all four sides
- // specifically so a compliant client (GTK4/Firefox concretely, see
- // that function's own doc comment) reserves no such margin at all,
- // so a compliant client loses nothing here. A client that ignores
- // the tiled hint and reserves one anyway ends up with a border a
- // few pixels larger than its real visible chrome - a real but
- // strictly smaller, more cosmetic problem than one stuck at the
- // wrong size and position indefinitely.
- let content = dwindow.bbox();
+ //
+ // A first fix switched outright to `bbox()` - the real bounding
+ // box of the window's current surface tree, which updates on every
+ // commit unconditionally - on the reasoning that `sync_geometry`
+ // already unconditionally tells every window it is tiled on all
+ // four sides specifically so a compliant client reserves no
+ // invisible shadow margin, so nothing would be lost by no longer
+ // excluding one. Wrong: confirmed live via temporary diagnostic
+ // logging, Chrome reserves a real, correctly-current 10px margin on
+ // all four sides regardless of the tiled hint (Firefox, the window
+ // that exposed the original bug, does not - the two disagree on
+ // this, not just on how quickly they resend the hint). Raw `bbox()`
+ // gave the border/content mask Chrome's *entire* buffer, margin
+ // included - 20px wider and taller than its real visible chrome on
+ // each axis, with no compensating position shift - so the rounded
+ // border curve traced a rectangle Chrome's real content never
+ // reached, and its true, still-square corner poked straight through
+ // the curve instead of being hidden by it.
+ //
+ // The fix keeps both properties at once: a margin, `dwindow_
+ // geometry.loc`, assumed symmetric (left == right, top == bottom --
+ // true of every real CSD shadow margin observed here: a fixed
+ // design constant, not something that scales with window size) is
+ // far more durable than the rest of that same hint. A resize
+ // changes a client's real content size; it does not change how
+ // large that client's own shadow is, so the margin has no
+ // equivalent staleness window even while the hint's absolute size
+ // does. Subtracting it from the always-fresh `bbox()` - instead of
+ // trusting the hint's own absolute size (stale-prone) or using
+ // bbox() raw (margin-blind) - gets a content rect that is both
+ // current and correctly excludes the invisible margin, for a
+ // client that reserves one (Chrome) and one that doesn't (Firefox,
+ // where the hint's `.loc` is always `(0, 0)` and this reduces to
+ // plain `bbox()`) alike.
+ let dwindow_geometry = dwindow.geometry();
+ let bbox = dwindow.bbox();
+ let margin = (dwindow_geometry.loc.x.max(0), dwindow_geometry.loc.y.max(0));
+ let content = Rectangle::new(bbox.loc, (bbox.size.w - 2 * margin.0, bbox.size.h - 2 * margin.1).into());
if content.size.w <= 0 || content.size.h <= 0 {
// No real committed content yet - racing the first commit
// right after creation, most likely. Nothing to correct