(ctx context.Context, macro []hidrpc.KeyboardMacroStep)
| 1289 | } |
| 1290 | |
| 1291 | func rpcDoExecuteKeyboardMacro(ctx context.Context, macro []hidrpc.KeyboardMacroStep) error { |
| 1292 | logger.Debug().Interface("macro", macro).Msg("Executing keyboard macro") |
| 1293 | |
| 1294 | for i, step := range macro { |
| 1295 | delay := time.Duration(step.Delay) * time.Millisecond |
| 1296 | |
| 1297 | err := rpcKeyboardReport(step.Modifier, step.Keys) |
| 1298 | if err != nil { |
| 1299 | logger.Warn().Err(err).Msg("failed to execute keyboard macro") |
| 1300 | return err |
| 1301 | } |
| 1302 | |
| 1303 | // notify the device that the keyboard state is being cleared |
| 1304 | if isClearKeyStep(step) { |
| 1305 | gadget.UpdateKeysDown(0, keyboardClearStateKeys) |
| 1306 | } |
| 1307 | |
| 1308 | // Use context-aware sleep that can be cancelled |
| 1309 | select { |
| 1310 | case <-time.After(delay): |
| 1311 | // Sleep completed normally |
| 1312 | case <-ctx.Done(): |
| 1313 | // make sure keyboard state is reset |
| 1314 | err := rpcKeyboardReport(0, keyboardClearStateKeys) |
| 1315 | if err != nil { |
| 1316 | logger.Warn().Err(err).Msg("failed to reset keyboard state") |
| 1317 | } |
| 1318 | |
| 1319 | logger.Debug().Int("step", i).Msg("Keyboard macro cancelled during sleep") |
| 1320 | return ctx.Err() |
| 1321 | } |
| 1322 | } |
| 1323 | |
| 1324 | return nil |
| 1325 | } |
| 1326 | |
| 1327 | var rpcHandlers = map[string]RPCHandler{ |
| 1328 | "ping": {Func: rpcPing}, |
no test coverage detected