CGEventCreateKeyboardEvent and CGEventTapLocation

2020-06-25 09:07发布

问题:

I'm having a hard time dealing with custom keyboard events. I want to be able to send any key with / without kCGEventFlagMasks like command, alt, ctrl, shift...

e.g. I want to send the current frontmost app, let's assume it's TextEdit, the key combo cmd+t, which should show the font window.

But currently only t is added to the current document of TextEdit. I tried posting the event with custom set CGEventFlags and alternatively generating keyDown and keyUp events for cmd around the t event. The free app Key Codes shows me when I use the CGEventFlags set, that cmd+t has been pressed, but this key combo isn't passed to TextEdit, only the single t...

Here's my code:

...
flags = (flags | kCGEventFlagMaskCommand);
[self writeString:@"" withFlags:flags];
...

(void)writeString:(NSString *)valueToSet withFlags:(int)flags
{
UniChar buffer;
CGEventRef keyEventDown = CGEventCreateKeyboardEvent(NULL, 1, true);
CGEventRef keyEventUp = CGEventCreateKeyboardEvent(NULL, 1, false);
CGEventSetFlags(keyEventDown,0);                
CGEventSetFlags(keyEventUp,0);          
for (int i = 0; i < [valueToSet length]; i++) {
    [valueToSet getCharacters:&buffer range:NSMakeRange(i, 1)];
    CGEventKeyboardSetUnicodeString(keyEventDown, 1, &buffer);
    CGEventSetFlags(keyEventDown,flags);
    CGEventPost(kCGSessionEventTap, keyEventDown);
    CGEventKeyboardSetUnicodeString(keyEventUp, 1, &buffer);
    CGEventSetFlags(keyEventUp,flags);
    CGEventPost(kCGSessionEventTap, keyEventUp);

}
CFRelease(keyEventUp);
CFRelease(keyEventDown);

}

I'm also having a hard time understanding the meaning of a CGEventTapLocation. I don't know which event tap would be the most suitable for my task. The description in the Quartz Event Reference doesn't enlighten me:

kCGHIDEventTap
Specifies that an event tap is placed at the point where HID system events enter the window server.


kCGSessionEventTap
Specifies that an event tap is placed at the point where HID system and remote control events enter a login session.


kCGAnnotatedSessionEventTap
Specifies that an event tap is placed at the point where session events have been annotated to flow to an application.

I've seen many posts about that topic, but none of 'em helped me solve my problem... Thanks for your help!

回答1:

That's not the answer to the question but my current workaround via AppleScript:

appleScriptString = [NSString stringWithFormat:@"tell application \"System Events\" to key code %d using %@",keyCode, modifierDownString];

which I feed to that function:

- (void)runScript:(NSString*)scriptText
{
    NSDictionary *error = nil;
    NSAppleEventDescriptor *appleEventDescriptor;
    NSAppleScript *appleScript;

    appleScript = [[NSAppleScript alloc] initWithSource:scriptText];
    appleEventDescriptor = [appleScript executeAndReturnError:&error];

    [appleScript release];
}