views:

1004

answers:

3

I have a very simple chunk of code that is designed to simulate keyboard events. The simple example below should type "Cz" - the shift key goes down, the c key goes down, c comes up and shift comes up. Then the z key goes down and up.

It seems that sometimes the order gets muddled though. When I create a timer to call this routine every second, the output should be CzCzCzCz.... But here's what I get:

CZcZCZCzczCzczCzczCZCZCzCz

I'll run it again:

CzCzCzCzCZCzCZCzCZCzCZCzCZCzCzCz

Different. And equally wrong.

The code:

e1 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)56, true);
CGEventPost(kCGSessionEventTap, e1);
CFRelease(e1);
e2 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, true);
CGEventPost(kCGSessionEventTap, e2);
CFRelease(e2);
e3 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, false);
CGEventPost(kCGSessionEventTap, e3);
CFRelease(e3);
e4 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)56, false);
CGEventPost(kCGSessionEventTap, e4);
CFRelease(e4);

e7 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)6, true);
CGEventPost(kCGSessionEventTap, e7);
CFRelease(e7);
e8 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)6, false);
CGEventPost(kCGSessionEventTap, e8);
CFRelease(e8);

Is there something I'm missing in how to implement the keydown and keyup for the shift key? I think this might be a bug - where would I report it?

A: 

Any relation to this guy's bug?

Preston
YES! Wish I could get in touch with him.
Ben Packard
Why get in touch with him? His solution is right there in that message.
Peter Hosey
Well he has a decent workaround, but I want to know if this is a genuine bug or I (and he) were doing something wrong.
Ben Packard
No, he doesn't just have a workaround. He explained in his message exactly was wrong in his app.
Peter Hosey
Ok, that's not how I understand it though. To create a MPQueue, event taps and stick user info on to events to get expected behaviour is, to me, a workaround rather than a problem with his App. In fact Apple have confirmed this is a bug.
Ben Packard
PS - I think perhaps you only read his first follow up - he swiftly replied, retracting his App problem and restated his problem. Then followed a third time with the workaround I mentioned.Here is the retraction:http://lists.apple.com/archives/quartz-dev/2009/Oct/msg00086.htmlAnd here is the restatement:http://lists.apple.com/archives/quartz-dev/2009/Oct/msg00087.html
Ben Packard
+4  A: 

I have found a reliable way to post modified keyboard events - it does not follow the example in Apple's documentation (which doesn't work) but seems to make sense, and most importantly, WORKS.

Rather than sending 'shift key down' and 'shift key up' messages (as instructed in the docs), you need to set a modifier flag on the keypress. Here's how to output an uppercase Z.

CGEventRef event1, event2;
event1 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)6, true);//'z' keydown event
CGEventSetFlags(event1, kCGEventFlagMaskShift);//set shift key down for above event
CGEventPost(kCGSessionEventTap, event1);//post event

I'm then releasing the 'z' key for completeness (also setting the shift-flag on, though not sure if this is correct).

event2 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)6, false);
CGEventSetFlags(event2, kCGEventFlagMaskShift);
CGEventPost(kCGSessionEventTap, event2);

Finally (and bizarrely) you DO need to send the 'key up' event for the shift key:

  e5 = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)56, false);
CGEventPost(kCGSessionEventTap, e5);

Don't forget to release your events once you're done with them.

I hope this is useful to someone - it took me a long time to get this to work.

Ben Packard
I gave a minus 1... this doesn't work. It works to type a capital letter, but follow that capital letter up with a small letter and the capital letter types again. Tried it a million ways and no go.
regulus6633
A: 

Synergy-plus (http://code.google.com/p/synergy-plus/) seems to be affect by this same issue as of 10.6.3. I was able to code a work-around using your method. (Thanks Ben!)

jason.e.reynolds