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) {
data := msg.Data
dataLen := len(data)
scopedLogger := hidRPCLogger.With().
Str("channel", msg.channel).
Bytes("data", data).
Int("data_len", dataLen).
Bytes("data", data[:min(dataLen, 32)]).
Logger()
scopedLogger.Debug().Msg("HID RPC message received")
if len(data) < 1 {
scopedLogger.Warn().Int("length", len(data)).Msg("received empty data in HID RPC message handler")
if dataLen < 1 {
scopedLogger.Warn().Msg("received empty data in HID RPC message handler")
return
}
@ -96,7 +98,7 @@ func onHidMessage(msg hidQueueMessage, session *Session) {
r <- nil
}()
select {
case <-time.After(1 * time.Second):
case <-time.After(30 * time.Second):
scopedLogger.Warn().Msg("HID RPC message timed out")
case <-r:
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
}
var suspendedKeyDownMessages bool = false
func (u *UsbGadget) SuspendKeyDownMessages() {
suspendedKeyDownMessages = true
}
func (u *UsbGadget) ResumeSuspendKeyDownMessages() {
suspendedKeyDownMessages = false
}
func (u *UsbGadget) SetOnKeepAliveReset(f func()) {
u.onKeepAliveReset = &f
}
@ -169,9 +179,9 @@ func (u *UsbGadget) scheduleAutoRelease(key byte) {
}
// 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.
u.kbdAutoReleaseTimers[key] = time.AfterFunc(100*time.Millisecond, func() {
u.kbdAutoReleaseTimers[key] = time.AfterFunc(DefaultAutoReleaseDuration, func() {
u.performAutoRelease(key)
})
}
@ -353,7 +363,7 @@ func (u *UsbGadget) UpdateKeysDown(modifier byte, keys []byte) KeysDownState {
u.keysDownState = state
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(...)
}
return state

View File

@ -1132,7 +1132,13 @@ func isClearKeyStep(step hidrpc.KeyboardMacroStep) bool {
}
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 {
delay := time.Duration(step.Delay) * time.Millisecond

View File

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