feat(windows): IddCx hardware-cursor channel — remote-desktop sweep M2c

Brings the cursor channel to Windows hosts. The pf-vdisplay driver
declares an IddCx hardware cursor for sessions that negotiated
cursor-forward — DWM then EXCLUDES the pointer from the IDD frame and
delivers shape/position out-of-band, into the same CursorOverlay →
forwarder → wire → client pipeline the Linux portal path uses.

- pf-driver-proto v5 (additive, host floor stays 3): AddRequest's spare
  tail becomes hw_cursor (same size/offsets); IOCTL_SET_CURSOR_CHANNEL
  delivers a host-created CursorShm section (64-byte seqlock header +
  256² shape buffer, layout pinned + tested). No event crosses the
  boundary — the host polls at encode-tick pace.
- driver: wdk-iddcx grows the two cursor DDI wrappers; a per-monitor
  cursor worker (event wait → QueryHardwareCursor → seqlock publish)
  starts only when BOTH the ADD asked and the channel arrived, so a
  failed delivery leaves DWM compositing as today. Shape bytes ship raw
  (BGRA/masked + pitch); the host converts.
- host: the section rides the existing sealed-channel broker (least-
  privilege dup, remote reap on failure); IddPushCapturer::cursor()
  seqlock-reads → CursorOverlay (BGRA→RGBA, masked-color approximation,
  desktop→frame origin shift, per-shape conversion cache). New
  Capturer::cursor() trait hook — the encode loop prefers it over the
  frame-attached overlay because hardware-cursor moves produce NO new
  frame on a static desktop. hw_cursor survives the re-arrival resize
  (carried on the manager's Monitor).
- negotiation: cursor_forward grows the Windows arm (client cap ∧
  driver proto ≥ 5, probed once via the control device); SessionPlan
  carries cursor_forward → OutputFormat.hw_cursor.
- drive-by: wdk-probe's two pre-existing same-type casts (clippy) and
  pf-vdisplay's stale spike-test refs (crate::win_display moved to
  pf-win-display; tracing-subscriber was never a dep) repaired.

Verified: proto tests on Mac AND MSVC (15/15 incl. the CursorShm
layout pin); clippy -D warnings for proto/frame/capture/vdisplay/host
on Linux (.21) and native Windows (.173); the DRIVER workspace clippy
-D warnings green against the real WDK 10.0.26100 bindgen (DDI names,
enum variants and IDARG layouts all bind). On-box driver deploy +
on-glass validation follow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-22 23:43:23 +02:00
co-authored by Claude Fable 5
parent c3cbffe662
commit 3a34440a6b
21 changed files with 1009 additions and 36 deletions
@@ -97,6 +97,8 @@ pub unsafe fn dispatch(request: WDFREQUEST, ioctl_code: u32) {
control::IOCTL_SET_FRAME_CHANNEL => unsafe { set_frame_channel(request) },
// SAFETY: `request` is the framework WDFREQUEST.
control::IOCTL_UPDATE_MODES => unsafe { update_modes(request) },
// SAFETY: `request` is the framework WDFREQUEST.
control::IOCTL_SET_CURSOR_CHANNEL => unsafe { set_cursor_channel(request) },
_ => complete(request, STATUS_NOT_FOUND),
}
}
@@ -148,6 +150,7 @@ unsafe fn add(request: WDFREQUEST) {
max_frame_avg_nits: req.max_frame_avg_nits,
min_millinits: req.min_luminance_millinits,
},
req.hw_cursor != 0,
) else {
complete(request, STATUS_NOT_FOUND);
return;
@@ -174,6 +177,35 @@ unsafe fn add(request: WDFREQUEST) {
///
/// # Safety
/// `request` is the framework `WDFREQUEST`.
/// `IOCTL_SET_CURSOR_CHANNEL` (v5): adopt a monitor's hardware-cursor section, declare the
/// hardware cursor to the OS, start the query→publish worker.
///
/// # Safety
/// `request` is the framework `WDFREQUEST`.
unsafe fn set_cursor_channel(request: WDFREQUEST) {
// SAFETY: `request` is the framework WDFREQUEST.
let Some(req) = (unsafe { read_input::<control::SetCursorChannelRequest>(request) }) else {
complete(request, STATUS_INVALID_PARAMETER);
return;
};
let Some(ch) = crate::cursor_worker::CursorChannel::from_request(&req) else {
complete(request, STATUS_INVALID_PARAMETER);
return;
};
match crate::monitor::set_cursor_channel(req.target_id, ch) {
Ok(()) => complete(request, STATUS_SUCCESS),
Err(ch) => {
dbglog!(
"[pf-vd] SET_CURSOR_CHANNEL: no hw-cursor monitor with target_id {} — rejecting",
req.target_id
);
// NOT adopted: the host's error path reaps the duplicated handle remotely.
ch.into_unowned();
complete(request, STATUS_NOT_FOUND);
}
}
}
unsafe fn set_frame_channel(request: WDFREQUEST) {
// SAFETY: `request` is the framework WDFREQUEST.
let Some(req) = (unsafe { read_input::<control::SetFrameChannelRequest>(request) }) else {