From df218f96eadd176e514a52123fb0c477ae728ac1 Mon Sep 17 00:00:00 2001 From: LinkPass888 <57739158+LinkPass888@users.noreply.github.com> Date: Wed, 30 Sep 2026 14:25:54 +0800 Subject: [PATCH] feat(rapoo): drive the VT9 Pro through the Rapoo HID client The mouse-protocol PR that adds the Rapoo codec and its WebHID client also adds RapooHidClient, and it was not on the list of clients the controller opens on connect. Without that entry the driver never gets to run against a device that is already picked, which is the whole point of the client: it answers on its own vendor collection, so nothing else notices it. The client reports the battery on its own when the transport has no receiveInputReport (WebHID alone cannot read the register channel), and when OpenMouse Bridge supplies it the same connect path unlocks DPI, polling rate and the sensor settings. --- src/device/controller.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/device/controller.ts b/src/device/controller.ts index 3c5ec76..b3915a9 100644 --- a/src/device/controller.ts +++ b/src/device/controller.ts @@ -169,6 +169,7 @@ import { MicrosoftHidClient } from "@openmouse/protocol/drivers/microsoft/hid"; import { DareuHidClient } from "@openmouse/protocol/drivers/dareu/hid"; import { IncottHidClient } from "@openmouse/protocol/drivers/incott/hid"; import { BytechHidClient } from "@openmouse/protocol/drivers/bytech/hid"; +import { RapooHidClient } from "@openmouse/protocol/drivers/rapoo/hid"; import { parsePreviewMode, previewsEnabled, type PreviewMode } from "../preview-modes"; import { sleepLabel } from "./options"; import { traitsFor } from "./traits"; @@ -243,7 +244,12 @@ function activeAs(...classes: ClientClass[]): T | null { const DM_CLASSES = [WLMouseHidClient, LamzuHidClient, LamzuAtlantisHidClient, AtkHidClient, AtkBitmouseHidClient, NinjutsoHidClient] as const; const RAZER_CLASSES = [RazerHidClient, RazerViperMiniHidClient, RazerViperHidClient, RazerCobraHidClient] as const; -const NEEDS_OPEN = [LamzuAtlantisHidClient, TeevolutionHidClient, VgnF2HidClient, KeychronNapeHidClient, KeychronM6HidClient, WLMouseBeastX4kHidClient, ModdoHidClient, ZaunkoenigHidClient, CorsairHidClient, FantechHidClient, WallhackMouseHidClient, WallhackKeyboardHidClient, GloriousHidClient, GloriousClassicHidClient, MchoseHidClient, MchoseDockHidClient, MchoseA5ProMaxHidClient, MchoseV3HidClient, MicrosoftHidClient, DareuHidClient, IncottHidClient, BytechHidClient] as const; +// Rapoo's VT9 Pro listens on its own vendor collection and answers reads +// through GET_REPORT(Input), which in the browser means OpenMouse Bridge: +// opening it on connect is what makes the register walk in readStatus() +// possible, and the driver reports the battery on its own when Bridge is +// absent rather than failing. +const NEEDS_OPEN = [LamzuAtlantisHidClient, TeevolutionHidClient, VgnF2HidClient, KeychronNapeHidClient, KeychronM6HidClient, WLMouseBeastX4kHidClient, ModdoHidClient, ZaunkoenigHidClient, CorsairHidClient, FantechHidClient, WallhackMouseHidClient, WallhackKeyboardHidClient, GloriousHidClient, GloriousClassicHidClient, MchoseHidClient, MchoseDockHidClient, MchoseA5ProMaxHidClient, MchoseV3HidClient, MicrosoftHidClient, DareuHidClient, IncottHidClient, BytechHidClient, RapooHidClient] as const; const PULSAR_CLASSES = [PulsarHidClient, PulsarProHidClient, PulsarXs1HidClient] as const; const logitechClient = (): LogitechHidppClient | null => activeAs(LogitechHidppClient);