### Swift Shortcut Recording and Global Hotkey Setup Source: https://github.com/kentzo/shortcutrecorder/blob/master/README.md Example demonstrating how to set up a shortcut recorder and register a global hotkey action in Swift. Requires importing the ShortcutRecorder framework. ```swift import ShortcutRecorder let defaults = NSUserDefaultsController.shared let keyPath = "values.shortcut" let options = [NSBindingOption.valueTransformerName: .keyedUnarchiveFromDataTransformerName] let beepAction = ShortcutAction(keyPath: keyPath, of: defaults) { _ in NSSound.beep() return true } GlobalShortcutMonitor.shared.addAction(beepAction, forKeyEvent: .down) let recorder = RecorderControl() recorder.bind(.value, to: defaults, withKeyPath: keyPath, options: options) recorder.objectValue = Shortcut(keyEquivalent: "⇧⌘A") ``` -------------------------------- ### Objective-C Shortcut Recording and Global Hotkey Setup Source: https://github.com/kentzo/shortcutrecorder/blob/master/README.md Example demonstrating how to set up a shortcut recorder and register a global hotkey action in Objective-C. Requires importing the ShortcutRecorder framework. ```objectivec #import NSUserDefaultsController *defaults = NSUserDefaultsController.sharedUserDefaultsController; NSString *keyPath = @"values.shortcut"; NSDictionary *options = @{NSValueTransformerNameBindingOption: NSKeyedUnarchiveFromDataTransformerName}; SRShortcutAction *beepAction = [SRShortcutAction shortcutActionWithKeyPath:keyPath ofObject:defaults actionHandler:^BOOL(SRShortcutAction *anAction) { NSBeep(); return YES; }]; [[SRGlobalShortcutMonitor sharedMonitor] addAction:beepAction forKeyEvent:SRKeyEventTypeDown]; SRRecorderControl *recorder = [SRRecorderControl new]; [recorder bind:NSValueBinding toObject:defaults withKeyPath:keyPath options:options]; recorder.objectValue = [SRShortcut shortcutWithKeyEquivalent:@"⇧⌘A"]; ``` -------------------------------- ### Implement ShortcutController in Swift Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Demonstrates programmatic creation of a ShortcutController, binding to model objects, and accessing selection properties. ```swift import ShortcutRecorder // Create controller programmatically let controller = ShortcutController() controller.identifier = "myShortcutController" // Bind to model controller.bind(.contentObject, to: userDefaults, withKeyPath: "myShortcut", options: [ .valueTransformerName: NSValueTransformerName.keyedUnarchiveFromDataTransformerName ]) // Connect to recorder control controller.recorderControl = myRecorderControl // Set action target for automatic ShortcutAction creation controller.shortcutActionTarget = self // Access computed selection properties let keyEquivalent = controller.value(forKeyPath: "selection.keyEquivalent") as? String let modifierMask = controller.value(forKeyPath: "selection.keyEquivalentModifierMask") as? NSEventModifierFlags let literalKeyCode = controller.value(forKeyPath: "selection.literalKeyCode") as? String let symbolicKeyCode = controller.value(forKeyPath: "selection.symbolicKeyCode") as? String // Bind menu item directly to controller's selection menuItem.bind(.keyEquivalent, to: controller, withKeyPath: "selection.keyEquivalent", options: nil) menuItem.bind(.keyEquivalentModifierMask, to: controller, withKeyPath: "selection.keyEquivalentModifierMask", options: nil) ``` -------------------------------- ### Register Global Shortcuts with SRGlobalShortcutMonitor Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Demonstrates how to use SRGlobalShortcutMonitor to register system-wide hotkeys. Shows creating shortcut actions with block handlers or target/action pairs, adding actions for key down/up events, pausing/resuming monitoring, and removing actions. ```swift import ShortcutRecorder // Get the shared global monitor let globalMonitor = GlobalShortcutMonitor.shared // Create a shortcut action with block handler let beepAction = ShortcutAction(keyPath: "values.myShortcut", of: NSUserDefaultsController.shared) { action in NSSound.beep() print("Global shortcut triggered!") return true // Return true if action was handled } // Add action for key down event globalMonitor.addAction(beepAction, forKeyEvent: .down) // Or create action with target/action pattern let targetAction = ShortcutAction( shortcut: Shortcut(keyEquivalent: "⌃⌥⇧⌘F")!, target: self, action: #selector(handleShortcut(_:)), tag: 1 ) globalMonitor.addAction(targetAction, forKeyEvent: .down) // Pause/resume monitoring (useful during recording) globalMonitor.pause() globalMonitor.resume() // Remove specific action globalMonitor.removeAction(beepAction, forKeyEvent: .down) // Remove all actions globalMonitor.removeAllActions() // Handle both key down and key up globalMonitor.addAction(beepAction, forKeyEvent: .down) globalMonitor.addAction(beepAction, forKeyEvent: .up) ``` -------------------------------- ### Create SRShortcut Objects Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Demonstrates various ways to create SRShortcut objects, including from key equivalent strings, key codes and modifier flags, keyboard events, and Cocoa text key bindings. Shows how to access shortcut properties and obtain a dictionary representation. ```swift import ShortcutRecorder // Create from key equivalent string (symbolic format) let shortcut1 = Shortcut(keyEquivalent: "⇧⌘A") // Create from key code and modifier flags let shortcut2 = Shortcut( code: .ansiA, modifierFlags: [.command, .shift], characters: "A", charactersIgnoringModifiers: "a" ) // Create from keyboard event if let event = NSApp.currentEvent, event.type == .keyDown { let shortcut3 = Shortcut(event: event) } // Create from Cocoa text key binding let shortcut4 = Shortcut(keyBinding: "^a") // Access properties print(shortcut1?.keyCode ?? .none) // Key code value print(shortcut1?.modifierFlags ?? []) // Modifier flags print(shortcut1?.characters ?? "") // Character with modifiers print(shortcut1?.readableStringRepresentation(isASCII: true) ?? "") // "⇧⌘A" // Dictionary representation (compatible with ShortcutRecorder 2) let dict = shortcut1?.dictionaryRepresentation ``` -------------------------------- ### Configure SRRecorderControl for Recording Shortcuts Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Shows how to create and configure an SRRecorderControl instance for capturing keyboard shortcuts. Covers setting allowed and required modifier flags, enabling/disabling specific recording behaviors, setting an initial shortcut value, and binding to user defaults. ```swift import ShortcutRecorder // Create and configure the recorder control let recorder = RecorderControl() recorder.translatesAutoresizingMaskIntoConstraints = false // Configure allowed modifier flags (default: command, option, shift, control) recorder.set( allowedModifierFlags: [.command, .option, .shift, .control], requiredModifierFlags: [.command], // At least Command required allowsEmptyModifierFlags: false // Must have modifier flags ) // Configure behavior options recorder.allowsEscapeToCancelRecording = true recorder.allowsDeleteToClearShortcutAndEndRecording = true recorder.pausesGlobalShortcutMonitorWhileRecording = true recorder.drawsASCIIEquivalentOfShortcut = true recorder.allowsModifierFlagsOnlyShortcut = false // Allow modifier-only shortcuts // Set initial value recorder.objectValue = Shortcut(keyEquivalent: "⇧⌘A") // Bind to user defaults with value transformer let defaults = NSUserDefaultsController.shared recorder.bind( .value, to: defaults, withKeyPath: "values.myShortcut", options: [.valueTransformerName: NSValueTransformerName.keyedUnarchiveFromDataTransformerName] ) // Add to view view.addSubview(recorder) NSLayoutConstraint.activate([ recorder.centerXAnchor.constraint(equalTo: view.centerXAnchor), recorder.centerYAnchor.constraint(equalTo: view.centerYAnchor), recorder.widthAnchor.constraint(greaterThanOrEqualToConstant: 200) ]) ``` -------------------------------- ### Configure ShortcutRecorder in Objective-C Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Provides a complete implementation of SRRecorderControl and SRShortcutValidator, including delegate methods and global shortcut monitoring. ```objective-c #import @interface AppDelegate () @property (weak) IBOutlet SRRecorderControl *recorderControl; @property (strong) SRShortcutValidator *validator; @property (strong) SRShortcutAction *globalAction; @end @implementation AppDelegate - (void)applicationDidFinishLaunching:(NSNotification *)notification { // Configure recorder [self.recorderControl setAllowedModifierFlags:SRCocoaModifierFlagsMask requiredModifierFlags:NSEventModifierFlagCommand allowsEmptyModifierFlags:NO]; self.recorderControl.delegate = self; // Setup validator self.validator = [[SRShortcutValidator alloc] initWithDelegate:self]; // Bind to user defaults NSUserDefaultsController *defaults = [NSUserDefaultsController sharedUserDefaultsController]; NSDictionary *options = @{NSValueTransformerNameBindingOption: NSKeyedUnarchiveFromDataTransformerName}; [self.recorderControl bind:NSValueBinding toObject:defaults withKeyPath:@"values.globalShortcut" options:options]; // Create global shortcut action self.globalAction = [SRShortcutAction shortcutActionWithKeyPath:@"values.globalShortcut" ofObject:defaults actionHandler:^BOOL(SRShortcutAction *action) { NSLog(@"Global shortcut triggered!"); [[NSSound soundNamed:@"Basso"] play]; return YES; }]; [[SRGlobalShortcutMonitor sharedMonitor] addAction:self.globalAction forKeyEvent:SRKeyEventTypeDown]; } #pragma mark - SRRecorderControlDelegate - (BOOL)recorderControl:(SRRecorderControl *)aControl canRecordShortcut:(SRShortcut *)aShortcut { NSError *error = nil; if (![self.validator validateShortcut:aShortcut error:&error]) { NSAlert *alert = [NSAlert alertWithError:error]; [alert runModal]; return NO; } return YES; } - (BOOL)recorderControl:(SRRecorderControl *)aControl shouldUnconditionallyAllowModifierFlags:(NSEventModifierFlags)aModifierFlags forKeyCode:(SRKeyCode)aKeyCode { // Allow function keys without modifiers return aKeyCode >= SRKeyCodeF1 && aKeyCode <= SRKeyCodeF20; } #pragma mark - SRShortcutValidatorDelegate - (BOOL)shortcutValidatorShouldCheckMenu:(SRShortcutValidator *)aValidator { return YES; } - (BOOL)shortcutValidatorShouldCheckSystemShortcuts:(SRShortcutValidator *)aValidator { return YES; } @end ``` -------------------------------- ### Monitor Global Shortcuts with AXGlobalShortcutMonitor Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Uses Quartz Event Services to monitor global shortcuts, including modifier-only combinations. Requires Accessibility permissions to function. ```swift import ShortcutRecorder // Initialize with default run loop (requires Accessibility permission) guard let axMonitor = AXGlobalShortcutMonitor() else { print("Failed to create AX monitor - check Accessibility permissions") return } // Or specify run loop and tap options let axMonitor2 = AXGlobalShortcutMonitor( runLoop: .main, tapOptions: .defaultTap // .listenOnly for passive monitoring ) // Create modifier-only shortcut (not possible with standard GlobalShortcutMonitor) let modifierOnlyAction = ShortcutAction( shortcut: Shortcut(code: .none, modifierFlags: [.command, .option], characters: nil, charactersIgnoringModifiers: nil), actionHandler: { action in print("Command+Option pressed!") return true } ) axMonitor?.addAction(modifierOnlyAction, forKeyEvent: .down) // Access the underlying event tap let eventTap = axMonitor?.eventTap let runLoop = axMonitor?.eventTapRunLoop ``` -------------------------------- ### Transform Key Codes and Modifier Flags Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Demonstrates using LiteralKeyCodeTransformer, SymbolicKeyCodeTransformer, ASCIILiteralKeyCodeTransformer, and ASCIISymbolicKeyCodeTransformer for key codes. Also shows LiteralModifierFlagsTransformer and SymbolicModifierFlagsTransformer for modifier flags, including layout direction support. ```swift import ShortcutRecorder // Key code transformers let literalTransformer = LiteralKeyCodeTransformer.shared let symbolicTransformer = SymbolicKeyCodeTransformer.shared let asciiLiteralTransformer = ASCIILiteralKeyCodeTransformer.shared let asciiSymbolicTransformer = ASCIISymbolicKeyCodeTransformer.shared // Transform key code to string let keyCode = NSNumber(value: KeyCode.ansiA.rawValue) let literal = literalTransformer.transformedValue(keyCode) as? String // "a" or locale-dependent let symbol = asciiSymbolicTransformer.transformedValue(keyCode) as? String // "A" // Reverse transform (ASCII transformers only) let reversedKeyCode = asciiSymbolicTransformer.reverseTransformedValue("A") as? NSNumber // Modifier flags transformers let literalModTransformer = LiteralModifierFlagsTransformer.shared let symbolicModTransformer = SymbolicModifierFlagsTransformer.shared let modFlags = NSNumber(value: (NSEventModifierFlags.command.rawValue | NSEventModifierFlags.shift.rawValue)) let literalMods = literalModTransformer.transformedValue(modFlags) as? String // "⇧⌘" let symbolicMods = symbolicModTransformer.transformedValue(modFlags) as? String // "Shift-Command" (localized) // With layout direction support let rtlMods = literalModTransformer.transformedValue(modFlags, layoutDirection: .rightToLeft) ``` -------------------------------- ### Monitor Local Shortcuts with LocalShortcutMonitor Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Handles shortcuts within the application's responder chain. Integrates with standard NSResponder methods like keyDown and performKeyEquivalent. ```swift import ShortcutRecorder class MyViewController: NSViewController { let localMonitor = LocalShortcutMonitor() override func viewDidLoad() { super.viewDidLoad() // Add custom shortcut action let action = ShortcutAction( shortcut: Shortcut(keyEquivalent: "⌘E")!, actionHandler: { _ in print("Edit shortcut triggered!") return true } ) localMonitor.addAction(action, forKeyEvent: .down) // Or use convenience method localMonitor.addAction(#selector(toggleSidebar(_:)), forKeyEquivalent: "⌘\\", tag: 100) } override func keyDown(with event: NSEvent) { if !localMonitor.handleEvent(event, withTarget: self) { super.keyDown(with: event) } } override func performKeyEquivalent(with event: NSEvent) -> Bool { if localMonitor.handleEvent(event, withTarget: self) { return true } return super.performKeyEquivalent(with: event) } @objc func toggleSidebar(_ sender: Any?) { print("Toggle sidebar!") } } // Pre-configured monitors for common shortcuts let standardShortcuts = LocalShortcutMonitor.standardShortcuts // Text navigation let clipboardShortcuts = LocalShortcutMonitor.clipboardShortcuts // Cut, copy, paste let windowShortcuts = LocalShortcutMonitor.windowShortcuts // Close, minimize let documentShortcuts = LocalShortcutMonitor.documentShortcuts // Save, open, print let appShortcuts = LocalShortcutMonitor.appShortcuts // Hide, quit let mainMenuShortcuts = LocalShortcutMonitor.mainMenuShortcuts // Full main menu set ``` -------------------------------- ### Custom RecorderControl Styling Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Shows how to create and apply custom styles to SRRecorderControl using RecorderControlStyle.Components and subclassing RecorderControl for complete customization. ```swift import ShortcutRecorder // Create custom style with specific components let components = RecorderControlStyle.Components( appearance: .darkAqua, // .aqua, .darkAqua, .vibrantLight, .vibrantDark accessibility: .highContrast, // .none, .highContrast layoutDirection: .leftToRight, // .leftToRight, .rightToLeft tint: .blue // .blue, .graphite ) let customStyle = RecorderControlStyle(identifier: "my-custom-style", components: components) // Apply to recorder let recorder = RecorderControl() recorder.style = customStyle // Create style from bundle resources // Resources should be named: --.png // Example: my-style-darkaqua-acc-bezel-normal.png let bundleStyle = RecorderControlStyle(identifier: "my-style", components: components) // Subclass for complete customization class MyRecorderControl: RecorderControl { override func makeDefaultStyle() -> RecorderControlStyle { let components = RecorderControlStyle.Components( appearance: .unspecified, accessibility: .unspecified, layoutDirection: .unspecified, tint: .unspecified ) return RecorderControlStyle(identifier: "my-app-style", components: components) } override func drawBackground(_ dirtyRect: NSRect) { // Custom background drawing NSColor.controlBackgroundColor.setFill() focusRingShape.fill() } override func drawLabel(_ dirtyRect: NSRect) { // Custom label drawing using drawingLabel and drawingLabelAttributes let label = drawingLabel let attributes = drawingLabelAttributes ?? [:] label.draw(in: bounds, withAttributes: attributes) } } ``` -------------------------------- ### Validate Shortcuts with ShortcutValidator Source: https://context7.com/kentzo/shortcutrecorder/llms.txt Checks for conflicts with system shortcuts or menu key equivalents. Supports custom validation logic via the ShortcutValidatorDelegate. ```swift import ShortcutRecorder class MyDelegate: NSObject, ShortcutValidatorDelegate { let validator = ShortcutValidator(delegate: nil) func validateShortcut(_ shortcut: Shortcut) -> Bool { validator.delegate = self do { // Full validation (delegate + system + menu) try validator.validate(shortcut: shortcut) return true } catch { print("Invalid shortcut: \(error.localizedDescription)") return false } } // MARK: - ShortcutValidatorDelegate func shortcutValidator(_ validator: ShortcutValidator, isShortcutValid shortcut: Shortcut, reason: AutoreleasingUnsafeMutablePointer) -> Bool { // Custom validation logic if shortcut.keyCode == .escape { reason.pointee = "Escape is reserved" as NSString return false } return true } func shortcutValidatorShouldCheckMenu(_ validator: ShortcutValidator) -> Bool { return true // Check against app menu items } func shortcutValidatorShouldCheckSystemShortcuts(_ validator: ShortcutValidator) -> Bool { return true // Check against system-wide shortcuts } } // Validate against specific menu let menu = NSApp.mainMenu! do { try validator.validate(shortcut: shortcut, againstMenu: menu) } catch { print("Conflicts with menu item") } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.