0

I can install system wide keyboard monitor by the below instructions:

CGEventRef eventCallback(CGEventTapProxy proxy, CGEventType type,
    CGEventRef event, void *userData)
{
}

CFMachPortRef eventTap = CGEventTapCreate(kCGHIDEventTap,
    kCGHeadInsertEventTap, kCGEventTapOptionDefault,
    kCGEventKeyDown,
    &eventCallback,
    NULL);
if(eventTap)
{
    CFRunLoopSourceRef eventRunLoopSourceRef =
        CFMachPortCreateRunLoopSource(NULL, eventTap, 0);
    CFRelease(eventTap);
    CFRunLoopAddSource(CFRunLoopGetCurrent(), eventRunLoopSourceRef,
        kCFRunLoopDefaultMode);
    CFRelease(eventRunLoopSourceRef);
}

The disadvantage of this code is that it requires to activate "Universal access" in "System Preferences" and also monitor all processes (I do not need it).

I want to monitor keyboard events inside my process. How it possible and is it required to activate "Universal access"? Thankyou.

mh taqia
  • 3,506
  • 1
  • 24
  • 35

4 Answers4

4

I think you want NSEvent's addLocalMonitorForEventsMatchingMask:handler:

self.eventMonitor = [NSEvent addLocalMonitorForEventsMatchingMask:NSKeyDownMask 
    handler:^(NSEvent *event) {
        NSLog( @"keyDown event!" );
        return event;
    }];

See the docs. This doesn't require Universal Access to be turned on.

zpasternack
  • 17,838
  • 2
  • 63
  • 81
  • What happens if I dont have access to "self"? I have been written a dylib which injected into other processes, In carbon apps like InDesign, I use Carbon Events and have no problen, but in cocoa apps like TextEdit how can I use your approach inside a dylib? – mh taqia Jul 22 '12 at 10:36
  • addLocalMonitorForEventsMatchingMask:handler: returns an id, which you need to save somewhere so you can remove the monitor later (with removeMonitor:). In my example, I made it a property on a class, but it doesn't have to be. – zpasternack Jul 22 '12 at 18:47
2

If you do not have to monitor other processes then you should be able to use normal events to look at the keyboard.

In Carbon, install a handler for kEventRawKeyDown (say) of kEventClassKeyboard, e.g. at the application or window levels.

In Cocoa, implement keyDown: or whatever method you require on a subclass of NSResponder such as your NSApplication subclass or a particular NSWindow subclass.

Kevin Grant
  • 5,363
  • 1
  • 21
  • 24
  • What happens if I dont have access to NSApplication? I have been written a dylib which injected into other processes, In carbon apps like InDesign, I use Carbon Events and have no problen, but in cocoa apps like TextEdit how can I implement keyDown: inside a dylib? – mh taqia Jul 22 '12 at 10:34
2
ProcessSerialNumber psn = { 0 };
GetCurrentProcess( & psn );
CGEventTapCreateForPSN( & psn, ... );

This is the process-wide manner for listening to events only in the current process, not system-wide.

Ivan Caravanio
  • 597
  • 1
  • 7
  • 20
1

In Cocoa, I think you'd want to subclass NSApplication and override -[NSApplication sendEvent:].

JWWalker
  • 22,385
  • 6
  • 55
  • 76
  • What happens if I dont have access to "NSApplication"? I have been written a dylib which injected into other processes, In carbon apps like InDesign, I use Carbon Events and have no problen, but in cocoa apps like TextEdit how can I monitor keydown inside a dylib? – mh taqia Jul 22 '12 at 10:39