0

Apologies if this is a stupid/easy question, but still getting used to everything in Mac land.

Dave was kind enough to answer a question for me here: Modify NSEvent to send a different key than the one that was pressed

which resulted in the following code, which works great:

#import <Cocoa/Cocoa.h>

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    //0x0b is the virtual keycode for "b"
    //0x09 is the virtual keycode for "v"
    if (CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode) == 0x0B) {
        CGEventSetIntegerValueField(event, kCGKeyboardEventKeycode, 0x09);
    }

    return event;
}

int main(int argc, char *argv[]) {
    //return NSApplicationMain(argc, (const char **)argv);

    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    CFRunLoopSourceRef runLoopSource;

    CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap, kCGHeadInsertEventTap, kCGEventTapOptionDefault, kCGEventMaskForAllEvents, myCGEventCallback, NULL);

    if (!eventTap) {
        NSLog(@"Couldn't create event tap!");
        exit(1);
    }

    runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);

    CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);

    CGEventTapEnable(eventTap, true);

    CFRunLoopRun();

    CFRelease(eventTap);
    CFRelease(runLoopSource);
    [pool release];

    exit(0);
}

Thanks to some helpful error messages (can't have two "main" methods) I figured out that I had to put this code in the main.m file (right?). That means I'm overwriting the default method:

int main(int argc, char *argv[]) {
    return NSApplicationMain(argc, (const char **)argv);
}

Which means none of my other Objective-C based code is firing. But if I uncomment that bit (or make any other attempt to call NSApplicationMain) then the main.m run loop is what doesn't run.

I imagine this is fairly simple for a seasoned Mac guy, but I'm having a hard time wrapping my head around it. Thanks.

Community
  • 1
  • 1
ck_
  • 3,719
  • 10
  • 49
  • 76

1 Answers1

1

I don't see any reason why the same idea won't work elsewhere in your code. Can you put it in the -applicationDidFinishLaunching: method of your app delegate? If you do, you will not need the CFRunLoop() call, since the run loop will already be running. Nor will you need the autorelease pool bit.

JeremyP
  • 84,577
  • 15
  • 123
  • 161