#674

fix(display): bounded exclusive topology maintenance for post-apply physical-output return (issue 599)

OpenDABnoREGRETwants to merge intofrom

What

Fixes #599

After an exclusive virtual-display stream, the host re-attached both physical displays a few seconds later, so the requested exclusive layout was never maintained (physical primary stayed enabled / layout not applied).

The display helper v2 state machine had a gap: while an exclusive request was active (singleton topology, VirtualDisplayMonitoring), later topology-change evidence (DisplayChange / PowerResume / DeviceArrival / DeviceRemoval) was not fed into the exclusive maintenance path. The post-apply reactivation gap was therefore never closed.

Fix

Bounded "Exclusive topology maintenance" verification lane added to the display helper v2 state machine (Windows backend):

  • New verification purpose: VerificationPurpose::ExclusiveTopologyMaintenance.
  • New bounded state: exclusive_topology_check_pending_, exclusive_topology_quiet_until_, exclusive_topology_repairs_remaining_.
  • On a topology-evidence display event during an exclusive request with a singleton topology, pending check unset, repairs remaining > 0 and quiet period elapsed → arm check, transition to Verification, dispatch verification (750 ms delay, purpose ExclusiveTopologyMaintenance, expected topology = current_request_.topology).
  • On verification completion:
    • clear pending; ignore stale completions;
    • success → enter_steady_state;
    • repairs exhausted → warn and return to steady state;
    • otherwise decrement repairs, suppress further applies for the session, transition and dispatch apply worker (0 ms).
  • Exclusive request detection uses the exclusive virtual layout string; recovery state cleared on helper teardown.

Scope / known limitation

This closes the maintainer-confirmed failure stage (post-apply reactivation + maintenance of the exclusive topology). It does not attempt to re-derive identity, apply-gate or per-app override root causes, which remain separate investigation lanes.

Testing

  • g++ -std=c++23 -fsyntax-only -DSUNSHINE_TEST_PORTABLE_WINDOWS_TYPES ... src/platform/windows/display_helper_v2/state_machine.cpp → clean.
  • Regression test added: Issue599ExclusiveMaintainsTopologyOnPostApplyDisplayChange (asserts verification dispatched with 750 ms delay, exclusive purpose and singleton topology).
  • Full Windows build / runtime validation happens on the Windows CI box (test_component_windows_display_recovery, installer/MSI workflow).

🤖 Generated with OpenCode (Flint)