Domanda

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)?

È stato utile?

Soluzione

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

Altri suggerimenti

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.

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];
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top