So far, so good. You have an event tap port. Now you need to turn it
into a runloop source, and in this case, add it to the runloop behind
the Carbon main event loop. Note that I normally don't recommend doing
this, as it will throttle the flow of events to the rate at which the
main loop can process and draw. In this case, the main event loop will
just be servicing the CGEventTap, so we might be able to get away with
this.
CFRunLoopSourceRef eventSrc;
CFRunLoopRef runLoop;
eventSrc = CFMachPortCreateRunLoopSource(NULL, machPortRef, 0);
if ( eventSrc == NULL )
printf( "No event run loop src?\n" );
// Get the CFRunLoop primitive for the Carbon Main Event Loop, and
add the new event souce
CFRunLoopAddSource(GetCFRunLoopFromEventLoop(GetMainEventLoop()),
eventSrc, kCFRunLoopDefaultMode);
RunApplicationEventLoop();
if (machPortRef)
CFRelease(machPortRef);
if ( eventSrc )
CFRelease(eventSrc);
}
In a command line tool, faceless app, or daemon, you can do something
similar purely at the CoreFoundation level:
#include <ApplicationServices/ApplicationServices.h>
CGEventRef printEventCallback(CGEventTapProxy proxy, CGEventType type,
CGEventRef event, void *refcon)
{
printf( "Got event of type %d\n", type )
return event;
}
int main(int argc, char ** argv)
{
CFMachPortRef eventPort;
CFRunLoopSourceRef eventSrc;
CFRunLoopRef runLoop;
eventPort = CGEventTapCreate(kCGSessionEventTap,
kCGHeadInsertEventTap,
kCGEventTapOptionListenOnly,
CGEventMaskBit(kCGEventOtherMouseDown),
printEventCallback,
NULL );
if ( eventPort == NULL )
{
printf( "NULL event port\n" );
exit( 1 );
}
eventSrc = CFMachPortCreateRunLoopSource(NULL, eventPort, 0);
if ( eventSrc == NULL )
printf( "No event run loop src?\n" );
runLoop = CFRunLoopGetCurrent();
if ( runLoop == NULL )
printf( "No run loop?\n" );
CFRunLoopAddSource(runLoop, eventSrc, kCFRunLoopDefaultMode);
CFRunLoopRun();
}