Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to implement shortcut key input in Mac Cocoa App?

I've needed to make a global hot key input box in my Cocoa App.

I know about Shortcut Recorder, but it is a very old solution. It has parts implemented using Carbon, which has been deprecated, and I can't publish my app to the Mac App Store if I use it.

Is there any ready-to-use modern solution? Can anybody give me the way to make this by myself (I don't know where to start from)?

like image 464
Victor Shcherbakov Avatar asked Nov 20 '11 11:11

Victor Shcherbakov


People also ask

How do you program keyboard shortcuts on a Mac?

On your Mac, choose Apple menu > System Preferences, click Keyboard , then click Shortcuts. Select App Shortcuts on the left, click the Add button , click the Application pop-up menu, then choose a specific app or All Applications.

How do I create a keyboard shortcut for Text on a Mac?

Open “System Preferences” > Keyboard > Shortcuts Tab > Services. You should see the service that you have just created. Click on the service and click on “Add Shortcut” and assign a shortcut. Now the service will be invoked every-time you hit the shortcut and the service would enter the keystrokes “[email protected]”.


3 Answers

There is a modern framework named MASShortcut for implementing Global Shortcuts in OS X 10.7+.

like image 103
Vadim Avatar answered Oct 20 '22 04:10

Vadim


Not all of Carbon is deprecated. You can't make a pure-Carbon application anymore, but some APIs live on and some of them are still the easiest way to do certain things.

One of these is the Carbon Events hotkey API. You certainly can sift through all the events using NSEvent's event-monitor methods, but it's unnecessary work. The Carbon Events hotkey API is still supported and much simpler—you just tell it what key you want to match and what function to call when the key is pressed. And there are Cocoa wrappers such as DDHotKey that make it even simpler.

  • RegisterEventHotKey, the relevant Carbon Events function (see also UnregisterEventHotKey in the same doc)
  • DDHotKey
  • MASShortcut, yet another wrapper (suggested by TongG):
    • MASShortcut (with ARC)
    • MASShortcut (without ARC)
  • KeyboardShortcuts, written in Swift and includes a SwiftUI hotkey recorder view [added to this answer in edit by the project's author].
like image 32
Peter Hosey Avatar answered Oct 20 '22 02:10

Peter Hosey


In Mac OS X 10.6 and higher, you can use the methods +addGlobalMonitorForEventsMatchingMask:handler: and +addLocalMonitorForEventsMatchingMask:handler: defined from the NSEvent class. Monitoring Events reports the following information:

Local and global event monitors are mutually exclusive. For example, the global monitor does not observe the event stream of the application in which it is installed. The local event monitor only observes the event stream of its application. To monitor events from all applications, including the "current" application, you must install both event monitors.

The code shown in that page is for a local event monitor, but the code for a global event monitor is similar; what changes is the invoked NSEvent's method.

_eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:
        (NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask | NSKeyDownMask)
        handler:^(NSEvent *incomingEvent) {
    NSEvent *result = incomingEvent;
    NSWindow *targetWindowForEvent = [incomingEvent window];
    if (targetWindowForEvent != _window) {
        [self _closeAndSendAction:NO];
    } else if ([incomingEvent type] == NSKeyDown) {
        if ([incomingEvent keyCode] == 53) {
            // Escape
            [self _closeAndSendAction:NO];
            result = nil; // Don't process the event
        } else if ([incomingEvent keyCode] == 36) {
            // Enter
            [self _closeAndSendAction:YES];
            result = nil;
        }
    }
    return result;
}];

Once the monitor is not anymore necessary, you remove it using the following code:

[NSEvent removeMonitor:_eventMonitor];
like image 20
apaderno Avatar answered Oct 20 '22 02:10

apaderno