Repository navigation
feat(studio)!: hotkeys bind by physical key - #84
Conversation
Quest-Claim: 3ec65ecaa92cd3bf
A binding is winit's physical key, taken from the window's own key event before egui, so keypad keys bind apart from the main row and any key binds. X11 grabs by keycode through x11rb instead of global-hotkey, and Windows registers every binding again when the foreground window's layout changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 32 minutes. View limit details
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. |
kixelated
left a comment
There was a problem hiding this comment.
Automated review by review (OpenAI)
Reviewed head: 37ac09f
Base: 107f736
No actionable correctness findings in this static review of the 13-file change.
Direction and coverage:
- Physical-key identity now survives binding capture before egui, including keypad keys and unidentified native keys. Duplicate detection and action lookup use physical position and modifiers rather than the display label.
- X11 grabs and releases the same keycodes, handles the configured lock combinations, and suppresses detectable repeat presses. The Wayland portal receives keypad/Unicode keysyms while retaining desktop-selected shortcut behavior.
- Windows foreground-layout changes trigger re-registration on the window thread; native mapping and registration lifecycle were checked against the global-hotkey backend. The documented Windows keypad Enter and NumLock restrictions remain platform limitations, not guarantees of physical-key independence there.
- Saved bindings from the old format must be rebound, as the PR documents. Keep that migration warning and complete the stated Windows runtime follow-up before treating its layout-switch behavior as validated.
Verification limits: GitHub-only source and diff inspection. No builds, unit tests, X11/XWayland/Wayland sessions, macOS or Windows keyboard tests executed. The reported macOS/Linux checks and Xvfb exercises were not independently reproduced; Windows runtime behavior remains unverified. COMMENT only, not approval.
(Written by review (OpenAI))

Completes quest/m1/hotkeys-keypad.md, re-planned in moq-dev/studio#68: a hotkey is the physical key the operator pressed, on every platform.
Changes
Bindingis now winit'sPhysicalKey, the modifiers, and what the layout printed on the key when it was bound (key_without_modifiers). The window's winit event handler hears each key before egui (hotkeys::Keyboard), so keypad keys stay apart from the main row and a key egui cannot name, or winit leavesUnidentified, still binds. This replaces the keypad twin tracking (hotkeys/keypad.rs, deleted).hotkeys/x11.rs): keycode = winit scancode + 8, for named andUnidentifiedkeys alike, with every NumLock/CapsLock mix, and XKB detectable auto-repeat so a held key fires once. global-hotkey is no longer built on Linux. The layout lookup, the "release would hit another key" check, and the restart note are gone.hotkeys/native.rs), with winit'sKeyCodemapped to global-hotkey'sCode, soNumpad*register as keypad keys. A key winit leavesUnidentifiedis refused, saying global-hotkey cannot name it.hotkeys/layout.rs). A task reads that layout four times a second, since Windows tells no other app when it changes, and wakes the window, whoselogicregisters every binding again through the new layout; this also runs while the window is hidden. Unregistering is by id, so nothing strands.KP_*keysyms for keypad keys, and a non-ASCII character by its Unicode keysym (U00F6for ö). Shortcut ids name the physical key (scene/ctrl+Digit1,scene/Numpad1).README.md's Hotkeys section drops the keypad refusal, the X11 letter refusal, the restart note, and the layout read at start or bind; it states the Windows keypad limits below.Choices made without asking
RegisterHotKeymatches virtual keys, and keypad Enter and Enter are bothVK_RETURN, so the system cannot tell them apart; a binding on Enter fires for both, and keypad keys fire only with NumLock on (NumLock off turns keypad 1 intoVK_END). Telling them apart needs a low-level keyboard hook (WH_KEYBOARD_LL) in place ofRegisterHotKey, which Windows silently removes from a slow process and which anti-cheat software watches for, so I keptRegisterHotKeyand documented the limit.kio::clock::interval, asautosave.rspolls the scene file: no event reports another window's layout change.Public API and wire impact
None outside the binary. The settings key
hotkeyschanges format (breaking, see above); the portal shortcut ids for scenes change, so the desktop asks for scene shortcuts again once.Validation
just ciat the merged head 37ac09f (265 tests passed).cargo clippy -p moq-studio --all-targets -D warnings;cargo nextest run -p moq-studio hotkeys.XF86MailForward(evdev 233, which winit leavesUnidentified) to Save clip, and Ctrl+C to recording, with no refusal. Pressing each fired its own action in the status bar (cut to Main,took Main, the Replay and Save clip errors,recording into ...); keypad 1 fired with NumLock on too, and aftersetxkbmap usthe key that typed ö still fired Replay. XWayland was not exercised: the GNOME session on that host is locked, so no input reaches its X clients.cargo checkof the whole crate forx86_64-pc-windows-msvcfails in C build scripts (tract-linalg) without an MSVC toolchain, sohotkeys/native.rsandhotkeys/layout.rswere compiled and clippy-checked forx86_64-pc-windows-msvcin a scratch crate with the same dependencies. The layout follow, the keypad registrations, and the keypad Enter refusal have not run on Windows.Follow-ups
cargo build -p moq-studio(andcargo checkof the bin alone) fails onmaintoo:health.rsawaitsPrefixConsumer::next, which moq-stats builds only with itsasyncfeature, enabled today only by the moq-relay dev-dependency. moq-studio's ownmoq-statsdependency should enableasync. Workspace and--all-targetsbuilds pass, so CI does not see it.Review
Codex (gpt-6.1-sol, medium) via
quest review --base origin/main, round 1 on head 37ac09f: no findings.(Written by Claude Opus 5.5)
🤖 Generated with Claude Code