Skip to content

Conversation

@ym
Copy link
Contributor

@ym ym commented Aug 29, 2025

This PR moved HID events to a dedicated queue and switched from JSONRPC to a custom binary format to improve performance under poor network conditions.

It's also worth noting that the /dev/hidg* endpoints can sometimes hang indefinitely, so a timeout was introduced to prevent the queue from being blocked forever in such cases.

Copy link
Contributor

@IDisposable IDisposable left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that was fast :) suggestions/questions are not blockers

CapsLock bool `json:"caps_lock"`
ScrollLock bool `json:"scroll_lock"`
Compose bool `json:"compose"`
Kana bool `json:"kana"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wished I had killed off these bools already :(

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was kept for backwards compatibility.

@ym ym force-pushed the feat/hid-channel branch from 533fc86 to 3a5af59 Compare September 1, 2025 06:54
@ym ym force-pushed the feat/hid-channel branch from 3a5af59 to e181523 Compare September 1, 2025 06:56
@adamshiervani adamshiervani added this to the 0.4.7 milestone Sep 1, 2025
@adamshiervani adamshiervani moved this to In Review in JetKVM Sep 1, 2025
@ym ym force-pushed the feat/hid-channel branch from c8e5be2 to 7feb92c Compare September 1, 2025 10:31
@ym ym requested a review from adamshiervani September 1, 2025 10:31
Comment on lines 145 to 153
if (rpcHidReady) {
console.debug("Sending keypress event via HidRPC");
reportKeypressEvent(key, press);
return;
}

if (keyPressReportApiAvailable) {
// if the keyPress api is available, we can just send the key press event
sendKeypressEvent(key, press);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a bit of duplicate logic:

  • keyPressReportApiAvailable isn’t useful, since it’s effectively the same as rpcHidReady.
  • sendKeypressEvent() duplicates the preceding if statement in this function. Just replace keyPressReportApiAvailable with rpcHidReady and remove the preceding if statement.

send("relMouseReport", { dx: calcDelta(x), dy: calcDelta(y), buttons });
const dx = calcDelta(x);
const dy = calcDelta(y);
if (rpcHidReady) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I’d suggest not using useHidRPC() directly for mouse and keyboard events. Instead, let hidRPC serve purely as a transport layer, with dedicated hooks handling input logic.

We use useKeyboard() for keyboard input and useRPC() for mouse reports. Mixing approaches like this adds confusion and clutters an already complex HID JS API surface.

A clearer approach would be to introduce both useMouse() and useKeyboard() hooks. That way, consumption is consistent and obvious, while each hook can encapsulate its own complexity.

We added useKeyboard() out of necessity because its fallback logic was big. That isn’t the case for the mouse, where the fallback is rather simple -- but, I would say the added clarity and consistency still make a useMouse() hook worthwhile.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, moving mouse logic to useMouse

@ym ym requested a review from adamshiervani September 4, 2025 09:19
@ym ym requested a review from IDisposable September 4, 2025 09:25
const getRelMouseMoveHandler = useCallback(
({ isPointerLockActive, isPointerLockPossible }: RelMouseMoveHandlerProps) => (e: MouseEvent) => {
if (mouseMode !== "relative") return;
if (isPointerLockActive === false && isPointerLockPossible) return;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you didn't actually change this (just moved here from WebRTVideo.tsx), but this seems odd... do we only support relative mouse mode if we can lock the pointer, AND have locked the pointer?

If that's the case, then what happens if we haven't locked? We ignore all mouse events?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it's definitely odd ... Let me just remove it


keyPressReportApiAvailable: boolean;
setkeyPressReportApiAvailable: (available: boolean) => void;
// keyPressReportApiAvailable is no longer needed, we'll simply use hidChannel available to
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could probably just delete this commented-out code.

};

document.addEventListener("fullscreenchange ", handleFullscreenChange);
document.addEventListener("fullscreenchange", handleFullscreenChange);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WOW, nice catch... this could explain some of the oddities of focus when going in and out of fullscreen repeatedly

Copy link
Contributor

@IDisposable IDisposable left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit: (we can discuss the relative mouse locked mode elsewhere)

@IDisposable
Copy link
Contributor

:shipit:

@adamshiervani adamshiervani merged commit bcc307b into dev Sep 4, 2025
3 checks passed
@github-project-automation github-project-automation bot moved this from In Review to Done in JetKVM Sep 4, 2025
@adamshiervani adamshiervani deleted the feat/hid-channel branch September 4, 2025 20:28
ym added a commit to ym/jetkvm-kvm that referenced this pull request Sep 26, 2025
* feat: use hidRpcChannel to save bandwidth

* chore: simplify handshake of hid rpc

* add logs

* chore: add timeout when writing to hid endpoints

* fix issues

* chore: show hid rpc version

* refactor hidrpc marshal / unmarshal

* add queues for keyboard / mouse event

* chore: change logging level of JSONRPC send event to trace

* minor changes related to logging

* fix: nil check

* chore: add comments and remove unused code

* add useMouse

* chore: log msg data only when debug or trace mode

* chore: make tslint happy

* chore: unlock keyboardStateLock before calling onKeysDownChange

* chore: remove keyPressReportApiAvailable

* chore: change version handle

* chore: clean up unused functions

* remove comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants