# How Keyboard Shortcuts Are Configured and Matched Against User Input in OpenScreen

> Discover how OpenScreen configures keyboard shortcuts and matches them against user input. Explore its type-safe system for efficient key binding and conflict validation.

- Repository: [Sid/openscreen](https://github.com/siddharthvaddem/openscreen)
- Tags: internals
- Published: 2026-04-03

---

**OpenScreen implements a type-safe shortcut system in [`src/lib/shortcuts.ts`](https://github.com/siddharthvaddem/openscreen/blob/main/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`](https://github.com/siddharthvaddem/openscreen/blob/main/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`](https://github.com/siddharthvaddem/openscreen/blob/main/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`](https://github.com/siddharthvaddem/openscreen/blob/main/src/lib/shortcuts.ts#L29-L52) and [`src/lib/shortcuts.ts#L85-L103`](https://github.com/siddharthvaddem/openscreen/blob/main/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:

1. The pressed `key` matches the binding’s `key` property (case-insensitive).
2. The primary modifier matches the binding’s `ctrl` flag—using `Meta` on macOS and `Ctrl` on Windows/Linux.
3. The `Shift` and `Alt` modifiers 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`](https://github.com/siddharthvaddem/openscreen/blob/main/src/lib/shortcuts.ts#L105-L118)

```tsx
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`](https://github.com/siddharthvaddem/openscreen/blob/main/src/lib/shortcuts.ts#L67-L82)

```ts
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`](https://github.com/siddharthvaddem/openscreen/blob/main/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`](https://github.com/siddharthvaddem/openscreen/blob/main/src/lib/shortcuts.ts), with separate schemas for mutable (`DEFAULT_SHORTCUTS`) and fixed (`FIXED_SHORTCUTS`) bindings.
- **Platform-Aware Matching**: The `matchesShortcut` function normalizes platform differences by detecting macOS via the `isMac` parameter to correctly validate `Meta` versus `Ctrl` modifiers.
- **Conflict Validation**: The `findConflict` utility prevents users from remapping fixed system shortcuts or creating duplicate bindings, distinguishing between fixed and configurable collisions.
- **Graceful Upgrades**: `mergeWithDefaults` ensures 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`](https://github.com/siddharthvaddem/openscreen/blob/main/src/lib/shortcuts.ts), localized UI labels are maintained in JSON files such as [`src/i18n/locales/en/shortcuts.json`](https://github.com/siddharthvaddem/openscreen/blob/main/src/i18n/locales/en/shortcuts.json), [`src/i18n/locales/zh-CN/shortcuts.json`](https://github.com/siddharthvaddem/openscreen/blob/main/src/i18n/locales/zh-CN/shortcuts.json), and [`src/i18n/locales/es/shortcuts.json`](https://github.com/siddharthvaddem/openscreen/blob/main/src/i18n/locales/es/shortcuts.json). This separation keeps the matching logic platform-agnostic while supporting multilingual interfaces.