Listening for Global Keypresses in OSX.

While working on some new projects recently, I found it difficult to find any good information about how to listen for global keypresses in OSX using a mix of objective-c++ and c. The following code is the result of several hours of searching and frustration, hopefully it can save someone else the same pain.

The method I used to listen for global keypresses is using Event Taps from the Quartz framework. The user must either run this code as root, or have enabled access for assistive devices.

#include <ApplicationServices/ApplicationServices.h>
CGEventRef
myCGEventCallback(CGEventTapProxy proxy, CGEventType type,
                  CGEventRef event, void *refcon)
{
    // Paranoid sanity check.
    if ((type != kCGEventKeyDown) && (type != kCGEventKeyUp))
        return event;

    // The incoming keycode.
    CGKeyCode keycode = (CGKeyCode)CGEventGetIntegerValueField(
                                       event, kCGKeyboardEventKeycode);

    //Keypress code goes here.

    // We must return the event for it to be useful.
    return event;
}

int
main(void)
{
    CFMachPortRef      eventTap;
    CGEventMask        eventMask;
    CFRunLoopSourceRef runLoopSource;

    // Create an event tap. We are interested in key presses.
    eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
    eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, 0,
                                eventMask, myCGEventCallback, NULL);
    if (!eventTap) {
        fprintf(stderr, "failed to create event tap\n");
        exit(1);
    }   

    // Create a run loop source.
    runLoopSource = CFMachPortCreateRunLoopSource(
                        kCFAllocatorDefault, eventTap, 0);

    // Add to the current run loop.
    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource,
                       kCFRunLoopCommonModes);

    // Enable the event tap.
    CGEventTapEnable(eventTap, true);

    // Set it all running.
    CFRunLoopRun();

    exit(0);
}

Compile the above code either using Xcode or GCC with the following –

gcc -Wall -o globalkeypress globalkeypress.c -framework ApplicationServices

In the next couple of days I will upload some code that shows how to move the mouse and simulate mouse clicks.

Advertisements

One thought on “Listening for Global Keypresses in OSX.

  1. I wanted to make a background C application that could listen for keyboard shortcuts. This is EXACTLY what I was looking for! Thank you so much!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s