fix(windows/cursor-flip): flag + forced same-mode re-commit — the working un-declare

The empty-caps un-declare is REJECTED by IddCx (STATUS_INVALID_PARAMETER,
on-glass driver 9.9.0722.1407) — there is no un-declare DDI. The
composite flip now works with the only lever the OS gives us: every
mode COMMIT reverts the path to the software cursor, and the driver
skips its per-commit re-declare while cursor_forward_on is off. So:

- driver: disable stores the flag only (no DDI call); enable still
  declares immediately against the live worker's event.
- host capturer: after a successful disable flip, force a same-mode
  re-commit (win_display::force_mode_reenumeration) — DWM composites
  the pointer from the very next commit; the swap-chain flap is the
  class the driver's preserved-publisher machinery already rides out.
- state now survives re-arrivals end-to-end: the capturer caches the
  APPLIED state (cleared on every channel (re)delivery, which
  re-created driver entries need — their flag defaults to declared),
  and the stream loop re-applies every tick instead of edge-gating
  (steady-state cost: one Option compare).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-22 23:43:23 +02:00
co-authored by Claude Opus 4.8
parent 79d30fde64
commit b50e4767de
4 changed files with 74 additions and 45 deletions
+6 -3
View File
@@ -2033,11 +2033,14 @@ pub(super) fn virtual_stream(ctx: SessionContext, prepared: Option<PreparedDispl
// frame-attached overlay (the Linux portal path).
if let Some(fwd) = cursor_fwd.as_mut() {
let client_draws = cursor_client_draws.load(Ordering::Relaxed);
// EVERY tick, not edge-gated: the capturer caches the applied state (an Option
// compare in steady state) and clears it on channel re-deliveries — so the render
// state survives capturer rebuilds AND driver-side monitor re-arrivals, which an
// edge detector here silently lost. Windows IDD (un)declares the driver's hardware
// cursor; no-op on every other capturer.
capturer.set_cursor_forward(client_draws);
if client_draws != cursor_client_drew {
cursor_client_drew = client_draws;
// Windows IDD: (un)declare the driver's hardware cursor so DWM excludes vs
// composites; no-op on every other capturer.
capturer.set_cursor_forward(client_draws);
tracing::info!(
client_draws,
"cursor render mode flipped ({})",