As an experiment, I am trying to achieve the following:
I was thinking of handling the keydown and keyup event, but apparently handleEvent:client:
in IMKServerInput Protocol seems to only catch key down and mouse events.
Without much experience with cocoa, I’ve tried some methods with no success:
recognizedEvents:
in IMKStateSetting Protocol, but that didn’t seem to catch the event either.NSFlagsChanged
event fire with spacebar.CGEventTap
which seems to handle user inputs in lower level. Didn’t go further to this route, yet.I reached to a conclusion that IMKit is only capable of passively receiving events.
Since it is not an application, there is no keyUp:
method to override - AFAIK, IMKit does not inherit NSResponder
class.
Unfortunately cocoa is way too broad and has much less (or overflowed with non-helping) documentations for a novice like me to dive in.
Can anyone help me to the right direction?
I tried all possible alternatives one by one, and eventually achieved it by creating a global EventTap
with CGEventTap
.
The code basically looks like this:
// Create an event tap.
CGEventMask eventMask = ((1 << kCGEventKeyDown) | (1 << kCGEventKeyUp));
CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap,
kCGHeadInsertEventTap,
0,
eventMask,
myCGEventCallback,
NULL);
if (!eventTap) {
NSLog(@"failed to create event tap\n");
return NO;
} else {
// Create a run loop source.
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
// Add to the current run loop.
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
// Enable the event tap.
CGEventTapEnable(eventTap, true);
return YES;
}
where myCGEventCallback
handles the global states.
Meanwhile here are some of what I've found out:
IMKServerInput
'catch' the NSKeyUp event. Just adding an NSKeyUpMask
to recognizedEvents:
would not work. addLocalMonitorForEventsMatchingMask:handler:
and CGEventTapCreateForPSN
would not catch the event. I suppose this is because though an Input Method may run as a separate process, the event itself is fired from the application, like TextEdit, and handed over to the Input `Method.IOHIDManager:
is for adding new hardware devices and making drivers./Library/Input Methods
does not run with sudo privilege --, or registering the application to the Accessibility control. That's in System Preferences → Security & Privacy → Privacy tab → Accessibility, in Mavericks.