How Hold-to-Record Mode Works with Modifier Keys in OpenSuperWhisper
OpenSuperWhisper enables push-to-talk recording by holding a single modifier key (⌘, ⌥, ⇧, ⌃, or Fn), using a low-level event tap to start transcription immediately on key-down and stop on key-up after a 0.3-second threshold.
OpenSuperWhisper is an open-source macOS dictation application that supports hold-to-record functionality using single modifier keys without complex shortcuts. The implementation relies on a preference-driven architecture that coordinates between user settings, event monitoring, and recording state management. Understanding how hold-to-record mode works with modifier keys requires examining the flow from AppPreferences through ShortcutManager to the low-level ModifierKeyMonitor.
Architecture Overview
The hold-to-record system combines preference storage, trigger selection, and event monitoring to provide seamless voice transcription control.
Preference Configuration
User settings drive the hold-to-record behavior through two key properties in AppPreferences.swift:
AppPreferences.shared.holdToRecord: A boolean toggle that enables the feature (defaults totrue)AppPreferences.shared.modifierOnlyHotkey: Stores the selected modifier key as an enum value (.noneindicates standard shortcut mode should be used instead)
When modifierOnlyHotkey is set to a specific key like .rightOption or .leftCommand, the system switches from standard keyboard shortcuts to modifier-only monitoring.
Trigger Selection Logic
The ShortcutManager.setupRecordingTrigger() method in ShortcutManager.swift determines which input method to activate based on preference hierarchy:
- Mouse button hotkey takes precedence if configured
- Modifier-only mode activates if
modifierOnlyHotkey≠.none, which starts aModifierKeyMonitorinstance for the selected key and disables the normal keyboard shortcut - Standard shortcut operates if neither specialized mode is active
This priority system ensures only one trigger mechanism is active at any time to prevent conflicts.
Low-Level Event Monitoring
When modifier-only mode is selected, ModifierKeyMonitor (implemented in ModifierKeyMonitor.swift) creates a Core Graphics event tap that monitors system-wide flagsChanged events. The monitor:
- Filters for events matching the chosen modifier key's
keyCode - Invokes
onKeyDownwhen the key is pressed - Invokes
onKeyUpwhen the key is released
This low-level access allows the app to detect modifier key states even when OpenSuperWhisper is not the active application.
Recording State Management
Both the standard shortcut and modifier-key monitor forward events to the same callbacks in ShortcutManager:
On key-down (handleKeyDown):
- Recording starts immediately
- A
DispatchWorkItemis scheduled to execute after theholdThreshold(0.3 seconds) - When the work item fires, it sets an internal
holdModeflag totrue
On key-up (handleKeyUp):
- The pending
DispatchWorkItemis cancelled - If
holdModeistrue(meaning the key was held longer than 0.3 seconds), the recording stops andholdModeresets tofalse
This timing mechanism distinguishes between a quick tap (which might trigger other actions) and an intentional hold-to-record gesture.
Implementation Examples
Configure the hold-to-record preference and select a modifier key in the settings UI:
// Settings.swift - Toggle for enabling the feature
Toggle("Hold-to-record", isOn: $viewModel.holdToRecord)
// Stores to AppPreferences.shared.holdToRecord
// Picker for selecting a single modifier key
Picker("Modifier", selection: $viewModel.modifierOnlyHotkey) {
ForEach(ModifierKey.allCases.filter { $0 != .none }) { key in
Text(key.displayName).tag(key)
}
}
// Stores to AppPreferences.shared.modifierOnlyHotkey
Programmatically configure the system to use Right Option key with hold-to-record:
// Configure preferences directly
AppPreferences.shared.modifierOnlyHotkey = ModifierKey.rightOption.rawValue
AppPreferences.shared.holdToRecord = true
// ShortcutManager automatically wires the monitor
// No additional code required - the shared instance listens for key-down/up
Alternative configuration using a mouse button instead of a modifier key:
// Enable mouse-button mode (takes precedence over modifier keys)
AppPreferences.shared.mouseButtonHotkey = MouseButton.right.rawValue
// Same hold-to-record logic applies via handleKeyDown/handleKeyUp
Key Source Files
| File | Role |
|---|---|
OpenSuperWhisper/ShortcutManager.swift |
Central coordinator that decides trigger type, manages the 0.3-second hold threshold via DispatchWorkItem, and interfaces with the recording engine |
OpenSuperWhisper/Utils/AppPreferences.swift |
Persists user settings including holdToRecord boolean and modifierOnlyHotkey enum value |
OpenSuperWhisper/ModifierKeyMonitor.swift |
Implements low-level event tap for flagsChanged events and translates physical key presses into onKeyDown/onKeyUp callbacks |
OpenSuperWhisper/Settings.swift |
SwiftUI interface that exposes the hold-to-record toggle and modifier key picker to users |
Summary
- Preference-driven activation: The feature is controlled by
AppPreferences.shared.holdToRecordandmodifierOnlyHotkey, allowing users to choose between standard shortcuts and single-key modifiers. - Hierarchical trigger selection:
ShortcutManager.setupRecordingTrigger()prioritizes mouse buttons, then modifier keys, then standard shortcuts to prevent input conflicts. - Low-level event access:
ModifierKeyMonitoruses a Core Graphics event tap to detect modifier key states system-wide throughflagsChangedevents. - Timed state transitions: A 0.3-second
DispatchWorkItemdistinguishes between taps and holds, ensuring recording only commits when the user intentionally holds the key.
Frequently Asked Questions
What modifier keys can be used for hold-to-record?
OpenSuperWhisper supports the standard macOS modifier keys: Command (⌘), Option (⌥), Shift (⇧), Control (⌃), and Function (Fn). Each key can be configured independently for left or right variants (e.g., Left Command vs. Right Command) through the ModifierKey enum in AppPreferences.swift.
How does the app distinguish between a quick tap and a hold?
The system uses a 0.3-second threshold managed by ShortcutManager. When a key is pressed, a DispatchWorkItem is scheduled to run after 0.3 seconds and set holdMode = true. If the key is released before this timer fires, the work item is cancelled and holdMode remains false, preventing the recording from stopping prematurely. Only keys held longer than this threshold trigger the hold-to-record behavior.
Can I use a mouse button instead of a keyboard modifier?
Yes. ShortcutManager.setupRecordingTrigger() checks AppPreferences.shared.mouseButtonHotkey before examining modifierOnlyHotkey. If a mouse button is configured (such as MouseButton.right), the system enables mouse-button mode and uses the same handleKeyDown/handleKeyUp callbacks, applying identical hold-to-record timing logic.
Where are the hold-to-record preferences stored?
Preferences are persisted in AppPreferences.swift using a singleton pattern (AppPreferences.shared). The holdToRecord boolean and modifierOnlyHotkey string are stored in the user's standard preferences domain, allowing settings to persist across application launches and sync with the Settings UI defined in Settings.swift.
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 →