hammer-editor/docs/KEYBOARD-SHORTCUTS.md
Adam Brown 9cde66bef6
Fix AltGr shortcuts closing the desktop app (#859) (#907)
Windows reports AltGr as Ctrl+Alt, so typing @ on a Turkish-Q or German
QWERTZ layout matched the loose Ctrl+Q quit test and closed the app.

Window shortcut matching moves into WindowShortcuts.kt, built on the
exact-modifier matchesShortcut helper, which also tightens Ctrl+W and
Ctrl+Shift+F.

* Move save-all off Ctrl+Alt+S to Ctrl+Shift+S

Ctrl+Alt+S is itself an AltGr chord on Windows, so it fired and ate the
character on layouts that map AltGr+S, such as Polish (s with acute).
Rebound on desktop, Android, and iOS, and Android's global search now
matches its modifiers exactly like the rest.

No shortcut uses Alt now, which is what keeps AltGr keystrokes reaching
the editor.

* Keep Koin hint classes out of test detection
2026-08-16 00:00:10 -07:00

3.7 KiB

Keyboard Shortcuts

Desktop, plus the two project shortcuts on Android and iOS with a hardware keyboard. Ctrl and Cmd are interchangeable everywhere below: onKeyShortcut ( composeUi/src/commonMain/kotlin/com/darkrockstudios/apps/hammer/common/compose/ShortcutModifiers.kt) treats isCtrlPressed || isMetaPressed as a single "ctrl" modifier, so these are not macOS-specific Cmd bindings, they work with either key on every platform.

Every binding matches its modifiers exactly, and none of them uses Alt. Both rules are load bearing: Windows reports AltGr as Ctrl+Alt, so a loose or Alt based chord fires while a Turkish, German, or Polish layout types the character on that key (issue #859).

Application

These are matched in desktop/.../WindowShortcuts.kt and dispatched from each window's onKeyEvent.

Shortcut Action Window
Esc Navigate back ProjectEditorWindow.kt, ProjectSelectionWindow.kt
Ctrl+Q Quit application ProjectEditorWindow.kt, ProjectSelectionWindow.kt
Ctrl+W Close current project ProjectEditorWindow.kt
Ctrl+Shift+F Open global search ProjectEditorWindow.kt

Project (while a project is open)

These two work on all three platforms, each through the host hook that does not depend on what Compose has focused. Compose routes key events along the focus path, so a screen with nothing focused never sees them, which is why none of these are Modifier shortcuts.

Platform Hook
Desktop ProjectEditorWindow.kt window onPreviewKeyEvent
Android ProjectRootActivity.dispatchKeyEvent
iOS ShortcutHostController.keyCommands in ComposeContainer.swift

Android and iOS reach the shared action through ProjectShortcutHost, which ProjectRootScaffold binds while the project UI is composed. The application shortcuts above use the window's onKeyEvent instead and yield to a focused component that consumes the key. Modifier shortcuts (the editor ones below) only fire when focus sits inside the composable they are attached to.

F3 means F3 with nothing held, so Ctrl+F3 and Shift+F3 do not start a sync.

Shortcut Action
Ctrl+Shift+S Save all dirty buffers (scenes, notes, etc.)
F3 Start project sync (server-linked only)

Editors (scene, note, timeline event, story idea)

Shortcut Action Source
Ctrl+S Save the current item saveShortcutModifier via SceneEditorUi.kt, ViewNoteUi.kt, ViewTimeLineEventUi.kt, StoryIdeasUi.kt
Ctrl+F Open find bar findShortcutModifier via SceneEditorUi.kt, FocusModeUi.kt

Rich Text Formatting

Available anywhere MarkdownFormatBar.kt is used (scene, note, and encyclopedia editors).

Shortcut Action
Ctrl+B Toggle bold
Ctrl+I Toggle italic
Ctrl+Shift+X Toggle strikethrough