CGEventCreateKeyboardEvent just crashes?!?

  • Hi all,

    anybody can use CGEventCreateKeyboardEvent?

    I create the simplest project possible. Call the function exactly the
    way it's documented. And always got a nice small SIGBUS...

    Here's my source:

    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        // insert code here...
        NSLog(@"Hello, Apple World! What's there with them blasted
    events?!?");
        CGEventRef er=CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56,
    true); // directly from docs
        NSLog(@"actually, got event ref at %x. Bye.",er);
        [pool release];
        return 0;
    }

    Here's the project (I've tried plain C one, too): http://www.ocs.cz/
    apps/CGEventCrash.zip

    Will be very grateful for any advice what I do wrong...
    ---
    Ondra ÄŒada
    OCSoftware:    <ocs...>              http://www.ocs.cz
    private        <ondra...>            http://www.ocs.cz/oc
  • Hi Ondra,

    I ran into this problem a while ago and never could figure out what
    was wrong. If you don't need the CGEventRef back, trying using
    CGPostKeyboardEvent() instead. It looks like this:

    CGPostKeyboardEvent((CGCharCode)0, (CGKeyCode)56, true);

    -Phil

    On Oct 4, 2006, at 1:56 PM, Ondra Cada wrote:

    > Hi all,
    >
    > anybody can use CGEventCreateKeyboardEvent?
    >
    > I create the simplest project possible. Call the function exactly
    > the way it's documented. And always got a nice small SIGBUS...
    >
    > Here's my source:
    >
    > int main (int argc, const char * argv[]) {
    > NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    > // insert code here...
    > NSLog(@"Hello, Apple World! What's there with them blasted
    > events?!?");
    > CGEventRef er=CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56,
    > true); // directly from docs
    > NSLog(@"actually, got event ref at %x. Bye.",er);
    > [pool release];
    > return 0;
    > }
    >
    > Here's the project (I've tried plain C one, too): http://www.ocs.cz/
    > apps/CGEventCrash.zip
    >
    > Will be very grateful for any advice what I do wrong...
    > ---
    > Ondra ÄŒada
    > OCSoftware:    <ocs...>              http://www.ocs.cz
    > private        <ondra...>            http://www.ocs.cz/oc
    >
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/<dev...>
    >
    > This email sent to <dev...>
    >
  • On Oct 4, 2006, at 4:56 AM, Ondra Cada wrote:

    > Hi all,
    >
    > anybody can use CGEventCreateKeyboardEvent?
    >
    > I create the simplest project possible. Call the function exactly
    > the way it's documented. And always got a nice small SIGBUS...
    >
    > Here's my source:
    >
    > int main (int argc, const char * argv[]) {
    > NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    > // insert code here...
    > NSLog(@"Hello, Apple World! What's there with them blasted
    > events?!?");
    > CGEventRef er=CGEventCreateKeyboardEvent (NULL, (CGKeyCode)56,
    > true); // directly from docs
    > NSLog(@"actually, got event ref at %x. Bye.",er);
    > [pool release];
    > return 0;
    > }

    The problem is that CGEventCreateKeyboardEvent is supposed to use the
    default event source if you pass NULL for the first param, but a bug
    in the Tiger implementation caused it to not initialize the default
    source soon enough and so it crashed when attempting to use it. This
    has been fixed in Leopard. The recommended workaround is to call
    CFRelease(CGEventCreate(NULL)) before calling the other APIs.

    -eric
  • Eric,

    On 4.10.2006, at 16:37, Eric Schlegel wrote:

    > The recommended workaround is to call CFRelease(CGEventCreate
    > (NULL)) before calling the other APIs

    thanks a lot.

    Well... now it does not crash, but it does not seem to do anything
    else, either. May I please ask for a bit more advice what am I
    overlooking? I would think the following code should hide iTunes; it
    does not though -- regardless the value of wait I try:

    #import <Foundation/Foundation.h>
    #import <unistd.h> // usleep

    int main (int argc, const char * argv[]) {
        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
        // insert code here...
        NSLog(@"Hello, Apple World! What's there with them blasted
    events?!?");
        CFRelease(CGEventCreate(NULL));
        // find iTunes
        ProcessSerialNumber serial;
        serial.highLongOfPSN=0;
        serial.lowLongOfPSN=kNoProcess;
        ProcessInfoRec pinfo;
        pinfo.processInfoLength=sizeof(ProcessInfoRec);
        pinfo.processName=NULL;
        pinfo.processAppSpec=NULL;
        pinfo.processLocation=NULL;
        BOOL ok=NO;
        for (;;) {
            if (GetNextProcess(&serial)!=noErr) break; // found nothing
            if (GetProcessInformation(&serial,&pinfo)==noErr) // 'hook'
    is iTunes
                if ([(id)UTCreateStringForOSType(pinfo.processSignature)
    isEqualToString:@"hook"]) {
                    ok=YES;
                    break;
                }
        }
        if (ok) { // just hide it, for the moment
            unsigned wait=100000;
            NSLog(@"allright, sending...");
            CGEventPostToPSN(&serial,CGEventCreateKeyboardEvent (NULL,
    (CGKeyCode)0x37, true)); // command
            usleep(wait);
            CGEventPostToPSN(&serial,CGEventCreateKeyboardEvent (NULL,
    (CGKeyCode)0x04, true)); // h
            usleep(wait);
            CGEventPostToPSN(&serial,CGEventCreateKeyboardEvent (NULL,
    (CGKeyCode)0x04, false));
            usleep(wait);
            CGEventPostToPSN(&serial,CGEventCreateKeyboardEvent (NULL,
    (CGKeyCode)0x37, false));
            NSLog(@"sent all");
        }
        [pool release];
        return 0;
    }

    Thanks a lot in advance,
    ---
    Ondra ÄŒada
    OCSoftware:    <ocs...>              http://www.ocs.cz
    private        <ondra...>            http://www.ocs.cz/oc
  • Ondra, there's a better way.
    http://developer.apple.com/documentation/Carbon/Reference/
    Process_Manager/Reference/reference.html#//apple_ref/c/func/
    ShowHideProcess

    On Oct 4, 2006, at 9:27 AM, Ondra Cada wrote:

    > Eric,
    >
    > On 4.10.2006, at 16:37, Eric Schlegel wrote:
    >
    >> The recommended workaround is to call CFRelease(CGEventCreate
    >> (NULL)) before calling the other APIs
    >
    > thanks a lot.
    >
    > Well... now it does not crash, but it does not seem to do anything
    > else, either. May I please ask for a bit more advice what am I
    > overlooking? I would think the following code should hide iTunes;
    > it does not though -- regardless the value of wait I try:
    >
    > #import <Foundation/Foundation.h>
    > #import <unistd.h> // usleep
    >
    > int main (int argc, const char * argv[]) {
    > NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    > // insert code here...
    > NSLog(@"Hello, Apple World! What's there with them blasted
    > events?!?");
    > CFRelease(CGEventCreate(NULL));
    > // find iTunes
    > ProcessSerialNumber serial;
    > serial.highLongOfPSN=0;
    > serial.lowLongOfPSN=kNoProcess;
    > ProcessInfoRec pinfo;
    > pinfo.processInfoLength=sizeof(ProcessInfoRec);
    > pinfo.processName=NULL;
    > pinfo.processAppSpec=NULL;
    > pinfo.processLocation=NULL;
    > BOOL ok=NO;
    > for (;;) {
    > if (GetNextProcess(&serial)!=noErr) break; // found nothing
    > if (GetProcessInformation(&serial,&pinfo)==noErr) // 'hook'
    > is iTunes
    > if ([(id)UTCreateStringForOSType
    > (pinfo.processSignature) isEqualToString:@"hook"]) {
    > ok=YES;
    > break;
    > }
    > }
    > if (ok) { // just hide it, for the moment
    > unsigned wait=100000;
    > NSLog(@"allright, sending...");
    > CGEventPostToPSN(&serial,CGEventCreateKeyboardEvent (NULL,
    > (CGKeyCode)0x37, true)); // command
    > usleep(wait);
    > CGEventPostToPSN(&serial,CGEventCreateKeyboardEvent (NULL,
    > (CGKeyCode)0x04, true)); // h
    > usleep(wait);
    > CGEventPostToPSN(&serial,CGEventCreateKeyboardEvent (NULL,
    > (CGKeyCode)0x04, false));
    > usleep(wait);
    > CGEventPostToPSN(&serial,CGEventCreateKeyboardEvent (NULL,
    > (CGKeyCode)0x37, false));
    > NSLog(@"sent all");
    > }
    > [pool release];
    > return 0;
    > }
    >
    > Thanks a lot in advance,
    > ---
    > Ondra ÄŒada
    > OCSoftware:    <ocs...>              http://www.ocs.cz
    > private        <ondra...>            http://www.ocs.cz/oc
    >
    >
    > _______________________________________________
    > Do not post admin requests to the list. They will be ignored.
    > Cocoa-dev mailing list      (<Cocoa-dev...>)
    > Help/Unsubscribe/Update your Subscription:
    > http://lists.apple.com/mailman/options/cocoa-dev/jstiles%
    > 40blizzard.com
    >
    > This email sent to <jstiles...>
  • John,

    On 4.10.2006, at 18:50, John Stiles wrote:

    > Ondra, there's a better way.
    > http://developer.apple.com/documentation/Carbon/Reference/
    > Process_Manager/Reference/reference.html#//apple_ref/c/func/
    > ShowHideProcess

    definitely, sorry I haven't made it clean: the Cmd-h is just the
    simplest test I have been able to make up. The real goal is much more
    comprehensive control of the application though :) -- generally I
    need to send both keyboard and mouse events at will.

    Which, alas, so far does not work at all, whatever I try :/
    ---
    Ondra ÄŒada
    OCSoftware:    <ocs...>              http://www.ocs.cz
    private        <ondra...>            http://www.ocs.cz/oc
  • On Oct 4, 2006, at 11:27 AM, Ondra Cada wrote:

    > On 4.10.2006, at 16:37, Eric Schlegel wrote:
    >
    >> The recommended workaround is to call CFRelease(CGEventCreate
    >> (NULL)) before calling the other APIs
    >
    > thanks a lot.
    >
    > Well... now it does not crash, but it does not seem to do anything
    > else, either. May I please ask for a bit more advice what am I
    > overlooking? I would think the following code should hide iTunes;
    > it does not though -- regardless the value of wait I try:

    I think that I was unable to get events created with the default
    source to work, but had success when I created and used a private
    source:

    /* psn holds target's PSN, code is keycode to send, state is up/down */
    CGEventSourceRef source = CGEventSourceCreate
    (kCGEventSourceStatePrivate);
    CGEventRef ev = CGEventCreateKeyboardEvent(source, code, state);
    CGEventPostToPSN(&psn, ev);

    -Greg
previous month october 2006 next month
MTWTFSS
            1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31          
Go to today