Skip to content

Commit

Permalink
SYNERGY-1397 MacOS function keys (deskflow#7135)
Browse files Browse the repository at this point in the history
* SYNERGY-1397 MacOS function keys

* SYNERGY-1397 Update ChangeLog and version number

* SYNERGY-1397 Remove extra comment

* SYNERGY-1397 Remove assertions

* SYNERGY-1397 Change log level to warning
  • Loading branch information
SerhiiGadzhilov authored Jan 13, 2022
1 parent c6918b7 commit dc72af7
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 42 deletions.
6 changes: 6 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
v1.14.3-snapshot
===========
Bug fixes:
- #7135 Fix issue with function keys on macOS
===========

v1.14.2-stable
===========
Bug fixes:
Expand Down
4 changes: 2 additions & 2 deletions cmake/Version.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
136 changes: 98 additions & 38 deletions src/lib/platform/OSXKeyState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include "base/Log.h"

#include <Carbon/Carbon.h>
#include <IOKit/hidsystem/IOHIDLib.h>

// Note that some virtual keys codes appear more than once. The
// first instance of a virtual key code maps to the KeyID that we
Expand Down Expand Up @@ -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<UInt8> modifiers {
s_shiftVK,
s_superVK,
s_altVK,
s_controlVK,
s_capsLockVK
};

return (modifiers.find(virtualKey) != modifiers.end());
}

} //namespace


//
// OSXKeyState
Expand Down Expand Up @@ -336,34 +396,34 @@ 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;
}

if (m_capsPressed) {
modifiers |= kCGEventFlagMaskAlphaShift;
}

return modifiers;
}

Expand Down Expand Up @@ -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
{
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down
8 changes: 6 additions & 2 deletions src/lib/platform/OSXKeyState.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class OSXKeyState : public KeyState {
virtual SInt32 pollActiveGroup() const;
virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const;

CGEventFlags getModifierStateAsOSXFlags();
CGEventFlags getModifierStateAsOSXFlags() const;
protected:
// KeyState overrides
virtual void getKeyMap(synergy::KeyMap& keyMap);
Expand Down Expand Up @@ -151,9 +151,13 @@ class OSXKeyState : public KeyState {

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);
Expand Down

0 comments on commit dc72af7

Please sign in to comment.