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

6 KiB

STEP20C nested valid-grab fixture (EXPERIMENTAL)

This source-only fixture reproduces the nested popup probe. 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/.

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.

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.