0
votes

I've got some code from a console app I wrote that im trying to adapt to use in a UI based app. It registers an event trap to monitor the mouse movement system wide. Some one advised me to create and run a thread to do the event loop set up so i don't block the app (the code is called from applicationDidFinishLaunching).

I have to be honest I've looked at a few documents about run loops and im completely confused :-( My code just hangs in the call to the listen function.

static MouseListener* listener = nil;

CGEventRef eventOccurred(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void* refcon) {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

    event = [listener eventOccurred:proxy:type:event:refcon];

    [pool release];

    return event;
}


@implementation MouseListener

-(MouseListener*) myinit {
    if (self = [super init]) {
        eventThread = [[NSThread alloc] initWithTarget:self                              
                                              selector:@selector(listen:)                              
                                                object:nil];        
        [eventThread start];
    }   

    return self;
}

-(void)listen:(NSObject*) object {        
    if (!listener) {
        listener = self;  

        CFMachPortRef tap = CGEventTapCreate(kCGHIDEventTap, 
                                             kCGHeadInsertEventTap, 
                                             kCGEventTapOptionDefault, 
                                             NSAnyEventMask, 
                                             eventOccurred, 
                                             NULL);

        if (tap) {
            CFRunLoopRef loop = CFRunLoopGetCurrent(); 
            CFRunLoopSourceRef src = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0);
            CFRunLoopAddSource(loop, src, kCFRunLoopCommonModes);
            CGEventTapEnable(tap, true);
            //CFRunLoopRun();
            //[[NSRunLoop currentRunLoop] run];
            CFRelease(src);
            CFRelease(tap);
       }
    }
}

-(CGEventRef) eventOccurred:(CGEventTapProxy) proxy: (CGEventType) type: (CGEventRef) event: (void*) refcon {

    // Do stuff, never gets called

    return event;
}
1

1 Answers

0
votes

I'll need to check my code once I'm back home, but what you have looks okay (I've done similar, but listening for I/O Kit events instead). CFRunLoopRun() is the function you want to call, however, why don't you just add your event tap to your app's main runloop? That saves any thread shenanigans too.