Skip to content

Keyboard and gestures

Status: PROPOSED

The complete planned key set comes from docs/ui/ui-plan.md:292–304. Only P, Ctrl+L, Left, and Right are implemented today. Every other binding and the focus-scoped dispatcher are PROPOSED.

Focus-scoping rule

PROPOSED — shortcuts dispatch by focused surface before they dispatch by key. Bare digit and letter keys never fire while a text or numeric input has focus. Space is playback only when the Simulate viewport has focus.

flowchart TD
  K["KeyDown"] --> F{"Focused control?"}
  F -->|Text / numeric input| I["Preserve typing and editing"]
  F -->|Viewport / chrome| C{"Context"}
  C -->|Paint mode| P["Paint bindings"]
  C -->|Simulate viewport| S["Playback + viewport bindings"]
  C -->|Other stage/chrome| G["Global modified commands"]

This replaces the current flat dispatcher. HOW IT ISShellKeybindings.Handle currently compares exactly four keys with no focus argument (src/Nps.Shell/Controls/ShellKeybindings.cs:73–113).

Keybindings

Key Planned action Scope Honesty
P Play / pause Simulate/playback context; Slicer without a playhead reports unavailable today HOW IT IS dispatcher key (src/Nps.Shell/Controls/ShellKeybindings.cs:84–89); current Slicer stub at src/SlicerApp/MainWindow.axaml.cs:171–185
Ctrl+L Toggle inspector Window HOW IT IS (src/Nps.Shell/Controls/ShellKeybindings.cs:91–96)
Left Step one move backward Simulate/playback context HOW IT IS dispatcher key (src/Nps.Shell/Controls/ShellKeybindings.cs:105–110); Slicer reports unavailable today
Right Step one move forward Simulate/playback context HOW IT IS dispatcher key (src/Nps.Shell/Controls/ShellKeybindings.cs:98–103); Slicer reports unavailable today
Ctrl+1 Switch to Prepare Window PROPOSED
Ctrl+2 Switch to Preview Window PROPOSED
Ctrl+3 Switch to Simulate Window PROPOSED
Ctrl+O Open model Window PROPOSED
Ctrl+Shift+O Open G-code Window PROPOSED
Ctrl+E Open Export Window; disabled with reason when no generated path PROPOSED
Ctrl+Enter Slice / Re-slice Window; disabled with reason when no model PROPOSED
[ Layer down Preview / Simulate viewport PROPOSED
] Layer up Preview / Simulate viewport PROPOSED
T Toggle travels Viewport, not while typing PROPOSED binding over an existing display toggle
X Toggle extrusions Viewport, not while typing PROPOSED binding over an existing display toggle
G Toggle Ghost Compare Preview / Simulate viewport, not while typing PROPOSED
B Enter / exit region paint mode Prepare viewport, not while typing PROPOSED
F Zoom to Fit Viewport, not while typing PROPOSED binding over an existing toolbar action
0 Reset camera Viewport, not while typing PROPOSED binding over an existing toolbar action
? Open keybinding cheat sheet Window when not editing text/numeric input PROPOSED
Esc Exit paint, close overlay/dialog, or dismiss banner according to active context Contextual; innermost transient surface first PROPOSED
Space Play / pause Only when the Simulate viewport is focused PROPOSED

Note

P remains the current playback key. Space is not a second global binding: it is restricted to the focused Simulate viewport so buttons, text inputs, and other stages keep normal Space behavior.

Existing toolbar actions, planned keys

HOW IT IS — Reset, Isometric, Front, Top, Right, Zoom to Fit, Travels, Extrusions, Layer Up, and Layer Down already exist as the ten controls in ViewportToolbar (src/Nps.Shell/Controls/ViewportToolbar.cs:29–38,53–67). The F, 0, T, X, [, and ] keyboard routes are PROPOSED; they reuse the same actions rather than introducing different behavior.

The existing camera presets are Reset, Isometric, Front, Top, and Right (src/Nps.Shell/ViewportController.cs:79–89). No XYZ snap hotkeys are promised.

Viewport gestures

Gesture Action Scope Honesty
Left-button drag Orbit camera Viewport, outside paint mode HOW IT IS — current app handler updates rotation and calls SetCamera (src/SlicerApp/MainWindow.axaml.cs:819–842)
Other-button drag Pan camera Viewport, outside paint mode HOW IT IS — same handler updates pan (src/SlicerApp/MainWindow.axaml.cs:833–842)
Mouse wheel Zoom at cursor Viewport, outside paint mode PROPOSED — there is no wheel handler today
Left-button drag Paint faces into active region Viewport while paint mode is active PROPOSED
Shift + left-button drag Erase faces from active region Viewport while paint mode is active PROPOSED
Esc Leave paint mode Paint context PROPOSED
Click finding marker Focus the finding, layer, and move Preview / Simulate PROPOSED marker interaction over existing finding focus
Drag layer-band thumb Change minimum or maximum visible layer Preview / Simulate left sidebar PROPOSED
Drag layer band Move the visible min–max window Preview / Simulate left sidebar PROPOSED
Press / drag playback scrubber Pause while scrubbing and preview target move Simulate HOW IT IS (src/Nps.Shell/Controls/PlaybackPanel.axaml.cs:326–390,454–484)
Release playback scrubber Commit move; resume only if previously playing Simulate HOW IT IS app path (src/SimulatorApp/MainWindow.axaml.cs:868–915)

Pointer events already travel from the shared shell to each app (src/Nps.Shell/Controls/MainWindowShell.axaml.cs:35–37,269–290). Wheel zoom and paint dispatch are PROPOSED additions to that route.

Cheat sheet

PROPOSED? opens an overlay containing the same table as this page, grouped by Global, Stage, Viewport, Paint, and Playback. It closes with Esc and does not change stage or engine state.

The overlay must derive from the same binding definitions used by dispatch; it must not advertise shortcuts that do not exist. In particular, the activity bar does not gain undocumented single-letter overlay keys.

Conflict rules

PROPOSED — dispatch follows these priorities:

  1. Active modal/dialog handles its own commands.
  2. Paint mode handles paint gestures and Esc.
  3. A focused text/numeric control keeps bare letters and digits.
  4. The focused Simulate viewport may handle Space and playback keys.
  5. Stage/viewport shortcuts run only in their declared scope.
  6. Modified global commands run once and mark the event handled.
  7. An unmatched key remains available to Avalonia or the focused control.

A key never both types into a field and triggers an action.

See also