From 8d8f107a28c2b0796a283ff387a23e73138e7066 Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Fri, 6 Nov 2026 16:11:45 -0800 Subject: [PATCH 1/2] quest: hotkeys bind by physical key, folding in the X11 keycode grab Co-Authored-By: Claude Opus 5.5 --- quest/m1/README.md | 2 +- quest/m1/hotkeys-keypad.md | 37 +++++++++++++++++++++++++------------ 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/quest/m1/README.md b/quest/m1/README.md index e7365eb..ec5c697 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -24,5 +24,5 @@ than opening an m2 for them. ## Required - [Viewer-side composition](/quest/m1/compose/README.md) - sources as their own tracks plus a layout track, composed by viewers and by a server -- [Keypad keys bind as hotkeys](/quest/m1/hotkeys-keypad.md) - scene and action keys on the keypad, apart from the main row +- [Hotkeys bind by physical key](/quest/m1/hotkeys-keypad.md) - keypad keys apart from the main row, and any X11 key across layout changes - [Scene graph view](/quest/m1/scene-graph.md) - a node view of picture and audio scenes, their routing, volume, pan, and waveforms diff --git a/quest/m1/hotkeys-keypad.md b/quest/m1/hotkeys-keypad.md index cac820c..361a6ab 100644 --- a/quest/m1/hotkeys-keypad.md +++ b/quest/m1/hotkeys-keypad.md @@ -1,20 +1,33 @@ -# [S] Keypad keys bind as hotkeys +# [M] Hotkeys bind by physical key ## Goal -The operator binds keypad keys (`Numpad0` to `Numpad9`, the keypad -operators, and keypad Enter) to studio actions, and they fire system-wide on -macOS, Windows, X11, and the Wayland portal, apart from the main-row keys -with the same symbol. Streamers often put scenes on the keypad. +A hotkey is the physical key the operator pressed, on every platform: +- Keypad keys (`Numpad0` to `Numpad9`, the keypad operators, and keypad + Enter) bind apart from the main-row keys with the same symbol, and fire + system-wide on macOS, Windows, X11, and the Wayland portal. Streamers often + put scenes on the keypad. +- On X11, any key binds, including one that types a letter outside A to Z + (such as ö on a German layout), and a keyboard layout change neither strands + a held grab nor needs a restart. ## Plan From [moq-dev/studio#61](https://github.com/moq-dev/studio/pull/61), which -refuses keypad keys rather than binding them; picked 2026-11-06 (maintainer, -/quest-plan) as its own quest so #61 lands as reviewed. +refuses keypad keys and non-A-to-Z X11 letters, and asks for a restart after +an X11 layout change. Picked 2026-11-06 (maintainer, /quest-plan): keypad keys +as their own quest so #61 landed as reviewed, and the X11 keycode grab folded +in, since both rework the same grab path. -- Carry winit's physical `KeyCode` (or the key's keypad location) through - `Binding`, so `Numpad1` and `Digit1` stay distinct. -- Register global-hotkey's `Numpad*` codes on macOS, Windows, and X11, and - ask the GlobalShortcuts portal for `KP_*` keysyms on Wayland. -- `README.md` drops the note that keypad keys are refused. +- Carry winit's physical `KeyCode` through `Binding`, so `Numpad1` and + `Digit1` stay distinct. This replaces the keypad twin tracking in + `rs/moq-studio/src/hotkeys/keypad.rs`. +- On X11, the studio grabs by keycode itself (XGrabKey through x11rb, which + `layout.rs` already reads the keyboard mapping with) instead of through + global-hotkey, which grabs by keysym and looks it up again in the current + layout on release (see `Layout::releases` in `layout.rs`). Releasing a + grab then needs no lookup, so the restart note goes. +- Register global-hotkey's `Numpad*` codes on macOS and Windows, and ask the + GlobalShortcuts portal for `KP_*` keysyms on Wayland. +- `README.md`'s Hotkeys section drops the keypad refusal, the X11 letter + refusal, and the restart note. From 4d8e01ee9df124977aecbd7edb5eb740751d9c3d Mon Sep 17 00:00:00 2001 From: Luke Curley Date: Fri, 6 Nov 2026 17:03:04 -0800 Subject: [PATCH 2/2] quest: hotkeys keep Windows bindings across layout changes, and bind unnamed X11 keys Folds in CodeRabbit's two findings on the plan: Windows registers by virtual key, so the studio registers again when the layout changes; and Binding carries winit's PhysicalKey, so a key winit leaves Unidentified keeps its native code for the X11 keycode grab. Co-Authored-By: Claude Opus 5.5 --- quest/m1/README.md | 2 +- quest/m1/hotkeys-keypad.md | 36 +++++++++++++++++++++++++++--------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/quest/m1/README.md b/quest/m1/README.md index ec5c697..c974e45 100644 --- a/quest/m1/README.md +++ b/quest/m1/README.md @@ -24,5 +24,5 @@ than opening an m2 for them. ## Required - [Viewer-side composition](/quest/m1/compose/README.md) - sources as their own tracks plus a layout track, composed by viewers and by a server -- [Hotkeys bind by physical key](/quest/m1/hotkeys-keypad.md) - keypad keys apart from the main row, and any X11 key across layout changes +- [Hotkeys bind by physical key](/quest/m1/hotkeys-keypad.md) - keypad keys apart from the main row, any X11 key, and every binding across layout changes - [Scene graph view](/quest/m1/scene-graph.md) - a node view of picture and audio scenes, their routing, volume, pan, and waveforms diff --git a/quest/m1/hotkeys-keypad.md b/quest/m1/hotkeys-keypad.md index 361a6ab..855a9ed 100644 --- a/quest/m1/hotkeys-keypad.md +++ b/quest/m1/hotkeys-keypad.md @@ -8,26 +8,44 @@ A hotkey is the physical key the operator pressed, on every platform: system-wide on macOS, Windows, X11, and the Wayland portal. Streamers often put scenes on the keypad. - On X11, any key binds, including one that types a letter outside A to Z - (such as ö on a German layout), and a keyboard layout change neither strands - a held grab nor needs a restart. + (such as ö on a German layout) and one winit cannot name. +- A keyboard layout change leaves every binding on its key without a restart: + on X11 no held grab strands, and on Windows no binding moves to the key the + new layout gives its virtual key. ## Plan From [moq-dev/studio#61](https://github.com/moq-dev/studio/pull/61), which -refuses keypad keys and non-A-to-Z X11 letters, and asks for a restart after +refuses keypad keys and non-A-to-Z X11 letters, registers through the layout +in use when the studio starts or a key is bound, and asks for a restart after an X11 layout change. Picked 2026-11-06 (maintainer, /quest-plan): keypad keys as their own quest so #61 landed as reviewed, and the X11 keycode grab folded in, since both rework the same grab path. -- Carry winit's physical `KeyCode` through `Binding`, so `Numpad1` and - `Digit1` stay distinct. This replaces the keypad twin tracking in +- Carry winit's `PhysicalKey` through `Binding`, taken from the window's + winit key event rather than egui's, so `Numpad1` and `Digit1` stay distinct + and a key winit leaves `Unidentified` keeps its native code. egui-winit + drops a key it can name neither logically nor physically, so the Hotkeys + panel cannot take it from egui. This replaces the keypad twin tracking in `rs/moq-studio/src/hotkeys/keypad.rs`. - On X11, the studio grabs by keycode itself (XGrabKey through x11rb, which `layout.rs` already reads the keyboard mapping with) instead of through global-hotkey, which grabs by keysym and looks it up again in the current - layout on release (see `Layout::releases` in `layout.rs`). Releasing a - grab then needs no lookup, so the restart note goes. + layout on release (see `Layout::releases` in `layout.rs`). The keycode is + winit's Linux scancode plus 8 (`PhysicalKeyExtScancode::to_scancode`), for + a named key and an `Unidentified` one alike, so releasing a grab needs no + lookup and the restart note goes. +- On Windows, `RegisterHotKey` matches the virtual key the active layout gives + the pressed key, so `layout.rs` maps each binding's scancode to a virtual key + through that layout. The studio registers every binding again when that + layout changes, not only when a binding does, as `hear` does now. + Unregistering is by id, so nothing can strand. Recommended: read the + foreground window's layout, which the system translates the key with, since + a game usually has focus. - Register global-hotkey's `Numpad*` codes on macOS and Windows, and ask the - GlobalShortcuts portal for `KP_*` keysyms on Wayland. + GlobalShortcuts portal for `KP_*` keysyms on Wayland. macOS registers by key + position, so a layout change moves nothing there. A key winit leaves + `Unidentified` is refused outside X11, saying global-hotkey cannot name it. - `README.md`'s Hotkeys section drops the keypad refusal, the X11 letter - refusal, and the restart note. + refusal, the restart note, and the layout read when the studio starts or a + key is bound.