diff --git a/ChangeLog b/ChangeLog index 194889bff..8668ef0c5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +v1.14.3-snapshot +=========== +Bug fixes: +- #7135 Fix issue with function keys on macOS +=========== + v1.14.2-stable =========== Bug fixes: diff --git a/cmake/Version.cmake b/cmake/Version.cmake index dff192e51..d580ceee7 100644 --- a/cmake/Version.cmake +++ b/cmake/Version.cmake @@ -6,9 +6,9 @@ cmake_minimum_required (VERSION 3.4) set (SYNERGY_VERSION_MAJOR 1) set (SYNERGY_VERSION_MINOR 14) -set (SYNERGY_VERSION_PATCH 2) +set (SYNERGY_VERSION_PATCH 3) set (SYNERGY_VERSION_BUILD 1) -set (SYNERGY_VERSION_STAGE "stable") +set (SYNERGY_VERSION_STAGE "snapshot") # # Version from CI diff --git a/src/lib/platform/OSXKeyState.cpp b/src/lib/platform/OSXKeyState.cpp index aa7ee6ede..5b614845c 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 @@ -129,6 +130,65 @@ static const KeyEntry s_controlKeys[] = { { kKeyBrightnessDown, s_brightnessDown } }; +namespace { + +io_connect_t +getService(io_iterator_t iter) { + io_connect_t service = 0; + auto nextIterator = IOIteratorNext(iter); + + if (nextIterator) { + IOServiceOpen(nextIterator, mach_task_self(), kIOHIDParamConnectType, &service); + IOObjectRelease(nextIterator); + } + + return service; +} + +io_connect_t +getEventDriver() +{ + static io_connect_t sEventDrvrRef = 0; + + if (!sEventDrvrRef) { + // Get master device port + mach_port_t masterPort = 0; + if (!IOMasterPort(bootstrap_port, &masterPort)) { + io_iterator_t iter = 0; + auto dict = IOServiceMatching(kIOHIDSystemClass); + + if (!IOServiceGetMatchingServices(masterPort, dict, &iter)) { + sEventDrvrRef = getService(iter); + } + else { + LOG((CLOG_WARN, "IOService not found")); + } + + IOObjectRelease(iter); + } + else { + LOG((CLOG_WARN, "Couldn't obtain IO master port")); + } + } + + return sEventDrvrRef; +} + +bool +isModifier(UInt8 virtualKey) { + static std::set modifiers { + s_shiftVK, + s_superVK, + s_altVK, + s_controlVK, + s_capsLockVK + }; + + return (modifiers.find(virtualKey) != modifiers.end()); +} + +} //namespace + // // OSXKeyState @@ -336,26 +396,26 @@ OSXKeyState::fakeCtrlAltDel() bool OSXKeyState::fakeMediaKey(KeyID id) { - return fakeNativeMediaKey(id);; + return fakeNativeMediaKey(id); } CGEventFlags -OSXKeyState::getModifierStateAsOSXFlags() +OSXKeyState::getModifierStateAsOSXFlags() const { CGEventFlags modifiers = 0; - + if (m_shiftPressed) { modifiers |= kCGEventFlagMaskShift; } - + if (m_controlPressed) { modifiers |= kCGEventFlagMaskControl; } - + if (m_altPressed) { modifiers |= kCGEventFlagMaskAlternate; } - + if (m_superPressed) { modifiers |= kCGEventFlagMaskCommand; } @@ -363,7 +423,7 @@ OSXKeyState::getModifierStateAsOSXFlags() if (m_capsPressed) { modifiers |= kCGEventFlagMaskAlphaShift; } - + return modifiers; } @@ -476,30 +536,6 @@ OSXKeyState::getKeyMap(synergy::KeyMap& keyMap) } } -CGEventFlags -OSXKeyState::getDeviceIndependedFlags() const -{ - CGEventFlags modifiers = 0; - - if (m_shiftPressed) { - modifiers |= kCGEventFlagMaskShift; - } - - if (m_controlPressed) { - modifiers |= kCGEventFlagMaskControl; - } - - if (m_altPressed) { - modifiers |= kCGEventFlagMaskAlternate; - } - - if (m_superPressed) { - modifiers |= kCGEventFlagMaskCommand; - } - - return modifiers; -} - CGEventFlags OSXKeyState::getDeviceDependedFlags() const { @@ -530,12 +566,9 @@ OSXKeyState::getKeyboardEventFlags() const { // set the event flags for special keys // http://tinyurl.com/pxl742y - CGEventFlags modifiers = getDeviceIndependedFlags(); + CGEventFlags modifiers = getModifierStateAsOSXFlags(); - if (m_capsPressed) { - modifiers |= kCGEventFlagMaskAlphaShift; - } - else { + if (!m_capsPressed) { modifiers |= getDeviceDependedFlags(); } @@ -567,7 +600,30 @@ OSXKeyState::setKeyboardModifiers(CGKeyCode virtualKey, bool keyDown) } } -void +kern_return_t +OSXKeyState::postHIDVirtualKey(UInt8 virtualKey, bool postDown) +{ + NXEventData event; + bzero(&event, sizeof(NXEventData)); + auto driver = getEventDriver(); + kern_return_t result = KERN_FAILURE; + + if (driver) { + if (isModifier(virtualKey)) { + result = IOHIDPostEvent(driver, NX_FLAGSCHANGED, {0,0}, &event, kNXEventDataVersion, getKeyboardEventFlags(), true); + } + else { + event.key.keyCode = virtualKey; + const auto eventType = postDown ? NX_KEYDOWN : NX_KEYUP; + result = IOHIDPostEvent(driver, eventType, {0,0}, &event, kNXEventDataVersion, 0, false); + } + + } + + return result; +} + +void OSXKeyState::postKeyboardKey(CGKeyCode virtualKey, bool keyDown) { CGEventRef event = CGEventCreateKeyboardEvent(nullptr, virtualKey, keyDown); @@ -596,7 +652,11 @@ OSXKeyState::fakeKey(const Keystroke& keystroke) button, virtualKey, keyDown ? "down" : "up", client)); setKeyboardModifiers(virtualKey, keyDown); - postKeyboardKey(virtualKey, keyDown); + if (postHIDVirtualKey(virtualKey, keyDown) != KERN_SUCCESS) { + LOG((CLOG_WARN, "Fail to post HID event")); + postKeyboardKey(virtualKey, keyDown); + } + break; } diff --git a/src/lib/platform/OSXKeyState.h b/src/lib/platform/OSXKeyState.h index 00f8e53ac..92ac7217c 100644 --- a/src/lib/platform/OSXKeyState.h +++ b/src/lib/platform/OSXKeyState.h @@ -99,7 +99,7 @@ public: virtual SInt32 pollActiveGroup() const; virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const; - CGEventFlags getModifierStateAsOSXFlags(); + CGEventFlags getModifierStateAsOSXFlags() const; protected: // KeyState overrides virtual void getKeyMap(synergy::KeyMap& keyMap); @@ -151,9 +151,13 @@ private: 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 + kern_return_t postHIDVirtualKey(UInt8 virtualKeyCode, bool postDown); + // Get keyboard event flags accorfing to keyboard modifiers CGEventFlags getKeyboardEventFlags() const; - CGEventFlags getDeviceIndependedFlags() const; CGEventFlags getDeviceDependedFlags() const; void setKeyboardModifiers(CGKeyCode virtualKey, bool keyDown);