How Keyboard Shortcuts Are Managed in OpenSuperWhisper: Inside the ShortcutManager Singleton
OpenSuperWhisper centralizes all keyboard shortcut handling in a ShortcutManager singleton that orchestrates three mutually exclusive trigger modes—standard hotkeys, modifier-only keys, and mouse buttons—using the KeyboardShortcuts Swift package alongside custom macOS event monitors.
OpenSuperWhisper, the open-source macOS transcription app developed by Starmel, implements a sophisticated keyboard shortcut system that allows users to trigger voice recording from anywhere in the system. The architecture revolves around a single coordinator that manages multiple input modalities while ensuring only one trigger remains active at any given time. Understanding how these keyboard shortcuts are managed reveals a clean Swift implementation that balances flexibility with system-level event handling.
The ShortcutManager Singleton Architecture
At the core of the system lies ShortcutManager, a singleton class defined in OpenSuperWhisper/ShortcutManager.swift that acts as the central dispatcher for all recording triggers. Rather than scattering hotkey logic across view controllers, the manager encapsulates registration, monitoring, and state management in one location.
The manager leverages the KeyboardShortcuts Swift package by Sindre Sorhus to handle standard keyboard combinations. During application launch, it registers the default "toggle-record" hotkey (⌥ , Option plus backtick) and an escape key listener using KeyboardShortcuts.enable(.toggleRecord)`. This library abstracts away the complexity of macOS global hotkey registration while providing a native recorder UI for user customization.
Three Mutually Exclusive Trigger Modes
The ShortcutManager supports three distinct input methods, but only one can be active simultaneously. The selection depends on user preferences stored in AppPreferences, a persisted configuration layer located in OpenSuperWhisper/Utils/AppPreferences.swift.
Standard Keyboard Shortcuts via KeyboardShortcuts
By default, the system uses a conventional keyboard shortcut managed by the KeyboardShortcuts package. When this mode is active, the manager calls KeyboardShortcuts.enable(.toggleRecord) to register a global hotkey that works across all macOS applications. The default binding uses KeyboardShortcuts.Name("toggleRecord", default: .init(.backtick, modifiers: .option)), though users can customize this through the recorder control.
Modifier-Only Hotkeys with ModifierKeyMonitor
When users enable the modifier-only mode by setting AppPreferences.shared.modifierOnlyHotkey to a value like ModifierKey.leftOption.rawValue, the manager initializes ModifierKeyMonitor from OpenSuperWhisper/ModifierKeyMonitor.swift. This class creates a global event tap that watches for key-down and key-up events on the specified modifier key (Command, Option, Control, or Shift) without requiring an additional character key. The monitor forwards these events directly to ShortcutManager to trigger recording state changes.
Mouse Button Triggers via MouseButtonMonitor
For users preferring mouse input, setting AppPreferences.shared.mouseButtonHotkey to values like MouseButton.button4.rawValue activates MouseButtonMonitor in OpenSuperWhisper/MouseButtonMonitor.swift. This monitor establishes a global event tap that detects presses on extra mouse buttons (Middle, Button 4, or Button 5) and translates them into recording commands. This implementation allows hardware buttons on advanced mice to control transcription without keyboard interaction.
Hold-to-Record Implementation
Beyond simple toggling, ShortcutManager implements a hold-to-record mode controlled by the AppPreferences.shared.holdToRecord boolean. When enabled, the manager uses a DispatchWorkItem to detect sustained presses exceeding 0.3 seconds (the holdThreshold).
Upon detecting a key-down or button-down event in handleKeyDown(), the manager immediately begins recording but schedules a delayed work item. If the user releases the input before the threshold elapses, the recording stops immediately. If the threshold passes, the work item sets holdMode = true, and the recording continues until the corresponding key-up event occurs. This logic allows the same physical input to function as either a toggle or a push-to-talk mechanism depending on user preference.
Dynamic Configuration and NotificationCenter
The system remains responsive to preference changes through NotificationCenter. When users modify hotkey settings via the UI, the application posts a .hotkeySettingsChanged notification. The ShortcutManager observes this notification and invokes setupRecordingTrigger(), which performs a complete teardown of existing monitors before reinitializing the appropriate trigger type.
This ensures that switching from a keyboard shortcut to a mouse button trigger (or vice versa) happens atomically without leaving orphaned event taps or conflicting registrations. The manager guarantees system stability by validating that only one monitoring mechanism remains active at any given time.
Code Implementation Examples
The following examples demonstrate how to interact with the keyboard shortcut system programmatically:
Registering a custom hotkey using the KeyboardShortcuts API:
import KeyboardShortcuts
extension KeyboardShortcuts.Name {
static let toggleRecord = Self("toggleRecord", default: .init(.backtick,
modifiers: .option))
}
// In your Settings view
KeyboardShortcuts.Recorder(for: .toggleRecord)
Switching trigger modes via AppPreferences:
// Enable Option key-only hotkey
AppPreferences.shared.modifierOnlyHotkey = ModifierKey.leftOption.rawValue
// Or enable mouse button 4 (Back button)
AppPreferences.shared.mouseButtonHotkey = MouseButton.button4.rawValue
// Trigger reconfiguration
NotificationCenter.default.post(name: .hotkeySettingsChanged, object: nil)
Handling key-down events with hold-to-record logic:
private func handleKeyDown() {
holdWorkItem?.cancel()
holdMode = false
let holdEnabled = AppPreferences.shared.holdToRecord
Task { @MainActor in
if activeVm == nil {
let vm = IndicatorWindowManager.shared.show(nearPoint: cursorPosition)
vm.startRecording()
activeVm = vm
} else if !holdMode {
IndicatorWindowManager.shared.stopRecording()
activeVm = nil
}
}
if holdEnabled {
let workItem = DispatchWorkItem { [weak self] in self?.holdMode = true }
holdWorkItem = workItem
DispatchQueue.main.asyncAfter(deadline: .now() + holdThreshold,
execute: workItem)
}
}
Summary
- Centralized Control: All keyboard shortcut logic resides in the
ShortcutManagersingleton located inOpenSuperWhisper/ShortcutManager.swift. - Three Trigger Modes: The system supports standard hotkeys (KeyboardShortcuts package), modifier-only keys (ModifierKeyMonitor), and mouse buttons (MouseButtonMonitor).
- Preference-Driven:
AppPreferencesstores user selections formodifierOnlyHotkey,mouseButtonHotkey, andholdToRecord, persisting across app launches. - Dynamic Reconfiguration: The
.hotkeySettingsChangednotification triggers atomic teardown and reinitialization of monitors when settings change. - Hold-to-Record: A 0.3-second threshold using
DispatchWorkItemdistinguishes between toggle and push-to-talk behaviors. - Global Accessibility: All monitors use macOS global event taps, allowing recording initiation from any application context.
Frequently Asked Questions
What is the default keyboard shortcut in OpenSuperWhisper?
The default keyboard shortcut is Option + Backtick (⌥ ). This is registered at launch via the KeyboardShortcuts package using KeyboardShortcuts.enable(.toggleRecord)with a default value of.init(.backtick, modifiers: .option)in thetoggleRecord` name extension.
How does the modifier-only hotkey mode work?
When enabled through AppPreferences.shared.modifierOnlyHotkey, the ModifierKeyMonitor class creates a global event tap that monitors only the specified modifier key (such as Left Option or Right Command) for press and release events. This allows users to trigger recording by pressing and holding a modifier key alone, without combining it with a character key.
Can I use a mouse button instead of a keyboard shortcut?
Yes. By setting AppPreferences.shared.mouseButtonHotkey to values like MouseButton.button4 or MouseButton.middle, you activate MouseButtonMonitor, which watches for presses on extra mouse buttons. This is particularly useful for mice with dedicated "back" or "forward" buttons that can be repurposed for voice recording control.
What happens when I change hotkey settings while the app is running?
When preferences change, the app posts a .hotkeySettingsChanged notification. The ShortcutManager receives this notification and calls setupRecordingTrigger(), which tears down any active monitors (keyboard, modifier, or mouse) and reinitializes the appropriate trigger based on the new preferences. This ensures clean transitions between input methods without system conflicts or duplicate registrations.
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 →