The ownership split (design/display-management.md §3): the registry owns the
per-session virtual-display lifecycle on Linux, so a display can outlive its
session (keep-alive) and be reused on reconnect.
- registry.rs: a Linux pool driven by the pure lifecycle machine. acquire()
reuses a kept (lingering/pinned) display of the same backend+mode, else
creates one and keeps the backend's keepalive so the compositor output (and
its PipeWire node_id) survives the session. The session's capturer holds a
gen-stamped DisplayLease instead of the real keepalive; its drop drives
linger/teardown. Enabling fact: KWin/Mutter/gamescope put their node on the
DEFAULT PipeWire daemon (remote_fd=None) — reconnect re-attaches by node_id,
no fd re-open. wlroots (remote_fd=Some, xdpw portal) passes through unchanged
(teardown-on-drop) pending the fresh-portal-capture re-attach.
- Default (unconfigured) linger = Immediate → today's teardown-on-disconnect,
so no behavior change without a keep-alive policy; concurrent sessions still
each create their own output (reuse only matches LINGERING entries).
- Wired build_pipeline (punktfunk1) + gamestream through registry::acquire;
capture_virtual_output signature unchanged. Windows delegates to vd.create
(the manager already leases) — unchanged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Stage 1 of design/display-management.md — the lifecycle core + the display
management surface:
- vdisplay/lifecycle.rs: pure per-slot state machine (Idle/Active{refs}/
Lingering{until}/Pinned) with acquire/release/expiry/force-release
transitions. No I/O, no OS types — the platform-neutral distillation of the
Windows manager's model. Unit + a 200k-iteration seeded property walk
(no leaks / double-frees / refcount underflow across arbitrary interleavings).
- vdisplay/registry.rs: neutral snapshot/release facade over the per-OS
lifecycle owners. Windows reads/controls the VirtualDisplayManager; Linux
keep-alive (a per-session pool) lands in a following increment (needs GPU-box
validation).
- windows/manager.rs: additive snapshot() + force_release() (no behavior change
to the on-glass-validated path).
- mgmt: GET /api/v1/display/state (live/kept displays) + POST /api/v1/display/release
(tear down lingering/pinned now; refuses active). OpenAPI regenerated.
- web console: Virtual displays card gains a live-display list (polled) with
per-row + release-all buttons and a linger countdown.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>