-
Notifications
You must be signed in to change notification settings - Fork 222
Rework keyboard management to allow device-side tracking of modifier states #725
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rework keyboard management to allow device-side tracking of modifier states #725
Conversation
0dd7098
to
1e57f4b
Compare
@adamshiervani looks like this is mostly complete to get the state managed device-side. There was a lot of work done to make the type-checking better because I had trouble working out some issues, so I just hardened up the code to get it to the point where the error was "obvious". Sadly in the end it was some odd interaction between Go's default serialization of uint8/byte values to JSON, which if given an array slice of uint8/byte will emit the slice as a base-64 encoded blob... on the typescript side, that doesn't get recognized as an array, so passing the keys-down wasn't working. In the end, I added a Now that I'm mostly done, might want to chat through if I did this the way we want. One thing I've realized just today is that if the client UI tries to make the new rpc calls to the device and it's not current.. well. Might have to restore the code I elided in commit 0c76634 and do some device-version detection? |
Rebased and conflicts resolved |
Remove LED sync source option and add keypress reporting while still working with devices that haven't been upgraded We return the modifiers as the valid bitmask so that the VirtualKeyboard and InfoBar can represent the correct keys as down. This is important when we have strokes like Left-Control + Right-Control + Keypad-1 (used in switching KVMs and such). Fix handling of modifier keys in client and also removed the extraneous resetKeyboardState. Manage state to eliminate rerenders by judicious use of useMemo. Centralized keyboard layout and localized display maps Move keyboardOptions to useKeyboardLayouts Added translations for display maps. Add documentation on the legacy support. Return the KeysDownState from keyboardReport Clear out the hidErrorRollOver once sent to reset the keyboard to nothing down. Handles the returned KeysDownState from keyboardReport Now passes all logic through handleKeyPress. If we get a state back from a keyboardReport, use it and also enable keypressReport because we now know it's an upgraded device. Added exposition on isoCode management Fix de-DE chars to reflect German E2 keyboard. https://kbdlayout.info/kbdgre2/overview+virtualkeys Ran go modernize Morphs Interface{} to any Ranges over SplitSeq and FieldSeq for iterating splits Used min for end calculation remote_mount.Read Used range 16 in wol.createMagicPacket DID NOT apply the Omitempty cleanup. Strong typed in the typescript realm. Cleanup react state management to enable upgrading Zustand
942de9d
to
f903a6d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hell yeah, amazing work!!! Let's get this merged now.
Whew... |
Trying this out locally and seems like LMeta is not able to be held down. When I press and hold it down, the status bar only shows it pressed for a split second |
LMeta is pretty hard to manage because it pops up the OS menus when the browser/remote is on Windows and MacOS... mostly the only way I can get things to work with LMeta+something is to use Macros or Virtual Keyboard, but I would like to know more about how it acts on your system. Can you record a video or screen-share? |
Before this pr, i was able to easily use Windows+Shift+S, but now I have to basically press all 3 at once and release quickly Jetkvm connected to Windows |
Trying to get to the bottom of this! Please bear with me... Do you mean pressing keys on the physical keyboard? What OS is the browser/client running on? I think you mean you've got flowchart LR
PC[Linux] -->|press physical key | LMeta
LMeta --> Browser[fa:fa-browser Chrome]
Browser -->|event| JetKVM[client]
JetKVM -->|RPC| Device
Device -->|HID| Host[Windows]
Also, are you keyboard trapped, fullscreen + running the JetKVM on an HTTPS (not HTTP)? |
Oh, do you mean that you before could press-and-release LMeta, press-and-release Shift, press S and it would be seen as a Windows+Shift+S on the host? If that's the case I suspect that's because the old keyboard stack wasn't processing things in order or synchronously (which broke all kinds of input things and basically had to be fixed to be in-order processing. |
No, i could press shift, then meta, then s, Windows would register it, then I would release all 3. Yes, pressing and holding the physical key would only show as a quick press and release of the LMeta key. I have 0 issues holding down LMeta in dwm or hyprland to move stuff around or executing other shortcuts that use LMeta. |
Non-fullscreen and absolute mouse so not keyboard trapped. Wish that worked but it doesnt even with an https reverse proxy with an LE cert. |
Client = Arch in Firefox I have 0 shortcuts set to LMeta+Shift+S |
Preview: 20250828_235857.mp4 |
Great repro, thanks...will look into that ASAP |
One thing I noticed: Over IP (without HTTPS) I do see this momentary press |
this part here is the one causing the momentary MetaLeft press |
Nice find |
On Linux when I press Alt key and change the focus of the window without releasing it, the browser will force release it. So I dont know if the following statement is correct.
One for @IDisposable to confirm |
Commented out that 2 blocks and deployed and everything works for me 20250829_083600.mp4 |
|
||
u.log.Trace().Interface("old", u.keysDownState).Interface("new", state).Msg("keysDownState updated") | ||
u.keysDownState = state | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On review post folks beginning to test, I think I should have released the Lock here to ensure we're not holding through the entire callback for onKeysDownChange. Thoughts @adamshiervani ?
As far as I know, the app.jetkvm.com has not been updated yet since this isn't fully released. Thus it is still using the ReportKeys (old stack/Macros) instead of the ReportKeyPress (new stack)
Correct, not sure how to handle it now, but I certainly can remove that code in favor of a lazy timer. The comment remains true, though, because if someone is not in fullscreen on an HTTPS connection, we can't grab a keyboard lock, and thus the LMeta kicks in for the browser's OS (and thus we would never see the key up event. This code (in a different form existed before) see https://github.com/jetkvm/kvm/pull/725/files#diff-503edceb49a3a14452eb4663ab40040a5ff04a2a89f13e48be02539e2c939f08L441-L450 I will try to find a better way that doesn't force the key-up event unless we've lost focus and some interval passes... but that's going to be fun because it's possible for the key state to get out of sync with the device and host... so have to protect that. |
Interesting... maybe I should just not special-case the LMeta at all... |
As far as I know, the code on app.jetkvm.com is the old stack still (since 0.5 hasn't actually released). To get the new stack for now, you will have to be running against the device directly (via IP or your local DNS name) In fact I had to rework some stuff in this PR to support the opposite case (when app has been upgraded but the device hasn't)... wheeee |
Awesome, thanks for confirming... I'm all in favor of just not special casing things :) What's the "other" block you deleted? |
Remove LED sync source option and add keypress reporting while still working with devices that haven't been upgraded We return the modifiers as the valid bitmask so that the VirtualKeyboard and InfoBar can represent the correct keys as down. This is important when we have strokes like Left-Control + Right-Control + Keypad-1 (used in switching KVMs and such). Fix handling of modifier keys in client and also removed the extraneous resetKeyboardState. Manage state to eliminate rerenders by judicious use of useMemo. Centralized keyboard layout and localized display maps Move keyboardOptions to useKeyboardLayouts Added translations for display maps. Add documentation on the legacy support. Return the KeysDownState from keyboardReport Clear out the hidErrorRollOver once sent to reset the keyboard to nothing down. Handles the returned KeysDownState from keyboardReport Now passes all logic through handleKeyPress. If we get a state back from a keyboardReport, use it and also enable keypressReport because we now know it's an upgraded device. Added exposition on isoCode management Fix de-DE chars to reflect German E2 keyboard. https://kbdlayout.info/kbdgre2/overview+virtualkeys Ran go modernize Morphs Interface{} to any Ranges over SplitSeq and FieldSeq for iterating splits Used min for end calculation remote_mount.Read Used range 16 in wol.createMagicPacket DID NOT apply the Omitempty cleanup. Strong typed in the typescript realm. Cleanup react state management to enable upgrading Zustand
This is the beginnings of the rework of the keyboard support.
Goals:
reportKeypress
to pass all the keydown / keyup events so it can track the meta state and LED state