9

How would I register a global hotkey in Objective-C/Cocoa (Mac) ?

For example, the hotkey I'd like to register would be Alt - Cmd - D

Any help would be appreciated!

FelixSFD
  • 6,052
  • 10
  • 43
  • 117
Seb Jachec
  • 3,003
  • 2
  • 30
  • 56
  • 3
    why bolds ... We have tags for that ;) – nacho4d Jan 26 '11 at 16:57
  • 4
    Please keep in mind that using "alt-D" globally is not the best idea, as it usually generates a valid character (∂) and might be already defined in other applications (access keys in Safari are an example). Also, a common Mac user expects to have at least "cmd" as a modifier key in shortcuts. – Asmus Jan 26 '11 at 17:06
  • @Asmus: +1, and ideally the "hot key" needs to be user-configurable too. – Paul R Jan 26 '11 at 17:09
  • Yup. User-configurable would be nice, but I'm not too fussed. What about Alt-Cmd-D ? Trying to do a hotkey that's not too complicated but that doesn't clash with other stuff either. – Seb Jachec Jan 26 '11 at 17:16
  • 1
    Cmd-Alt-D is the global shortcut to show / hide the Dock, so this would not be exactly ideal ;-) Usually "Cmd + character" and "Cmd + Alt + character" are already in use by applications - but I think Cmd-Ctrl-D would be an option (can´t think of anything that uses that..) – Asmus Jan 26 '11 at 23:13
  • possible duplicate of [System-wide hotkey for an application](http://stackoverflow.com/questions/3760318/system-wide-hotkey-for-an-application) – Peter Hosey Jan 27 '11 at 11:46

4 Answers4

12

There's a convenient Cocoa wrapper for the required Carbon functions on GitHub: JFHotkeyManager. You could also use the new (since 10.6) NSEvent API addGlobalMonitorForEventsMatchingMask:handler:, but it only gets key events if access for assistive devices is enabled.

omz
  • 53,243
  • 5
  • 129
  • 141
  • 1
    Wowza... It even takes NSStrings like [hkm bind:@"alt command d" target:self action:@selector(show:)]; . =) – Seb Jachec Jan 26 '11 at 20:02
7

I wrote a wrapper class to make this a heck of a lot easier...

https://github.com/davedelong/DDHotKey

Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • 1
    Can you please explain the APIs you used in that code. Like I am trying to use `addGlobalMonitor` when assistive devices is not enabled but am having a hard time. Is `CGEventTap` an option when assistive devices is not enabled? – Noitidart Aug 30 '15 at 18:30
  • 1
    @Noitidart did you figure it out? Because I didn't. I wonder why someone would spend time writing up a nice wrapper to make some task a helluva lot easier without explaining how to use it. – user3496846 Jan 18 '16 at 13:28
  • 1
    Totally agree with you @user3496846 - Yeah I figured it out, both CG and objc methods are limited by accessiblity, if you want to register a hot key you have to use the Carbon method RegisterHotKey - https://developer.apple.com/legacy/library/documentation/Carbon/Reference/CarbonFrameworkReference/index.html#//apple_ref/doc/uid/TP40004336 – Noitidart Jan 18 '16 at 17:21
  • @Noitidart aha, OK, I will be diving into that, I guess. Thank you. – user3496846 Jan 18 '16 at 18:40
5

You'll want to use the functions InstallApplicationEventHandler and RegisterEventHotKey from the Carbon framework. This blog post gives a pretty good how-to (it's what I used when I was figuring this stuff out).

mipadi
  • 398,885
  • 90
  • 523
  • 479
4

here you go:

#import <Carbon/Carbon.h>

EventHandlerUPP hotKeyFunction;

pascal OSStatus hotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEvent, void *userData)
{    
    FooBar *obj =  userData;
    [obj foo];    
    return noErr;
}

@implementation FooBar

- (id)init
{
    self = [super init];
    if (self) {
        //handler
        hotKeyFunction = NewEventHandlerUPP(hotKeyHandler);
        EventTypeSpec eventType;
        eventType.eventClass = kEventClassKeyboard;
        eventType.eventKind = kEventHotKeyReleased;
        InstallApplicationEventHandler(hotKeyFunction,1,&eventType,self,NULL);
        //hotkey
        UInt32 keyCode = 80; //F19    
        EventHotKeyRef theRef = NULL;
        EventHotKeyID keyID;
        keyID.signature = 'FOO '; //arbitrary string
        keyID.id = 1;
        RegisterEventHotKey(keyCode,0,keyID,GetApplicationEventTarget(),0,&theRef);

    }        
    return self;
}

- (void)foo
{

}

@end
valexa
  • 4,462
  • 32
  • 48