Generate keyboard events for the frontmost application

10,759

Sure, you'll want to use CGEventCreateKeyboardEvent to create keyboard events, then post them as such:

    CGEventRef keyup, keydown;
    keydown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56, true);
    keyup = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56, false);

    CGEventPost(kCGHIDEventTap, keydown);
    CGEventPost(kCGHIDEventTap, keyup);
    CFRelease(keydown);
    CFRelease(keyup);

It's a bit more complicated than AppleScript but it does the trick. You do have to explicitly post a keydown and then a keyup event. More information at the Quartz Event Services Reference.

Share:
10,759
SteAp
Author by

SteAp

Fiddling around with Flutter. Writing Frog (spare-time project). Profile image: Please don't copy my painting.

Updated on June 22, 2022

Comments

  • SteAp
    SteAp almost 2 years

    In Mac OS / Cocoa, may I synthesize keyboard entries - strings - for the frontmost application in a transparent way?

    To be more precise, I don't want to send special characters or control sequences. My only need is to send standard characters.

    Just learned here, that AppleScript can do the trick like this:

    tell application "TextEdit"
        activate
    
        tell application "System Events"
            keystroke "f" using {command down}
        end tell
    end tell
    

    Q: How would I do this using ObjC / cocoa?

    UPDATE 2012-02-18 - Nicks proposal enhanced

    Based on Nick's code below, here is the final solution:

    // First, get the PSN of the currently front app
    ProcessSerialNumber psn;
    GetFrontProcess( &psn );
    
    // make some key events
    CGEventRef keyup, keydown;
    keydown = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)6, true);
    keyup = CGEventCreateKeyboardEvent (NULL, (CGKeyCode)6, false);
    
    // forward them to the frontmost app
    CGEventPostToPSN (&psn, keydown); 
    CGEventPostToPSN (&psn, keyup); 
    
    // and finally behave friendly
    CFRelease(keydown);
    CFRelease(keyup);
    

    Using this method, a click on a button of a non-activating panel targets the event to the actual front application. Perfectly what I want to do.

  • SteAp
    SteAp about 12 years
    Thank you! Never did anything at such a low level.