Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C: Listen to keyboard shortcuts and act on them

I am developing an app for Mac OS X and I need to listen to keyboard shortcut inputs so I can act on them.

For example:

  • Up and down keys move up and down on a table view.
  • + drops an item.
  • + + N creates a new item.

It shouldn't be restricted to events on the focused control.

Any ideas?

Thanks in advance.

like image 746
mikywan Avatar asked May 26 '11 13:05

mikywan


People also ask

What is the keyboard shortcut for C?

Alternatively referred to as Cmd+C, Command+C is a keyboard shortcut used to copy highlighted text or other object to the clipboard in a graphical user environment. On Windows computers, the keyboard shortcut to copy is Ctrl + C .


2 Answers

I think your best option* would be +[NSEvent addLocalMonitorForEventsMatchingMask:handler:]. This creates an object which will call a block handler whenever your application receives an event of the specified type. The handling takes place right before your NSApplication dispatches the event to a window, and you have the opportunity to modify the event or stop it from proceeding further.

You can thus catch key down events as they get passed to your app and do whatever you like with them before any controls get a chance to see them. I posted this originally in another question, but here's a snippet for doing things with arrow key presses:

NSEvent * (^monitorHandler)(NSEvent *);
monitorHandler = ^NSEvent * (NSEvent * theEvent){

    switch ([theEvent keyCode]) {
        case 123:    // Left arrow
            NSLog(@"Left behind.");
            break;
        case 124:    // Right arrow
            NSLog(@"Right as always!");
            break;
        case 125:    // Down arrow
            NSLog(@"Downward is Heavenward");
            break;
        case 126:    // Up arrow
            NSLog(@"Up, up, and away!");
            break;
        default:
            break;
    }
    // Return the event, a new event, or, to stop 
    // the event from being dispatched, nil
    return theEvent;
};

// Creates an object we do not own, but must keep track of so that 
// it can be "removed" when we're done; therefore, put it in an ivar.
eventMon = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask 
                                                 handler:monitorHandler];

See the Event-Handling Guide for some details about what you're supposed to do with that monitor object. Specifically, Apple apparently "discourages" removing it inside of dealloc, but doesn't give a reason.


*So long as you can require Snow Leopard, at least.

like image 150
jscs Avatar answered Sep 29 '22 02:09

jscs


You may need to implements callbacks in your application. Take a look to CGEventTapCreate to start listening for hotkeys.

CGEventTapCreate(kCGSessionEventTap,
             kCGTailAppendEventTap,
             kCGEventTapOptionDefault,
             kCGEventKeyDown
             myEventTapCallback,
             NULL);

myEventTapCallback should be conform to CGEventTapCallBack and gets called when a key is pressed. Then, inside myEventTapCallback you'll have enough information on keys pressed and you can implement your custom functionality.

like image 21
Manlio Avatar answered Sep 29 '22 01:09

Manlio