1

I have an application that, upon activation, is 'backgrounded' and has an NSStatusItem icon which can be clicked to either close the application or open an NSWindow.

Currently, I can click the icon, and then press command+option+T and the NSWindow will activate but what I can't do is press the key combo without first clicking the NSStatusItem.

So, I was wondering if it's possible at all to register a hot-key in the system or where do I need to be looking so that I don't have to first click the status item to 'activate' the application?

Thanks!

Peter Hosey
  • 95,783
  • 15
  • 211
  • 370
Zrb0529
  • 800
  • 9
  • 25

2 Answers2

4

Yep! Implementing global hotkeys yourself is a bit tedious, but there are some really great wrappers out there. I'm quite partial to the one I wrote: http://github.com/davedelong/DDHotKey

You use it like this:

- (void) registerHotkey {
    DDHotKeyCenter * c = [[DDHotKeyCenter alloc] init];
    [c registerHotKeyWithKeyCode:9 modifierFlags:NSControlKeyMask target:self action:@selector(hotkeyWithEvent:) object:nil];
    [c release];
}

- (void) hotkeyWithEvent:(NSEvent *)hkEvent {
    NSLog(@"hotkey event: %@", hkEvent);
}
Dave DeLong
  • 242,470
  • 58
  • 448
  • 498
  • 2
    If you include Carbon.h, you can use symbolic constants such as `kVK_ANSI_V` instead. – Peter Hosey Feb 13 '11 at 03:46
  • So, what I should do is to add DDHotKeyCenter.h and DDHotKeyCenter.m to my project, and then add the above to my application and use it to call MyWindow (the NSWindow), instead of 'NSLog(@"hotkey event: %@", hkEvent); I would type self.window makeMainWindow right? – Zrb0529 Feb 13 '11 at 07:01
  • I think I missed a step, when I try to compile I get the error " 'c' undeclared (first use in this function) " :-) – Zrb0529 Feb 13 '11 at 07:18
  • 1
    @TotalCocoaNewb did you include `#import "DDHotKeyCenter.h"` at the top of the file? – Dave DeLong Feb 13 '11 at 07:19
  • I had forgotten that, but now that I've done it, I get 6 new build errors such as: "_GetEventParamete", referenced from: _dd_hotKeyHandler in DDHotKeyCenter.o – Zrb0529 Feb 13 '11 at 07:30
  • 1
    @TotalCocoaNewb the readme mentions that you have to link against Carbon.framework as well. – Dave DeLong Feb 13 '11 at 08:26
  • ah, when I #import "Carbon.framework/Carbon.h" #include "Carbon.h" I get 'improper preprocessing directive 'import' and no such file or directory on carbon.h – Zrb0529 Feb 13 '11 at 20:03
  • wow, I'm dumb, I hadn't actually added Carbon.framework to my 'Frameworks' group! Thanks for all the help! working perfectly now. – Zrb0529 Feb 14 '11 at 00:42
  • Am I correct in reading this that the current key-combo setup is "control + 9" ? – Zrb0529 Feb 14 '11 at 00:50
  • @TotalCocoaNewb no; the `9` is the *keycode*, and it happens to represent the `v` key. As Peter Hosey suggests, you can use the constants defined in `Events.h` instead of a raw keycode. Also, check out the free "Key Codes" app on the Mac App Store. – Dave DeLong Feb 14 '11 at 01:13
  • I seem to be having an issue. Should I put the above code in my AppDelegate or AppController? – Zrb0529 Feb 14 '11 at 03:07
  • @TotalCocoaNewb you put it where it makes sense architecturally. – Dave DeLong Feb 14 '11 at 03:39
  • could I use - (void) addOutput: (NSWindow *) newOutput { NSWindow * current = [output string]; output setString:[ current TrialWindow] to open a window (named TrialWindow) using the hotkey code? I currently have it working where it will post the text strings in the example code and was wondering if I could use it to also open an existing window within the application? – Zrb0529 Feb 15 '11 at 23:32
  • @TotalCocoaNewb if you use the selector-based callback, then the callback must accept an `NSEvent`. It can optionally accept another object. If you use the block-based callback, then you can capture whatever you want in the callback. – Dave DeLong Feb 15 '11 at 23:38
  • so then, using the block-based callback could I use something like '-(IBAction)activateWindow:(id)sender {     if(! [trialWindow isVisible] )         [trialWindow makeKeyAndOrderFront:sender]; }' – Zrb0529 Feb 16 '11 at 00:26
  • @TotalCocoaNewb maybe? I'm not sure how the rest of your code is set up. – Dave DeLong Feb 16 '11 at 00:42
  • oh it's directly from the link posted above, I just removed example 1 and 2 and then added a new window in Interface Builder. – Zrb0529 Feb 16 '11 at 01:06
1

Yes, it is possible to set up a global hot-key. As Dave mentioned, there are several wrappers; the answers on that question give links to (AFAIK, as of this writing) all of them.

Community
  • 1
  • 1
Peter Hosey
  • 95,783
  • 15
  • 211
  • 370