Compare commits

...

1 Commits

Author SHA1 Message Date
Marc Brooks 93dbd280fb
Reduce traffic during pastes
Suspend KeyDownMessages while processing a macro.
Make sure we don't emit huge debugging traces.
Allow 30 seconds for RPC to finish (not ideal)
Reduced default delay between keys (and allow as low as 0)
2025-09-24 19:23:45 -05:00
4 changed files with 34 additions and 15 deletions

View File

@ -65,15 +65,17 @@ func handleHidRPCMessage(message hidrpc.Message, session *Session) {
func onHidMessage(msg hidQueueMessage, session *Session) { func onHidMessage(msg hidQueueMessage, session *Session) {
data := msg.Data data := msg.Data
dataLen := len(data)
scopedLogger := hidRPCLogger.With(). scopedLogger := hidRPCLogger.With().
Str("channel", msg.channel). Str("channel", msg.channel).
Bytes("data", data). Int("data_len", dataLen).
Bytes("data", data[:min(dataLen, 32)]).
Logger() Logger()
scopedLogger.Debug().Msg("HID RPC message received") scopedLogger.Debug().Msg("HID RPC message received")
if len(data) < 1 { if dataLen < 1 {
scopedLogger.Warn().Int("length", len(data)).Msg("received empty data in HID RPC message handler") scopedLogger.Warn().Msg("received empty data in HID RPC message handler")
return return
} }
@ -96,7 +98,7 @@ func onHidMessage(msg hidQueueMessage, session *Session) {
r <- nil r <- nil
}() }()
select { select {
case <-time.After(1 * time.Second): case <-time.After(30 * time.Second):
scopedLogger.Warn().Msg("HID RPC message timed out") scopedLogger.Warn().Msg("HID RPC message timed out")
case <-r: case <-r:
scopedLogger.Debug().Dur("duration", time.Since(t)).Msg("HID RPC message handled") scopedLogger.Debug().Dur("duration", time.Since(t)).Msg("HID RPC message handled")

View File

@ -153,6 +153,16 @@ func (u *UsbGadget) SetOnKeysDownChange(f func(state KeysDownState)) {
u.onKeysDownChange = &f u.onKeysDownChange = &f
} }
var suspendedKeyDownMessages bool = false
func (u *UsbGadget) SuspendKeyDownMessages() {
suspendedKeyDownMessages = true
}
func (u *UsbGadget) ResumeSuspendKeyDownMessages() {
suspendedKeyDownMessages = false
}
func (u *UsbGadget) SetOnKeepAliveReset(f func()) { func (u *UsbGadget) SetOnKeepAliveReset(f func()) {
u.onKeepAliveReset = &f u.onKeepAliveReset = &f
} }
@ -169,9 +179,9 @@ func (u *UsbGadget) scheduleAutoRelease(key byte) {
} }
// TODO: make this configurable // TODO: make this configurable
// We currently hardcode the duration to 100ms // We currently hardcode the duration to the default of 100ms
// However, it should be the same as the duration of the keep-alive reset called baseExtension. // However, it should be the same as the duration of the keep-alive reset called baseExtension.
u.kbdAutoReleaseTimers[key] = time.AfterFunc(100*time.Millisecond, func() { u.kbdAutoReleaseTimers[key] = time.AfterFunc(DefaultAutoReleaseDuration, func() {
u.performAutoRelease(key) u.performAutoRelease(key)
}) })
} }
@ -353,7 +363,7 @@ func (u *UsbGadget) UpdateKeysDown(modifier byte, keys []byte) KeysDownState {
u.keysDownState = state u.keysDownState = state
u.keyboardStateLock.Unlock() u.keyboardStateLock.Unlock()
if u.onKeysDownChange != nil { if u.onKeysDownChange != nil && !suspendedKeyDownMessages {
(*u.onKeysDownChange)(state) // this enques to the outgoing hidrpc queue via usb.go → currentSession.enqueueKeysDownState(...) (*u.onKeysDownChange)(state) // this enques to the outgoing hidrpc queue via usb.go → currentSession.enqueueKeysDownState(...)
} }
return state return state

View File

@ -1132,7 +1132,13 @@ func isClearKeyStep(step hidrpc.KeyboardMacroStep) bool {
} }
func rpcDoExecuteKeyboardMacro(ctx context.Context, macro []hidrpc.KeyboardMacroStep) error { func rpcDoExecuteKeyboardMacro(ctx context.Context, macro []hidrpc.KeyboardMacroStep) error {
logger.Debug().Interface("macro", macro).Msg("Executing keyboard macro") logger.Debug().Int("macro_steps", len(macro)).Msg("Executing keyboard macro")
// don't report keyboard state changes while executing the macro
gadget.SuspendKeyDownMessages()
defer func() {
gadget.ResumeSuspendKeyDownMessages()
}()
for i, step := range macro { for i, step := range macro {
delay := time.Duration(step.Delay) * time.Millisecond delay := time.Duration(step.Delay) * time.Millisecond

View File

@ -27,10 +27,10 @@ export default function PasteModal() {
const { executeMacro, cancelExecuteMacro } = useKeyboard(); const { executeMacro, cancelExecuteMacro } = useKeyboard();
const [invalidChars, setInvalidChars] = useState<string[]>([]); const [invalidChars, setInvalidChars] = useState<string[]>([]);
const [delayValue, setDelayValue] = useState(100); const [delayValue, setDelayValue] = useState(20);
const delay = useMemo(() => { const delay = useMemo(() => {
if (delayValue < 50 || delayValue > 65534) { if (delayValue < 0 || delayValue > 65534) {
return 100; return 20;
} }
return delayValue; return delayValue;
}, [delayValue]); }, [delayValue]);
@ -136,7 +136,8 @@ export default function PasteModal() {
<div <div
className="w-full" className="w-full"
onKeyUp={e => e.stopPropagation()} onKeyUp={e => e.stopPropagation()}
onKeyDown={e => e.stopPropagation()} onKeyDownCapture={e => e.stopPropagation()} onKeyDown={e => e.stopPropagation()}
onKeyDownCapture={e => e.stopPropagation()}
onKeyUpCapture={e => e.stopPropagation()} onKeyUpCapture={e => e.stopPropagation()}
> >
<TextAreaWithLabel <TextAreaWithLabel
@ -186,18 +187,18 @@ export default function PasteModal() {
type="number" type="number"
label="Delay between keys" label="Delay between keys"
placeholder="Delay between keys" placeholder="Delay between keys"
min={50} min={0}
max={65534} max={65534}
value={delayValue} value={delayValue}
onChange={e => { onChange={e => {
setDelayValue(parseInt(e.target.value, 10)); setDelayValue(parseInt(e.target.value, 10));
}} }}
/> />
{delayValue < 50 || delayValue > 65534 && ( {delayValue < 0 || delayValue > 65534 && (
<div className="mt-2 flex items-center gap-x-2"> <div className="mt-2 flex items-center gap-x-2">
<ExclamationCircleIcon className="h-4 w-4 text-red-500 dark:text-red-400" /> <ExclamationCircleIcon className="h-4 w-4 text-red-500 dark:text-red-400" />
<span className="text-xs text-red-500 dark:text-red-400"> <span className="text-xs text-red-500 dark:text-red-400">
Delay must be between 50 and 65534 Delay must be between 0 and 65534
</span> </span>
</div> </div>
)} )}