SYNERGY-1397 MacOS function keys (#7135)

* 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
This commit is contained in:
Serhii Hadzhilov
2022-01-13 18:58:29 +02:00
committed by GitHub
parent c6918b74cf
commit dc72af7a7b
4 changed files with 112 additions and 42 deletions

View File

@ -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
@ -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
@ -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;
}