chore: adjust auto release key interval

This commit is contained in:
Siyuan Miao 2025-09-11 17:46:50 +02:00
parent f10a2283d4
commit bc94ae5856
2 changed files with 43 additions and 20 deletions

View File

@ -22,6 +22,11 @@ var keyboardConfig = gadgetConfigItem{
reportDesc: keyboardReportDesc,
}
// macOS default: 15 * 15 = 225ms https://discussions.apple.com/thread/1316947?sortBy=rank
// Linux default: 250ms https://man.archlinux.org/man/kbdrate.8.en
// Windows default: 1ms `HKEY_CURRENT_USER\Control Panel\Accessibility\Keyboard Response\AutoRepeatDelay`
const autoReleaseKeyboardInterval = time.Millisecond * 225
// Source: https://www.kernel.org/doc/Documentation/usb/gadget_hid.txt
var keyboardReportDesc = []byte{
0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */
@ -173,8 +178,6 @@ func (u *UsbGadget) SetOnKeysDownChange(f func(state KeysDownState)) {
u.onKeysDownChange = &f
}
const autoReleaseKeyboardInterval = time.Millisecond * 450
func (u *UsbGadget) scheduleAutoRelease(key byte) {
u.kbdAutoReleaseLock.Lock()
defer u.kbdAutoReleaseLock.Unlock()
@ -222,7 +225,8 @@ func (u *UsbGadget) performAutoRelease(key byte) {
default:
}
_, err := u.keypressReport(key, false, false)
// we just reset the keyboard state to 0 no matter what
_, err := u.keypressReport(0, false, false)
if err != nil {
u.log.Warn().Uint8("key", key).Msg("failed to auto-release keyboard key")
}
@ -453,23 +457,6 @@ func (u *UsbGadget) keypressReport(key byte, press bool, autoRelease bool) (Keys
}
}
// if autoRelease {
// u.kbdAutoReleaseLock.Lock()
// u.kbdAutoReleaseLock.Unlock()
// ll.Uint8("key", key).Msg("locking kbdAutoReleaseLock, autoReleasLastKey reset")
// defer func() {
// ll.Uint8("key", key).Msg("unlocked kbdAutoReleaseLock, autoReleasLastKey reset")
// }()
// if u.kbdAutoReleaseLastKey == key {
// ll.Uint8("key", key).Msg("key already released by auto-release, skipping")
// u.kbdAutoReleaseLastKey = 0
// return u.UpdateKeysDown(modifier, keys), nil
// }
// }
err := u.keyboardWriteHidFile(modifier, keys)
if err != nil {
u.log.Warn().Uint8("modifier", modifier).Uints8("keys", keys).Msg("Could not write keypress report to hidg0")

View File

@ -220,6 +220,42 @@ export default function useKeyboard() {
// we don't need to cancel it actually
cancelOngoingKeyboardMacroHidRpc();
}, [rpcHidReady, cancelOngoingKeyboardMacroHidRpc, abortController]);
};
const KEEPALIVE_INTERVAL = 75; // 200ms interval
const cancelKeepAlive = useCallback(() => {
if (keepAliveTimerRef.current) {
clearInterval(keepAliveTimerRef.current);
keepAliveTimerRef.current = null;
}
}, []);
const scheduleKeepAlive = useCallback(() => {
// Clear existing timer if it exists
if (keepAliveTimerRef.current) {
clearInterval(keepAliveTimerRef.current);
}
// Create new interval timer
keepAliveTimerRef.current = setInterval(() => {
sendKeypressKeepAliveHidRpc();
}, KEEPALIVE_INTERVAL);
}, [sendKeypressKeepAliveHidRpc]);
// resetKeyboardState is used to reset the keyboard state to no keys pressed and no modifiers.
// This is useful for macros and when the browser loses focus to ensure that the keyboard state
// is clean.
const resetKeyboardState = useCallback(async () => {
// Cancel keepalive since we're resetting the keyboard state
cancelKeepAlive();
// Reset the keys buffer to zeros and the modifier state to zero
keysDownState.keys.length = hidKeyBufferSize;
keysDownState.keys.fill(0);
keysDownState.modifier = 0;
sendKeyboardEvent(keysDownState);
}, [keysDownState, sendKeyboardEvent, cancelKeepAlive]);
// handleKeyPress is used to handle a key press or release event.
// This function handle both key press and key release events.