What
After an exclusive virtual-display stream, the remote-monitor coordinator restore could leave the main monitor secondary, to the right of the other monitor, and on a fixed ~60 Hz mode. In this report it was a 4K monitor using Windows Dynamic Refresh Rate, which CCD reports as 240/4, and it came back at 59997/1000. That broken layout could then be captured as the next session's restore baseline, so the user had to fix the layout by hand after every stream.
This builds on libdisplaydevice's exact temporary mode restore (18bdadb) and fills the parts that master doesn't cover yet:
- Coordinator restore order. The coordinator now restores topology, then primary, then origins, then refresh. Refresh uses
setDisplayModesExactTemporaryand is best-effort: a refresh-only failure logs the requested and read-back rationals and no longer blocks primary or origins. - Exact baseline refresh. The coordinator baseline records the exact refresh rational.
- Failed-compose guard. If the geometry of a coordinator compose (topology, primary, origins) fails,
SNAPSHOT_CURRENTis blocked until a later compose succeeds, or until a saved baseline device is no longer connected (all-pathstargetAvailable, checked only while the guard is set). A Windows-database fallback layout is therefore never saved as the baseline. The guard is serialised, never held across helper IPC, and a newer compose supersedes an in-flight capture. - Snapshot policy. Captures that contain a transient session VDD are rejected, because creating one may already have moved the physical origins or primary. This reverses b589fb4b's filter-and-keep, but only for transient VDDs. Permanent and excluded VDDs keep the filter-and-keep behaviour, so they still get a baseline. Host-side capture checks use Active-only enumeration.
- Inventory and baseline guards are Windows-only.
Depends on Nonary/libdisplaydevice#16 (enumActiveDevices() and the exact-restore hook). The submodule currently points at that PR's commit 023be7e on my fork, so CI cannot fetch it until #16 lands. I'll re-point the submodule to the merged commit afterwards.
Known limitation (upstream, unchanged here)
equalRefreshRates cross-multiplies, so a broken fixed 60/1 (or 120/2) compares equal to DRR 240/4, and the exact restore short-circuits without re-entering DRR. ExactTemporaryAcceptsEquivalentNormalizedReadback locks this behaviour in. The reported incident (59997/1000) is not affected. I'll raise it separately.
Coordinator refresh restore is temporary (not saved to the Windows display database), consistent with the snapshot path.
Testing
- MSYS2 UCRT64 build of
sunshineandsunshine_display_helperon masterdb35f052. - All 20 display test targets pass, including new coordinator-order, refresh-only-failure, guard (geometry failure, disconnected device, stale evidence, IPC supersession) and exact-mode restore tests.
- On hardware: an earlier port of these changes onto 2.0.0 ran a real Legion Go 2 session (RTX 5090, MSI 4K DRR plus AOC, exclusive layout). The logs show:
- no
ERROR_INVALID_PARAMETERor coordinator failures at teardown; - the golden-first REVERT found the layout already matching: MSI primary at (0,0), DRR
240/4.
- no
- This exact master-based commit has not been tested on hardware yet.
- The original 2.0.0 diagnosis also involved the SetDisplayConfig flag fixes, which 18bdadb has since covered.
🤖 Generated with Claude Code
Activity
8Retargeted to canary and rebased (clean, no conflicts). The libdisplaydevice submodule now points at the merged 0e9a30e. Both review findings are addressed in 404baaefb; display tests pass (32/32).
Pushed c6fef1ae7 (four commits on canary; the display tests pass 32/32 locally, on Windows only, no live hardware run yet). Known limits, so nothing is overclaimed:
- The failed-compose protection lives in host memory only. A failed restore followed by a host restart (update, reboot, crash) loses it, and the next snapshot could save the damaged layout. Persisting it would need a new state file, so I left it out of this PR.
- Helper-side snapshot files are not fenced against in-process composes. A SNAPSHOT_CURRENT or EXPORT_GOLDEN already queued when a compose starts may still save a mid-compose layout (the host reports it as superseded and logs a warning).
previousandgoldenkeep the earlier state. - The guard protects the coordinator's saved layout, not the helper's session snapshot: after a successful REVERT the helper deletes its current snapshot and the next APPLY captures the live layout itself.
- The exact refresh restore still does nothing when Windows reports 60/1 against a saved 240/4 (Nonary/libdisplaydevice#17); a test pins that upstream limitation.
- 'Proven missing' means the target is reported unavailable at that moment, so a monitor in deep sleep is filtered from the compose input (its stored geometry is kept).
Could you retarget this PR to
canaryand resolve any resulting conflicts on your branch? That is the integration target for this change.