简体   繁体   中英

Send auto-repeated key using CoreGraphics methods (Mac OS X Snow Leopard)

I have been successful sending keystrokes in order to automate a particular software package for drawing that I use. This software relies a lot of keyboard shortcuts so I wrote something that could call some of these keyboard shortcuts in order to streamline my workflow. As I said, this has worked out good.

My library is a Cocoa library that is loaded as a plugin to the software package. Here is a snippet of code that I have been using for sending my keystrokes.

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
CGEventRef eventUp = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, false);

//setting the process number somewhere else
CGEventPostToPSN(&number, eventDown);
CGEventPostToPSN(&number, eventUp);

For some procedures in the drawing package if you continue to hold the Shift key then you activate a special tool. I have been unable to simulate this. I thought I could send the Shift key and say that I wanted it to auto-repeat but that doesn't seem to work. I have been using the following code to set the auto-repeat:

//This is done before sending the key
CGEventSetIntegerValueField(eventDown, kCGKeyboardEventAutorepeat, 1);

In my testing I have been unable to make any key auto-repeat. It just send the key once and that is it.

Is there anyone that have been successful autorepeating a key using the above method? I have searched the Internet for answers but all I have found are some unanswered questions from 2008... Any help is greatly appreciated.

Thanks,

mobbe

UPDATE: the Shift key's code isn't 56 , according to Events.h:

...
kVK_Shift                     = 0x38,
...

(EDIT: of course those of you who are paying attention (I wasn't) realize that HEX 38 == DEC 56.)

I also realized how to get modifier key presses: flagsChanged: . So using this keycode, I can catch Shift key presses in flagsChanged: , and the repeat works fine; I also get repeated key events for "normal" keys in keyDown: and keyUp: without difficulty.

It sounds like you may not have access to/want to change the event-handling code (to add flagsChanged: ) though, so if that keycode doesn't work for you, I'm stumped and can only say "Good luck!"


I believe that the field you're setting is used to indicate not that the event should be repeated by the system, but that an event is an auto-repeat of a previous event. You still have to generate each event yourself. Something like (EDITED to use a timer instead of a loop):

CGEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
// Post the initial keydown
CGEventPostToPSN(&pidNumber, eventDown);

// Keep track of how many Shift keydown events have been sent
shiftKeyRepeatCount = 1;
[NSTimer scheduledTimerWithTimeInterval:0.3    // I don't know exactly what the interval should be, of course
                                 target:self
                               selector:@selector(repeatShiftKeyDown:)
                               userInfo:nil
                                repeats:YES];

CFRelease(eventDown);

- (void)repeatShiftKeyDown:(NSTimer *)tim {
    if( shiftKeyRepeatCount >= kRepeatCountForSpecialTool ){
        [tim invalidate];
        [self sendShiftKeyUp];
        return;
    }
    shiftKeyRepeatCount++;
    GEventSourceRef eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
    CGEventRef eventDown = CGEventCreateKeyboardEvent(eventSource, (CGKeyCode)1, true);
    // Set the auto-repeat field
    CGEventSetIntegerValueField(eventDown, kCGKeyboardEventAutorepeat, 1);
    CGEventPostToPSN(&pidNumber, eventDown);
    CFRelease(eventDown);
}

I'm not certain whether you can reuse the first event with a changed field or you'll need to generate a new event to use when repeating.

The code that OP finally came up with to solve the problem (transferred here from a comment under other answer):

CGEventRef flagsChanged = CGEventCreate(eventSource); 
CGEventSetType(flagsChanged, kCGEventFlagsChanged); 
CGEventSetIntegerValueField(flagsChanged, kCGKeyboardEventKeycode, 56);     
CGEventSetFlags(flagsChanged, 131330); 
CGEventPostToPSN(&number, flagsChanged); 
CFRelease(flagsChanged); CFRelease(eventSource);

131330 is a constant indicating the Shift key; it is related to NSShiftKeyMask and kCGEventFlagMaskShift , which are 131072 ( 0x00020000 ). 131330 - 256 - 2 == 131072 .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM