diff --git a/src/lib/platform/OSXKeyState.cpp b/src/lib/platform/OSXKeyState.cpp index 2071621b..8ab0bc89 100644 --- a/src/lib/platform/OSXKeyState.cpp +++ b/src/lib/platform/OSXKeyState.cpp @@ -23,6 +23,7 @@ #include "base/Log.h" #include +#include // Note that some virtual keys codes appear more than once. The // first instance of a virtual key code maps to the KeyID that we @@ -469,6 +470,105 @@ OSXKeyState::getKeyMap(synergy::KeyMap& keyMap) } } +static io_connect_t getEventDriver(void) +{ + static mach_port_t sEventDrvrRef = 0; + mach_port_t masterPort, service, iter; + kern_return_t kr; + + if (!sEventDrvrRef) { + // Get master device port + kr = IOMasterPort(bootstrap_port, &masterPort); + assert(KERN_SUCCESS == kr); + + kr = IOServiceGetMatchingServices(masterPort, + IOServiceMatching(kIOHIDSystemClass), &iter); + assert(KERN_SUCCESS == kr); + + service = IOIteratorNext(iter); + assert(service); + + kr = IOServiceOpen(service, mach_task_self(), + kIOHIDParamConnectType, &sEventDrvrRef); + assert(KERN_SUCCESS == kr); + + IOObjectRelease(service); + IOObjectRelease(iter); + } + + return sEventDrvrRef; +} + +void +OSXKeyState::postHIDVirtualKey(const UInt8 virtualKeyCode, + const bool postDown) +{ + static UInt32 modifiers = 0; + + NXEventData event; + IOGPoint loc = { 0, 0 }; + UInt32 modifiersDelta = 0; + + bzero(&event, sizeof(NXEventData)); + + switch (virtualKeyCode) + { + case s_shiftVK: + case s_superVK: + case s_altVK: + case s_controlVK: + case s_capsLockVK: + switch (virtualKeyCode) + { + case s_shiftVK: + modifiersDelta = NX_SHIFTMASK; + m_shiftPressed = postDown; + break; + case s_superVK: + modifiersDelta = NX_COMMANDMASK; + m_superPressed = postDown; + break; + case s_altVK: + modifiersDelta = NX_ALTERNATEMASK; + m_altPressed = postDown; + break; + case s_controlVK: + modifiersDelta = NX_CONTROLMASK; + m_controlPressed = postDown; + break; + case s_capsLockVK: + modifiersDelta = NX_ALPHASHIFTMASK; + m_capsPressed = postDown; + break; + } + + // update the modifier bit + if (postDown) { + modifiers |= modifiersDelta; + } + else { + modifiers &= ~modifiersDelta; + } + + kern_return_t kr; + kr = IOHIDPostEvent(getEventDriver(), NX_FLAGSCHANGED, loc, + &event, kNXEventDataVersion, modifiers, true); + assert(KERN_SUCCESS == kr); + break; + + default: + event.key.repeat = false; + event.key.keyCode = virtualKeyCode; + event.key.origCharSet = event.key.charSet = NX_ASCIISET; + event.key.origCharCode = event.key.charCode = 0; + kr = IOHIDPostEvent(getEventDriver(), + postDown ? NX_KEYDOWN : NX_KEYUP, + loc, &event, kNXEventDataVersion, 0, false); + assert(KERN_SUCCESS == kr); + break; + } +} + void OSXKeyState::fakeKey(const Keystroke& keystroke) { @@ -477,76 +577,14 @@ OSXKeyState::fakeKey(const Keystroke& keystroke) KeyButton button = keystroke.m_data.m_button.m_button; bool keyDown = keystroke.m_data.m_button.m_press; - UInt32 client = keystroke.m_data.m_button.m_client; - CGEventSourceRef source = 0; CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button); LOG((CLOG_DEBUG1 - " button=0x%04x virtualKey=0x%04x keyDown=%s client=0x%04x", - button, virtualKey, keyDown ? "down" : "up", client)); + " button=0x%04x virtualKey=0x%04x keyDown=%s", + button, virtualKey, keyDown ? "down" : "up")); - CGEventRef ref = CGEventCreateKeyboardEvent( - source, virtualKey, keyDown); - - if (ref == NULL) { - LOG((CLOG_CRIT "unable to create keyboard event for keystroke")); - return; - } + postHIDVirtualKey(virtualKey, keyDown); - // persist modifier state. - if (virtualKey == s_shiftVK) { - m_shiftPressed = keyDown; - } - - if (virtualKey == s_controlVK) { - m_controlPressed = keyDown; - } - - if (virtualKey == s_altVK) { - m_altPressed = keyDown; - } - - if (virtualKey == s_superVK) { - m_superPressed = keyDown; - } - - if (virtualKey == s_capsLockVK) { - m_capsPressed = keyDown; - } - - // set the event flags for special keys - // http://tinyurl.com/pxl742y - CGEventFlags modifiers = 0; - - if (m_shiftPressed) { - modifiers |= kCGEventFlagMaskShift; - } - - if (m_controlPressed) { - modifiers |= kCGEventFlagMaskControl; - } - - if (m_altPressed) { - modifiers |= kCGEventFlagMaskAlternate; - } - - if (m_superPressed) { - modifiers |= kCGEventFlagMaskCommand; - } - - if (m_capsPressed) { - modifiers |= kCGEventFlagMaskAlphaShift; - } - - CGEventSetFlags(ref, modifiers); - CGEventPost(kCGHIDEventTap, ref); - CFRelease(ref); - - // add a delay if client data isn't zero - // FIXME -- why? - if (client != 0) { - ARCH->sleep(0.01); - } break; } diff --git a/src/lib/platform/OSXKeyState.h b/src/lib/platform/OSXKeyState.h index 00dbb551..a3e16315 100644 --- a/src/lib/platform/OSXKeyState.h +++ b/src/lib/platform/OSXKeyState.h @@ -149,6 +149,12 @@ private: static UInt32 mapKeyButtonToVirtualKey(KeyButton keyButton); void init(); + + // Post a key event to HID manager. It posts an event to HID client, a + // much lower level than window manager which's the target from carbon + // CGEventPost + void postHIDVirtualKey(const UInt8 virtualKeyCode, + const bool postDown); private: // OS X uses a physical key if 0 for the 'A' key. synergy reserves