swayfx-mosaic/tooling/probes/step20c-nested-grab/README.md

97 lines
6 KiB
Markdown

# STEP20C nested valid-grab fixture (EXPERIMENTAL)
This source-only fixture reproduces the [nested popup probe](../../../docs/design/STEP20C_NESTED_VALID_GRAB_PROBE.md).
It does not enter the Mosaic build, production patch or package. It reuses
the unchanged `pointer-daemon.c`, virtual-pointer XML and three private
patches from [`../step20c-valid-grab/`](../step20c-valid-grab/README.md).
## Bases and dependencies
| Input | Pinned base / version | SHA-256 |
| --- | --- | --- |
| Mosaic private patch | Mosaic `cd550382b311efdbfe3ed892f4e1d281d852e754` | `d416f6413ea097a48a44d231e50ffba363914f46c8687f0ea2e4dcacd5f31fe9` |
| SceneFX private patch | SceneFX `37ccd723bef49e6891156ffafce8f549f01446cc` (0.5) | `c74c515b98da8f5f637e260e6a3755c7a75bd78d1c39e54a67850f1c383e30e7` |
| Hidden-owner guard | After Mosaic private patch | `35785a8f3e863b3c1fd87932d8ff0c2949b03cb04382cc34e1126170968f802b` |
| Persistent virtual pointer | Previous fixture | `a00fcedc38ccb7ca4c25c982d9f38e8bde3168a3833f0c9cf2056e841d720938` |
| Virtual-pointer XML | wlr-protocols `b010a03648b88d143236de193bddbfea0c08bc84` | `3ff6d540be0bc5228195bf072bde42117ea17945a5c2061add5d3cf97d6bb524` |
| `nested-client.c` | This fixture | `2e40c98af72a0df8b316810589a0be8f4425a763db1de448b49a7813956b6f7d` |
| `prepare.sh` | This fixture, post-audit failed-build cleanup | `55fe81b7f17fb1cf8af7089a0034864910c49feccbe4cfe22e857c98b9db0dde` |
| `run.py` | This fixture, post-audit socket isolation and cleanup | `72ff17d8042edf3265b3a0ff91f0bc4805001b1438c4ecadfe29ead76278c9be` |
The measured machine had SwayFX 0.6, wlroots 0.20.2, SceneFX 0.5.0,
Wayland client 1.26.0 and wayland-protocols 1.49. The installed XDG Shell
XML declares version 7; the fixture binds `xdg_wm_base` version 3, like
the previous client. Required local tools include Git, Meson, Ninja, C17
compiler, `pkg-config`, `wayland-scanner`, `kitty`, `swaymsg`, `grim`, `wev`
and Python. `prepare.sh` downloads the pinned SceneFX source into a disposable
directory; it does not install anything.
## Differences from the earlier fixture
`nested-client.c` creates three distinct surfaces and XDG roles. Popup A's
parent is the toplevel `xdg_surface`; popup B's parent is A's `xdg_surface`.
Each popup uses a separate, logged, real pointer-button serial and maps only
after its own configure/ack. The client logs all surface object IDs, events,
local pointer coordinates, `popup_done` and child-first destruction. It accepts
`close_b` and `close_owner` on stdin. The runner exercises three placements:
`visible`, `b_cross` and `both_cross`. No prior source file is modified.
## Fresh replay
Run from a fresh repository checkout at or after the preserved fixture commit.
No old `/tmp` laboratory is needed. The script prints `LAB=/tmp/...` after
building a private SceneFX library, private guarded compositor, new client and
unchanged virtual-pointer daemon. Save that path for subsequent commands.
```sh
prepare_log=$(mktemp /tmp/mng-prepare-XXXXXXXX)
sh tooling/probes/step20c-nested-grab/prepare.sh | tee "$prepare_log"
LAB=$(sed -n 's/^LAB=//p' "$prepare_log")
test -d "$LAB"
python tooling/probes/step20c-nested-grab/run.py "$LAB" control visible_click visible
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_standard visible_click visible
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic visible_click visible
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic crossing b_cross
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic crossing both_cross
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic close_b visible
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic outside visible
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic hidden b_cross
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic hidden_click b_cross
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic owner visible
python tooling/probes/step20c-nested-grab/run.py "$LAB" private_mosaic toggle b_cross
```
For a full comparison, repeat `crossing`, `close_b`, `outside` and `owner`
with `control` and `private_standard` as in the report. Each case name is
single-use in a lab; use a new lab or rename an earlier case directory to
retain both iterations. `run.py` uses a short, new `/tmp/mng-*` runtime path
because Unix socket paths have a strict length limit; each case's
`runtime-path` records the path for audit. The script removes inherited desktop
Wayland/IPC variables, uses explicit `swaymsg -s`, terminates and reaps only
its own process groups, then removes its runtime directory. It never reloads
or replaces the daily compositor.
The retained historical runs used the earlier runner and preparation hashes;
the current `prepare.sh` removes an incomplete laboratory on failure, while
`run.py` adds an IPC path-length bound, clears inherited
`I3SOCK`, reaps child processes and removes its runtime directory. It changes
no popup protocol action, capture point or experimental compositor patch.
Each case contains `client.log` with `WAYLAND_DEBUG=1`, `pointer.log`,
`compositor.log`, `wev.log`, `tree-*.json`, `outputs-*.json` and both output
PNGs. Read `POPUP_A/B CREATE`, `GRAB_REQUEST`, `ROLE_CONFIGURE`,
`XDG_CONFIGURE`, `MAP`, `POINTER_*`, `POPUP_DONE` and `DESTROY` in order.
Compare screenshots and traces: a right-output pixel alone does not prove
which surface received a button, and `popup_done` under a legitimate grab
does not prove an invisible surface hit. The `open` scenario intentionally
only captures mapping; `visible_click` also presses B. A case returning zero
is not automatically a scientific PASS.
## Cleanup
After all per-case processes have exited, check `runtime-path` files for any
directory left by an interrupted run and remove only those recorded `/tmp/mng-*`
directories, then remove the named `LAB` directory and `prepare_log`. Preserve
the laboratory while reviewing evidence. Generated
protocol files, binaries, private libraries, sockets, logs and images remain
outside Git. The source fixture and original patches stay in Git.