iOS Silently Misroutes Modifier-Key Commands When a Keyboard and Mouse Are Both Present
Symptom
Modifier-key shortcuts (Cmd+V, Cmd+A, Shift+X) intermittently failed on iPhone. Plain keypresses worked every time. Our HID write to /dev/hidg0 returned success consistently, nothing happened on-device.
Root cause, isolated via controlled experiment
iOS system logs show the resulting Key Command's KeyboardFocus target flipping from the correct foreground app to com.apple.springboard under specific conditions:
cmd-v -> <keyboardFocus; pid: 9085; token: MobileNotes> # working
cmd-v -> <keyboardFocus; pid: 3738; token: com.apple.springboard> # broken
Testing keyboard-only vs. keyboard-plus-mouse topologies (identical iOS settings, identical test method) isolated the trigger:
AssistiveTouch enabled + iOS detecting Pointer/Mouse capability on the connected device at the same time as a keyboard.
| Setup | Topology | Result |
|---|---|---|
| Keyboard-only | pointer: 0 | 32/32 successful |
| Same keyboard + real USB mouse | keyboard + mouse | 11 succeeded, 4 dropped to SpringBoard |
| Real gaming keyboard | keyboard + firmware-declared virtual mouse | Cmd/Shift/Option commands enter SpringBoard |
| Bluetooth keyboard (Keychron K2 Max) | BLE keyboard + mouse collection | 32 attempted, 26 dropped to SpringBoard |
Reproduced independent of our own hardware on a real gaming keyboard with a firmware-declared virtual mouse, and a Bluetooth keyboard with a mouse collection in its descriptor, ruling out an HID-compatibility explanation specific to our stack. This is an iOS-side routing bug, not an Aiden-specific one.
Workaround
Not a fix, we have no visibility into iOS internals. Aiden runs two USB HID profiles with distinct Product IDs:
- Normal operation: keyboard + pointer
- Executing a modifier-key action: re-enumerates to keyboard-only first, runs the shortcut, then restores pointer capability
Switching scope covers a full agent action rather than a single keypress, to avoid the software keyboard repeatedly popping and retracting mid-action.
Links
- Full writeup with the complete experiment table and log output: aidenai.io/blog
- Repo (open, AGPL-3.0 for the open components): github.com/AidenAI-IO/aiden-firmware
Curious if anyone here working on iOS accessibility, remote control, or device automation tooling has run into the same failure mode, it doesn't seem tied to our specific implementation at all.