How Keyboard Shortcuts Are Configured and Matched Against User Input in OpenScreen
OpenScreen implements a type-safe shortcut system in src/lib/shortcuts.ts that maps discrete actions to key bindings, validates conflicts against fixed and mutable shortcuts, and matches runtime KeyboardEvent objects using platform-aware modifier detection.
OpenScreen treats keyboard shortcuts as strongly typed configuration objects that bridge user preferences with runtime input handling. The entire workflow—from defining default bindings to detecting conflicts and matching live keystrokes—lives in a single utilities file that ensures deterministic behavior across Windows, macOS, and Linux.
Defining the Shortcut Schema
The foundation of the system is a finite set of actions and their corresponding data structures declared at the top of src/lib/shortcuts.ts. The SHORTCUT_ACTIONS array enumerates every available command, while the ShortcutBinding interface defines the shape of a single mapping—specifying the key, ctrl, shift, and alt properties. These are aggregated into the ShortcutsConfig type, which represents the complete user-facing configuration object.
This strict typing guarantees that every action referenced in the UI or settings panel corresponds to a valid entry in the configuration schema. Source: src/lib/shortcuts.ts#L1-L22
Default and Fixed Shortcut Mappings
OpenScreen maintains two distinct categories of shortcuts to separate user-customizable actions from system-reserved commands.
Default mutable shortcuts (DEFAULT_SHORTCUTS) provide sensible initial bindings for every action that users can later override through the settings interface. These mappings cover common operations like play/pause or zoom controls.
Fixed shortcuts (FIXED_SHORTCUTS) represent UI-only shortcuts that cannot be remapped—such as Undo and Redo. These are used exclusively for display purposes and conflict detection, ensuring that critical system conventions remain protected. Source: src/lib/shortcuts.ts#L29-L52 and src/lib/shortcuts.ts#L85-L103
Matching Runtime Keyboard Events
When a KeyboardEvent bubbles through the application, OpenScreen evaluates it against stored configurations using the matchesShortcut function. This utility performs three precise checks:
- The pressed
keymatches the binding’skeyproperty (case-insensitive). - The primary modifier matches the binding’s
ctrlflag—usingMetaon macOS andCtrlon Windows/Linux. - The
ShiftandAltmodifiers match their respective boolean flags in the binding.
If all conditions satisfy, the function returns true, signaling that the event corresponds to the specific shortcut action. Source: src/lib/shortcuts.ts#L105-L118
import { matchesShortcut, DEFAULT_SHORTCUTS } from "@/lib/shortcuts";
function onKeyDown(e: KeyboardEvent) {
const shortcuts = DEFAULT_SHORTCUTS; // normally `mergeWithDefaults(savedConfig)`
const playBinding = shortcuts.playPause; // { key: " " }
if (matchesShortcut(e, playBinding, navigator.platform.includes("Mac"))) {
togglePlayPause();
e.preventDefault();
}
}
Conflict Detection Before Persistence
Before persisting a new key binding, OpenScreen validates it against existing mappings using findConflict. This function traverses both FIXED_SHORTCUTS and the current ShortcutsConfig to detect collisions.
It returns a conflict object specifying whether the clash is fixed (against a non-remappable system shortcut) or configurable (against another user-defined action). This prevents users from accidentally breaking essential navigation patterns or duplicating existing commands. Source: src/lib/shortcuts.ts#L67-L82
import { findConflict, DEFAULT_SHORTCUTS } from "@/lib/shortcuts";
const newBinding = { key: "z", ctrl: true };
const conflict = findConflict(newBinding, "addZoom", DEFAULT_SHORTCUTS);
if (conflict) {
if (conflict.type === "fixed") {
console.warn(`Clashes with fixed shortcut: ${conflict.label}`);
} else {
console.warn(`Clashes with action: ${conflict.action}`);
}
}
Merging User Settings with Defaults
When the application loads stored preferences, the mergeWithDefaults function overlays the user’s partial configuration onto DEFAULT_SHORTCUTS. This guarantees that any newly added actions—present in the defaults but absent from the user’s saved data—automatically receive their standard bindings without requiring manual migration.
The merge operation preserves user customizations while ensuring the configuration object always contains a complete, valid set of actions. Source: src/lib/shortcuts.ts#L40-L48
Summary
- Typed Configuration: All keyboard shortcuts in OpenScreen are defined as type-safe objects in
src/lib/shortcuts.ts, with separate schemas for mutable (DEFAULT_SHORTCUTS) and fixed (FIXED_SHORTCUTS) bindings. - Platform-Aware Matching: The
matchesShortcutfunction normalizes platform differences by detecting macOS via theisMacparameter to correctly validateMetaversusCtrlmodifiers. - Conflict Validation: The
findConflictutility prevents users from remapping fixed system shortcuts or creating duplicate bindings, distinguishing between fixed and configurable collisions. - Graceful Upgrades:
mergeWithDefaultsensures backward compatibility by filling gaps in user configurations with default values when the application updates.
Frequently Asked Questions
How does OpenScreen handle platform differences for modifier keys?
The matchesShortcut function accepts an isMac boolean parameter derived from navigator.platform. When true, it validates the Meta key against the binding’s ctrl property; otherwise, it checks the Ctrl key. This allows a single configuration schema to work across macOS, Windows, and Linux without duplicating entries.
Can users override fixed shortcuts like Undo and Redo?
No. Fixed shortcuts defined in FIXED_SHORTCUTS are immutable and used only for display and conflict detection. The findConflict function explicitly checks new bindings against this set and returns a type: "fixed" conflict if the user attempts to remap a protected shortcut.
What happens if a user’s saved shortcuts are missing new actions?
The mergeWithDefaults function overlays the persisted user configuration onto DEFAULT_SHORTCUTS. Any actions missing from the saved data automatically inherit their default bindings from the base configuration, ensuring the application always has a complete shortcut map.
Where are the human-readable labels for shortcuts stored?
While the core logic resides in src/lib/shortcuts.ts, localized UI labels are maintained in JSON files such as src/i18n/locales/en/shortcuts.json, src/i18n/locales/zh-CN/shortcuts.json, and src/i18n/locales/es/shortcuts.json. This separation keeps the matching logic platform-agnostic while supporting multilingual interfaces.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →