feat(windows): back the virtual mouse with a real HID device - #99
Conversation
The Windows mouse backend synthesised input with SendInput, which travels the Win32 cursor pipeline. Applications that read mouse input through the Raw Input API observe nothing on that path, so relative-motion controls such as camera look and click-drag are unusable while the mouse still appears to move on screen. Create the mouse as a HID device through the UMDF control channel, the same way gamepads are created, and deliver relative motion, buttons and scrolling as HID input reports. Raw Input consumers then see the device as they would a physical mouse. - Add a five-button mouse report descriptor with 16-bit relative axes, a wheel and an AC Pan axis. - Accumulate sub-detent high-resolution scroll so precision is preserved across events. - Delegate absolute motion to the existing injection path, which has no relative HID equivalent. - Fall back to the previous SendInput mouse whenever the driver is unavailable, so mouse input keeps working without the driver package.
Address static analysis findings: test the optional with has_value() and hold the HID button bitmask as std::byte rather than a raw integer.
90e8d3e to
f64667d
Compare
|
Thank you for the PR submission, but it looks like you used AI to create this PR. No problem with that, but please read and follow our Contributing guidelines and specifically our AI Usage policy. Additionally, please update the PR to use the correct template. You can find it at https://github.com/LizardByte/.github/blob/master/.github/pull_request_template.md?plain=1 I'll review shortly and address your notes. Thanks! |
Extends the Windows driver path to support Raw Input-visible mice alongside gamepads. Key changes: - Bumps control protocol to v3 and broker protocol to v4, renaming gamepad-specific structs/IOCTLs to generic device equivalents (e.g. `LvhWindowsCreateDeviceRequest`, `LVH_WINDOWS_IOCTL_CREATE_DEVICE`) - Adds `LVH_WINDOWS_DEVICE_GAMEPAD`/`LVH_WINDOWS_DEVICE_MOUSE` device type field to the create request - Introduces `mouse_protocol.hpp` with a canonical 7-byte five-button relative descriptor shared across backend, broker, and driver - `VhfInputReportQueue` gains a mouse accumulation path that batches relative motion/scroll by button state and emits descriptor-sized chunks, preventing VHF backpressure from discarding relative movement - `WindowsHidMouse` preserves caller-supplied bus type, VID, PID, version, name, manufacturer, and stable ID; falls back to `SendInput` only for license/availability errors, not protocol failures - Broker and driver validation enforce mouse-specific field constraints (fixed descriptor, no report ID, no output reports, no gamepad flags) - Renames internal gamepad-scoped state and methods to device-scoped equivalents (`WindowsVhfDeviceState`, `devices_` map, etc.)
|
Review generated by GPT-5.6 Sol. I fed this into my agent, since it has all the memory of decisions throughout the whole development of the project. Required changes
Answers to the questions in the PR body
I also had the agent make the changes, and put them into a separate branch (https://github.com/LizardByte/libvirtualhid/tree/feat/windows-hid-mouse). These changes end up much bigger than what you originally had. Feel free to review/push back on whatever. I did not really test any of this yet other than via unit tests locally. This is definitely something needed though, and was planned to be added here all along. I know I've greatly increased the complexity of the change, so if you'd rather I usher this to the finish line I'm fine with that (you'll still get credit for contributing and all). Also, I don't know if you're aware but I am granting some contributors free yearly licenses. Details are in https://app.lizardbyte.dev/2026-08-16-introducing-libvirtualhid-and-virtual-hid-driver/ ... feel free to apply after the PR is merged. |
|
Thanks for the detailed review, please do take it to the finish line. The remaining work is mostly inside the driver and broker, and I can't build or test that side properly from here, so you'll get there faster than I would. The queue coalescing point is the one I'm glad you caught. I reused the gamepad create path because it already carried an arbitrary descriptor, and I completely missed that replacing a pending report is fine for a gamepad reporting full state but destroys relative deltas from a mouse. That would have shown up as dropped movement under load and I'd have had no idea why. The other four all make sense to me, narrowing the fallback to unavailable/unlicensed, keeping the caller's profile identity, and carrying the remainder instead of clamping it away. On AI usage: it was moderate, and I should have said so up front. I've updated the PR to your template with that declared. I'll apply for a licence once this merges. Thanks again. |
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #99 +/- ##
==========================================
- Coverage 75.47% 72.85% -2.62%
==========================================
Files 34 34
Lines 8133 8752 +619
Branches 3044 3251 +207
==========================================
+ Hits 6138 6376 +238
- Misses 1454 2081 +627
+ Partials 541 295 -246
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 9 files with indirect coverage changes Continue to review full report in Codecov by Harness.
|
Extend the native control tool to create, inspect, reset, and remove virtual mice alongside gamepads. This adds keyboard-navigable mouse motion, button, and wheel actions, plus delayed browser-test scheduling for focus-sensitive mouse validation. Update the shared control model tests and refresh README and Windows/platform/store-review docs to reflect driver-backed mouse support and its licensing requirements.
|



Description
The Windows backend built its virtual mouse on
SendInput. That path goes through the Win32 cursor pipeline, which the Raw Input API does not observe. Applications readingWM_INPUTtherefore see no mouse at all, even though the cursor moves on screen, relative-motion controls like camera look and click-drag do nothing.This change creates the mouse as a real HID device through the UMDF control channel, the same route gamepads already take, and sends relative motion, buttons and scrolling as HID input reports.
WindowsHidMouse, which creates the device and submits seven-byte input reports.SendInputmouse when the driver is unavailable.Not verified on hardware, without a licence the driver declines device creation on my machine and the fallback path runs instead.
Superseded by the maintainer's branch
feat/windows-hid-mouse, which generalises device creation across the broker and driver protocols and adds a mouse-specific queue policy. See the review discussion below.Screenshot
N/A, not a UI change.
Issues Fixed or Closed
Roadmap Issues
Type of Change
Checklist
AI Usage
See our AI usage policy.