add workaround for river wm rotation issue

This commit is contained in:
2026-08-02 21:30:41 +02:00
parent 44aca6d476
commit 9dba86f3ca
4 changed files with 202 additions and 7 deletions
+26
View File
@@ -76,6 +76,32 @@ pixels. `render_output()` allocates a device-pixel buffer of `width * scale` and
shorter output dimension (`att_grid()`), which is what makes rotation and arbitrary aspect ratios
work with no special cases.
**Output resize / rotation** — the surface size comes from `configure` and *only* from `configure`:
ext-session-lock makes a buffer that does not match the acked size a `dimensions_mismatch` error,
which kills the client and leaves the session locked with nothing drawing on it. So the locker can
never resize itself on its own initiative.
That matters because not every compositor reconfigures. River 0.4.5 configures a lock surface once,
when it is created, and never again (`LockSurface.create()` is the only `configure()` call site, and
nothing in `Output.zig` re-issues one), so rotating or re-moding an output used to leave the locker
painting at the old size, clipped to the overlap. `att_lock` therefore watches `wl_output`
(`mode`/`geometry`/`scale`), and if the output changed shape but no configure arrives within
`RESIZE_GRACE_MS`, `recreate_lock_surface()` destroys the lock surface and makes a new one for the
same output, which forces a fresh configure at the current size. The lock object is untouched, so
the session stays locked across the swap.
Two guards keep this from misfiring, and both matter:
- The change detector compares `wl_output` values against a snapshot of `wl_output` values taken at
the last configure (`cfg_*`), never against the configured surface size. On a fractionally scaled
output the integer `wl_output.scale` cannot reproduce the logical size, so those two would never
match and every idle moment would look like a pending resize.
- `retry_*` records the geometry a recreate was already attempted for, so a compositor that ignores
the recreate is nagged once instead of being put in a destroy/create loop.
A compositor that does send a configure never reaches any of this: by the time the grace period
expires the snapshot matches again and `outputs_recheck_geometry()` does nothing.
**Pattern model** (`src/pattern.c`) — a sequence of dot indices (`row * 4 + col`). `pattern_add()`
implements the Android rule that unvisited dots lying exactly on the straight line between the
previous and new dot get captured first, using the gcd of the row/col delta. `pattern_to_string()`