feat(vdisplay): complete Stage 5 §6A group semantics — per-group restore, Mutter group-aware, gamescope groups
Host-side completion of Stage 5 (§6A many-clients-as-monitors), all unit-tested; two-session on-glass validation still pending (no GPU on the dev VM): - Per-group topology restore (§6.1): the KWin `exclusive` restore no longer rides the per-session StopGuard (which re-enabled the physical the moment the FIRST of several exclusive sessions dropped, under a live sibling). KWin hands its restore to the registry as a closure (new trait `take_topology_restore`); the registry keeps it in the display group (`Entry.topology_restore`) and, on teardown, floats it to a surviving same-group sibling (`hand_off_restore`) or runs it when the group empties — outside the lock, before the last output's keepalive drops, so the compositor never sees zero outputs. All three teardown paths (lease drop / linger expiry / mgmt release) honor it. Single-display path byte-for-byte unchanged. Unit-tested: float / run-on-last / non-carrier-first / never-cross-backend. - Mutter group-aware (new trait `set_first_in_group`): the registry tells each backend whether it's the first display of its group; a non-first Mutter session EXTENDS into the already-exclusive desktop instead of re-applying a sole-monitor ApplyMonitorsConfig that would disable the first session's virtual. (Mutter connectors are un-nameable, so it can't build a keep-all-virtuals config; skipping is the safe equivalent.) Single-session unchanged. Residual APPLY_TEMPORARY revert documented. - gamescope groups (§6.1): `registry::group_key` makes each gamescope spawn its own group (independent nested session, no shared desktop) — never auto-rowed against or restore-/topology-grouped with another gamescope. Applied in both the /display/state assembly and the acquire-time position computation. Unit-tested. Remaining Stage 5: the web console arrangement table, on-glass validation, and the documented residuals (wlroots exclusive, Mutter APPLY_TEMPORARY). design doc updated. cargo build/test (214)/clippy --all-targets/fmt green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,26 @@ pub trait VirtualDisplay: Send {
|
||||
/// single-display / first-of-group session issues no positioning at all. Best-effort — a failure
|
||||
/// leaves the compositor's default placement.
|
||||
fn apply_position(&mut self, _x: i32, _y: i32) {}
|
||||
/// Take the topology **restore** action this [`create`](Self::create) prepared — the work that
|
||||
/// un-does an `exclusive`/`primary` topology change (e.g. re-enable the physical outputs KWin
|
||||
/// disabled). The registry lifts it into the display **group** so it runs **once, when the group's
|
||||
/// last display is torn down** (design §6.1 — per-group restore), not when this one session's
|
||||
/// display drops: a sibling `exclusive` session must not have the physical re-enabled under it.
|
||||
/// Called right after `create`; the backend must not also run it itself. Default `None` — a backend
|
||||
/// whose topology auto-reverts (Mutter `APPLY_TEMPORARY`) or that changes nothing has nothing to
|
||||
/// hand off.
|
||||
fn take_topology_restore(&mut self) -> Option<Box<dyn FnOnce() + Send>> {
|
||||
None
|
||||
}
|
||||
/// Tell the backend whether this create will be the **first** display in its group — i.e. no
|
||||
/// sibling of the same backend is already live (design §6.1). A backend that *establishes* the
|
||||
/// group's topology (Mutter's sole-monitor `exclusive` `ApplyMonitorsConfig`) applies it only when
|
||||
/// first; a later sibling **extends** into the already-exclusive desktop instead of re-clobbering it
|
||||
/// (a fresh sole-monitor config would disable the first session's virtual output). Set by the
|
||||
/// registry right before [`create`](Self::create). Default no-op: KWin recognises siblings at
|
||||
/// runtime by output name (first-slot-wins + a group-aware disable filter), and single-display
|
||||
/// backends never have a sibling.
|
||||
fn set_first_in_group(&mut self, _first: bool) {}
|
||||
}
|
||||
|
||||
/// Compositors punktfunk knows how to drive (plan §6).
|
||||
|
||||
Reference in New Issue
Block a user