diff --git a/ChangeLog b/ChangeLog index 260b45a73..e170a8ac4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,7 @@ Bug fixes: Enhancements: - #7068 Add Synergy restart when settings changed +- #7072 Ability to run synergy as a pre-login agent =========== v1.14.1-rc diff --git a/src/lib/platform/OSXKeyState.cpp b/src/lib/platform/OSXKeyState.cpp index f000a4cc1..35bf35f40 100644 --- a/src/lib/platform/OSXKeyState.cpp +++ b/src/lib/platform/OSXKeyState.cpp @@ -23,7 +23,6 @@ #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 @@ -476,102 +475,72 @@ OSXKeyState::getKeyMap(synergy::KeyMap& keyMap) } } -static io_connect_t getEventDriver(void) +CGEventFlags +OSXKeyState::getKeyboardEventFlags() { - 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); + // set the event flags for special keys + // http://tinyurl.com/pxl742y + CGEventFlags modifiers = 0; - IOObjectRelease(service); - IOObjectRelease(iter); + if (m_shiftPressed) { + modifiers |= kCGEventFlagMaskShift; } - - return sEventDrvrRef; + + if (m_controlPressed) { + modifiers |= kCGEventFlagMaskControl; + } + + if (m_altPressed) { + modifiers |= kCGEventFlagMaskAlternate; + } + + if (m_superPressed) { + modifiers |= kCGEventFlagMaskCommand; + } + + if (m_capsPressed) { + modifiers |= kCGEventFlagMaskAlphaShift; + } + + return modifiers; } -void -OSXKeyState::postHIDVirtualKey(const UInt8 virtualKeyCode, - const bool postDown) +void +OSXKeyState::setKeyboardModifiers(CGKeyCode virtualKey, bool keyDown) { - 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) - { + switch(virtualKey) { 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; + m_shiftPressed = keyDown; + break; case s_controlVK: - modifiersDelta = NX_CONTROLMASK; - m_controlPressed = postDown; - break; + m_controlPressed = keyDown; + break; + case s_altVK: + m_altPressed = keyDown; + break; + case s_superVK: + m_superPressed = keyDown; + 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; + m_capsPressed = keyDown; + break; + default: + LOG((CLOG_DEBUG1 "The key is not a modifier")); + 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::postKeyboardKey(CGKeyCode virtualKey, bool keyDown) +{ + CGEventRef event = CGEventCreateKeyboardEvent(nullptr, virtualKey, keyDown); + if (event) { + CGEventSetFlags(event, getKeyboardEventFlags()); + CGEventPost(kCGHIDEventTap, event); + CFRelease(event); + } + else { + LOG((CLOG_CRIT "unable to create keyboard event for keystroke")); } } @@ -579,33 +548,33 @@ void OSXKeyState::fakeKey(const Keystroke& keystroke) { switch (keystroke.m_type) { - case Keystroke::kButton: { - - KeyButton button = keystroke.m_data.m_button.m_button; - bool keyDown = keystroke.m_data.m_button.m_press; - CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button); - - LOG((CLOG_DEBUG1 - " button=0x%04x virtualKey=0x%04x keyDown=%s", - button, virtualKey, keyDown ? "down" : "up")); + case Keystroke::kButton: { + bool keyDown = keystroke.m_data.m_button.m_press; + UInt32 client = keystroke.m_data.m_button.m_client; + KeyButton button = keystroke.m_data.m_button.m_button; + CGKeyCode virtualKey = mapKeyButtonToVirtualKey(button); - postHIDVirtualKey(virtualKey, keyDown); + LOG((CLOG_DEBUG1 + " button=0x%04x virtualKey=0x%04x keyDown=%s client=0x%04x", + button, virtualKey, keyDown ? "down" : "up", client)); - break; - } - - case Keystroke::kGroup: { - SInt32 group = keystroke.m_data.m_group.m_group; - if (keystroke.m_data.m_group.m_absolute) { - LOG((CLOG_DEBUG1 " group %d", group)); - setGroup(group); + setKeyboardModifiers(virtualKey, keyDown); + postKeyboardKey(virtualKey, keyDown); + break; } - else { - LOG((CLOG_DEBUG1 " group %+d", group)); - setGroup(getEffectiveGroup(pollActiveGroup(), group)); + + case Keystroke::kGroup: { + SInt32 group = keystroke.m_data.m_group.m_group; + if (keystroke.m_data.m_group.m_absolute) { + LOG((CLOG_DEBUG1 " group %d", group)); + setGroup(group); + } + else { + LOG((CLOG_DEBUG1 " group %+d", group)); + setGroup(getEffectiveGroup(pollActiveGroup(), group)); + } + break; } - break; - } } } diff --git a/src/lib/platform/OSXKeyState.h b/src/lib/platform/OSXKeyState.h index a6277dfd2..14b0e680b 100644 --- a/src/lib/platform/OSXKeyState.h +++ b/src/lib/platform/OSXKeyState.h @@ -149,12 +149,13 @@ 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); + + // Get keyboard event flags accorfing to keyboard modifiers + CGEventFlags getKeyboardEventFlags(); + + void setKeyboardModifiers(CGKeyCode virtualKey, bool keyDown); + + void postKeyboardKey(CGKeyCode virtualKey, bool keyDown); private: // OS X uses a physical key if 0 for the 'A' key. synergy reserves diff --git a/src/lib/platform/OSXScreen.mm b/src/lib/platform/OSXScreen.mm index e7a7048c7..afb28d263 100644 --- a/src/lib/platform/OSXScreen.mm +++ b/src/lib/platform/OSXScreen.mm @@ -48,6 +48,14 @@ #include #include +// The following creates a section that tells Mac OS X +// that it is OK to let us inject input in the login screen. +// Just the name of the section is important, not its contents. +__attribute__((used)) +__attribute__((section ("__CGPreLoginApp,__cgpreloginapp"))) +static const char magic_section[] = ""; +//////////////////////////////////////////////////////////// + // This isn't in any Apple SDK that I know of as of yet. enum { kSynergyEventMouseScroll = 11, @@ -792,16 +800,18 @@ OSXScreen::enable() this); } - if (!m_eventTapPort) { + if (m_eventTapPort) { + m_eventTapRLSR = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPort, 0); + if (m_eventTapRLSR) { + CFRunLoopAddSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode); + } + else{ + LOG((CLOG_ERR "failed to create a CFRunLoopSourceRef for the quartz event tap")); + } + } + else{ LOG((CLOG_ERR "failed to create quartz event tap")); } - - m_eventTapRLSR = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, m_eventTapPort, 0); - if (!m_eventTapRLSR) { - LOG((CLOG_ERR "failed to create a CFRunLoopSourceRef for the quartz event tap")); - } - - CFRunLoopAddSource(CFRunLoopGetCurrent(), m_eventTapRLSR, kCFRunLoopDefaultMode); } void