views:

11

answers:

1

Ola Folks,

Once again I want to drink from the pool of knowledge shared by people using SO.

I have written a small app for OSX that sends key events to an application. I am targeting OSX 10.5.x and newer. However, the problem exists when I build for 10.6.x as well. Everything works fine except when I send only the modifier keys; Alt, Command, Control and Shift.

The problem is that on the two MacBooks, the events for the modifier keys appear to be cleared as soon as the testers move the cursor using the mouse or touch the touchpad.

On a desktop with XCode installed, everything works fine. Just like it should. On two different MacBooks, the problem occurs. The desktop has a standard 101 key keyboard and a multi-button mouse attached.
When a mouse is connected to the MacBooks, a two button mouse with scrollwheel is used. However, the problem exists when no peripherals are attached and the touchpad is used.

What I expect to happen is that the Modifier Key event is sent to the target application, the user moves the cursor using the mouse / touchpad, press buttons on the mouse / touchpad and/or press keys on the keyboard with the modifier key down event 'active'. Then, when they finish, the key up event for the modifier key is sent.

Here is how I am sending key down events, the Shift key for this example:

case ModKeyShiftDown:
    xEventSource = CGEventSourceCreate(kCGEventSourceStatePrivate);
    xTheCommand = CGEventCreateKeyboardEvent(xEventSource, kVK_Shift, true);
    CGEventSetFlags(xTheCommand, kCGEventFlagMaskAlternate);
    CGEventPost(kCGHIDEventTap, xTheCommand);
    //CGEventPost(kCGSessionEventTap, xTheCommand);
    //CGEventPost(kCGAnnotatedSessionEventTap, xTheCommand);
    CFRelease(xTheCommand);
    CFRelease(xEventSource);
break;

I have used all three flags for creating the event source (kCGEventSourceStatePrivate, kCGEventSourceStateCombinedSessionState and kCGEventSourceStateHIDSystemState).

I have tried Creating the Keyboard Event with the Event Source as well as null as the first parameter.

I have tried with and without the appropriate flags on the event.

I have tried various combinations of posting the event; kCGHIDEventTap, kCGSessionEventTap and kCGAnnotatedSessionEventTap.

For completeness, here is how I send an up event for the Shift key:

case ModKeyShiftUp:
    xEventSource = CGEventSourceCreate(kCGEventSourceStatePrivate);
    xTheCommand = CGEventCreateKeyboardEvent(xEventSource, kVK_Shift, false);
    CGEventSetFlags(xTheCommand, 0);
    CGEventPost(kCGHIDEventTap, xTheCommand);
    //CGEventPost(kCGSessionEventTap, xTheCommand);
    //CGEventPost(kCGAnnotatedSessionEventTap, xTheCommand);
    CFRelease(xTheCommand);
    CFRelease(xEventSource);
break;

When the testers trigger a modifier key down event, they can see the cursor change as expected. This lets me know the event is being processed by the target application. However, as soon as they touch the mouse or touchpad, the cursor changes back to a standard cursor and the mouse events are processed as if no modifier key events are active.

I would like to know if there is a problem with the way I am sending the events. I would also like to know if there is an alternate way to send Modifier Key events that is Going To Work.

Sorry if I overtalked this. My excuse is that I only slept a couple of hours. :P

Thanx

-isdi-

A: 

Ola,

Interestingly enough, using AXUIElementRef and AXUIElementPostKeyboardEvent seem to work.

For whatever reason, sending key events using the Accessibility object and method above solves the problem for the testers.

ISDi