Reported on Hyprland: "anything from the library opens on my main display instead of
the virtual screen."
Hyprland and wlroots/sway are the two EXTEND-only backends: the per-session headless
output is added *beside* the operator's heads and nothing promotes it (KWin and Mutter
promote theirs primary; gamescope nests the app in its own compositor). Both compositors
open a new window on the FOCUSED monitor, and `output create headless` / `create_output`
does not focus what it creates — so focus stayed on the physical head and every library
launch opened where the client could not see it, with the stream showing a bare desktop.
Nothing in the tree moved or focused a window: no `focusmonitor`, no window rule, no
post-map correction. The launch path's own doc comment asserted the opposite ("KWin /
Mutter / wlroots ... the per-session virtual output is promoted primary, so a plain spawn
lands the app on the streamed output") — false for wlroots, and Hyprland was not listed.
Both backends now claim focus for the head they are about to stream, and the launch path
re-asserts it immediately before the spawn: the portal handshake, the encoder build and
the first frame all sit between capture bring-up and the launch, so a create-time focus
alone can be lost before the app ever starts. The name comes from the same slot the
absolute-input pointer is bound to, so focus and cursor land on one head by construction.
`focus_streamed_output` is gated on each backend's own managed-name predicate, which keeps
the mirror-pin case out — there the streamed head is a physical monitor the operator is
using, and stealing its focus is a change nobody asked for. Its match is exhaustive on
purpose so a backend added later has to decide rather than inherit "no focus" silently.
This does not implement the `primary`/`exclusive` topology levels on these two backends —
they are still accepted, echoed by the management API and dropped with a warning (sweep
13.18, whose shipped fix was the warning only). Focus is the extend-topology answer to
window placement and leaves the operator's monitors lit.
Tests pin the two argv shapes, which is where this can silently regress: `focusmonitor` is
a dispatcher and needs `hyprctl dispatch`, while sway spells its command `focus output
<name>` with the noun second, unlike every other call in that file. Both wrong forms are
rejected at exit 0 / with an error whose only field symptom is the bug itself.