Search code examples
macoseventscore-graphicscore-foundation

Basic event handling with core graphics


I am trying to handle events with core graphics and core fundation on mac os.

My code:

#import <CoreGraphics/CoreGraphics.h>
#import <CoreFoundation/CoreFoundation.h>

static int counter = 0;

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {

    printf("event 0x%i\n ", counter++);

    return event;
}


int main(int argc, const char * argv[]) {


    CFRunLoopRef runner = CFRunLoopGetCurrent();





    CFMachPortRef mach = CGEventTapCreate(kCGHIDEventTap,kCGTailAppendEventTap , kCGEventTapOptionDefault, kCGEventMaskForAllEvents, myCGEventCallback, NULL);


    CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, mach, 0);

    CFRunLoopAddSource(runner, runLoopSource, kCFRunLoopCommonModes);

    CGEventTapEnable(mach, true);


    CFRunLoopRun();

    printf("end\n");



}

But It reacts only for touchpad-events. Keyboard events seems to be ignored by my program. I have tried changing event masks but I does not work. Can you give some advice?

PS

Is that good start to handle events? I want to make full screen OpenGL game with core graphics without libraries like SFML or SDL. I am using CGDisplayCapture and CGL to create OpeGL context.


Solution

  • To answer the letter of your question: to get keyboard events via a CGEventTap your app must be trusted to control your computer with Accessibility APIs. That means it must be in the list of applications under System Preferences -> Security & Privacy -> Accessibility. You can use the function AXProcessIsTrustedWithOptions to ask for this permission; you have to be code signed, but not sandboxed, and should be packaged as a .app in order to be added to the trusted applications list.

    As to your second question, if this is a good way to handle events for a game… not really, no. Use the NSEvent/NSApplication APIs to get input for your application. CGEventTap is a better choice when you want to get events for the entire user session, or another app, to do something like hook user input to do something custom when another app is frontmost (as assistive applications often have to do). In particular by passing kCGHIDEventTap you have asked for events to be delivered to your application at the point they enter the window server… this can easily result in a bug in your application being able to render the session unusable (say, by accidentally discarding all input to the session).