From 9115d5570bcf85e68b8ffd9819359e44f8c4999d Mon Sep 17 00:00:00 2001 From: "Jerry (Xinyu Hou)" Date: Thu, 16 Jun 2016 15:18:31 +0000 Subject: [PATCH] #3305 Used Mac native way to simulate media keys --- src/lib/platform/OSXKeyState.cpp | 7 ++ src/lib/platform/OSXKeyState.h | 1 + src/lib/platform/OSXMediaKeySimulator.h | 30 ++++++++ src/lib/platform/OSXMediaKeySimulator.m | 84 ++++++++++++++++++++++ src/lib/synergy/IKeyState.h | 9 ++- src/lib/synergy/IPlatformScreen.cpp | 24 +++++++ src/lib/synergy/IPlatformScreen.h | 1 + src/lib/synergy/KeyState.cpp | 10 +++ src/lib/synergy/KeyState.h | 2 + src/lib/synergy/key_types.h | 8 +-- src/test/unittests/synergy/KeyStateTests.h | 1 + 11 files changed, 171 insertions(+), 6 deletions(-) create mode 100644 src/lib/platform/OSXMediaKeySimulator.h create mode 100644 src/lib/platform/OSXMediaKeySimulator.m create mode 100644 src/lib/synergy/IPlatformScreen.cpp diff --git a/src/lib/platform/OSXKeyState.cpp b/src/lib/platform/OSXKeyState.cpp index 9f3d923f..03d5d54e 100644 --- a/src/lib/platform/OSXKeyState.cpp +++ b/src/lib/platform/OSXKeyState.cpp @@ -18,6 +18,7 @@ #include "platform/OSXKeyState.h" #include "platform/OSXUchrKeyResource.h" +#include "platform/OSXMediaKeySimulator.h" #include "arch/Arch.h" #include "base/Log.h" @@ -316,6 +317,12 @@ OSXKeyState::fakeCtrlAltDel() return false; } +bool +COSXKeyState::fakeMediaKey(KeyID id) +{ + return fakeNativeMediaKey(id);; +} + CGEventFlags OSXKeyState::getModifierStateAsOSXFlags() { diff --git a/src/lib/platform/OSXKeyState.h b/src/lib/platform/OSXKeyState.h index 29cd5d6c..2aaffc47 100644 --- a/src/lib/platform/OSXKeyState.h +++ b/src/lib/platform/OSXKeyState.h @@ -92,6 +92,7 @@ public: // IKeyState overrides virtual bool fakeCtrlAltDel(); + virtual bool fakeMediaKey(KeyID id); virtual KeyModifierMask pollActiveModifiers() const; virtual SInt32 pollActiveGroup() const; diff --git a/src/lib/platform/OSXMediaKeySimulator.h b/src/lib/platform/OSXMediaKeySimulator.h new file mode 100644 index 00000000..277778df --- /dev/null +++ b/src/lib/platform/OSXMediaKeySimulator.h @@ -0,0 +1,30 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2016 Symless. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#import + +#include "synergy/key_types.h" + +#if defined(__cplusplus) +extern "C" { +#endif +bool fakeNativeMediaKey(KeyID id); +#if defined(__cplusplus) +} +#endif diff --git a/src/lib/platform/OSXMediaKeySimulator.m b/src/lib/platform/OSXMediaKeySimulator.m new file mode 100644 index 00000000..b7d243f6 --- /dev/null +++ b/src/lib/platform/OSXMediaKeySimulator.m @@ -0,0 +1,84 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2016 Symless. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#import "platform/OSXMediaKeySimulator.h" + +#import + +int convertKeyIDToNXKeyType(KeyID id) +{ + // hidsystem/ev_keymap.h + // NX_KEYTYPE_SOUND_UP 0 + // NX_KEYTYPE_SOUND_DOWN 1 + // NX_KEYTYPE_MUTE 7 + // NX_KEYTYPE_EJECT 14 + // NX_KEYTYPE_PLAY 16 + // NX_KEYTYPE_NEXT 17 + // NX_KEYTYPE_PREVIOUS 18 + // NX_KEYTYPE_FAST 19 + // NX_KEYTYPE_REWIND 20 + + int type = -1; + switch (id) { + case kKeyAudioUp: + type = 0; + break; + case kKeyAudioDown: + type = 1; + break; + case kKeyAudioMute: + type = 7; + break; + case kKeyEject: + type = 14; + break; + case kKeyAudioPlay: + type = 16; + break; + case kKeyAudioNext: + type = 17; + break; + case kKeyAudioPrev: + type = 18; + break; + default: + break; + } + + return type; +} + +bool +fakeNativeMediaKey(KeyID id) +{ + + NSEvent* downRef = [NSEvent otherEventWithType:NSSystemDefined + location: NSMakePoint(0, 0) modifierFlags:0xa00 + timestamp:0 windowNumber:0 context:0 subtype:8 + data1:(convertKeyIDToNXKeyType(id) << 16) | ((0xa) << 8) + data2:-1]; + CGEventRef downEvent = [downRef CGEvent]; + + NSEvent* upRef = [NSEvent otherEventWithType:NSSystemDefined + location: NSMakePoint(0, 0) modifierFlags:0xa00 + timestamp:0 windowNumber:0 context:0 subtype:8 + data1:(convertKeyIDToNXKeyType(id) << 16) | ((0xb) << 8) + data2:-1]; + CGEventRef upEvent = [upRef CGEvent]; + + CGEventPost(0, downEvent); + CGEventPost(0, upEvent); + + return true; +} diff --git a/src/lib/synergy/IKeyState.h b/src/lib/synergy/IKeyState.h index 0e6484c1..da0062c4 100644 --- a/src/lib/synergy/IKeyState.h +++ b/src/lib/synergy/IKeyState.h @@ -122,7 +122,14 @@ public: complete and false if normal key processing should continue. */ virtual bool fakeCtrlAltDel() = 0; - + + //! Fake a media key + /*! + Synthesizes a media key down and up. Only Mac would implement this by + use cocoa appkit framework. + */ + virtual bool fakeMediaKey(KeyID id) = 0; + //@} //! @name accessors //@{ diff --git a/src/lib/synergy/IPlatformScreen.cpp b/src/lib/synergy/IPlatformScreen.cpp new file mode 100644 index 00000000..7c2b679f --- /dev/null +++ b/src/lib/synergy/IPlatformScreen.cpp @@ -0,0 +1,24 @@ +/* + * synergy -- mouse and keyboard sharing utility + * Copyright (C) 2016 Symless. + * + * This package is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * found in the file COPYING that should have accompanied this file. + * + * This package is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "synergy/IPlatformScreen.h" + +bool +IPlatformScreen::fakeMediaKey(KeyID id) +{ + return false; +} diff --git a/src/lib/synergy/IPlatformScreen.h b/src/lib/synergy/IPlatformScreen.h index 98b7668c..cd00b23c 100644 --- a/src/lib/synergy/IPlatformScreen.h +++ b/src/lib/synergy/IPlatformScreen.h @@ -180,6 +180,7 @@ public: virtual bool fakeKeyUp(KeyButton button) = 0; virtual void fakeAllKeysUp() = 0; virtual bool fakeCtrlAltDel() = 0; + virtual bool fakeMediaKey(KeyID id); virtual bool isKeyDown(KeyButton) const = 0; virtual KeyModifierMask getActiveModifiers() const = 0; diff --git a/src/lib/synergy/KeyState.cpp b/src/lib/synergy/KeyState.cpp index 79b775f3..6adeb243 100644 --- a/src/lib/synergy/KeyState.cpp +++ b/src/lib/synergy/KeyState.cpp @@ -571,8 +571,18 @@ KeyState::fakeKeyDown(KeyID id, KeyModifierMask mask, KeyButton serverID) m_keyMap.mapKey(keys, id, pollActiveGroup(), m_activeModifiers, getActiveModifiersRValue(), mask, false); if (keyItem == NULL) { + // a media key won't be mapped on mac, so we need to fake it in a + // special way + if (id == kKeyAudioDown || id == kKeyAudioUp || id == kKeyAudioMute || + id == kKeyAudioPrev || id == kKeyAudioNext || + id == kKeyAudioPlay) { + LOG((CLOG_DEBUG "emulating media key")); + fakeMediaKey(id); + } + return; } + KeyButton localID = (KeyButton)(keyItem->m_button & kButtonMask); updateModifierKeyState(localID, oldActiveModifiers, m_activeModifiers); if (localID != 0) { diff --git a/src/lib/synergy/KeyState.h b/src/lib/synergy/KeyState.h index af9bcd6a..3d148353 100644 --- a/src/lib/synergy/KeyState.h +++ b/src/lib/synergy/KeyState.h @@ -73,6 +73,8 @@ public: virtual bool fakeKeyUp(KeyButton button); virtual void fakeAllKeysUp(); virtual bool fakeCtrlAltDel() = 0; + virtual bool fakeMediaKey(KeyID id) = 0; + virtual bool isKeyDown(KeyButton) const; virtual KeyModifierMask getActiveModifiers() const; diff --git a/src/lib/synergy/key_types.h b/src/lib/synergy/key_types.h index e789e140..71d19591 100644 --- a/src/lib/synergy/key_types.h +++ b/src/lib/synergy/key_types.h @@ -18,7 +18,7 @@ #pragma once -#include "base/EventTypes.h" +#include "common/basic_types.h" //! Key ID /*! @@ -284,12 +284,10 @@ static const KeyID kKeyAppUser2 = 0xE0B7; //@} struct KeyNameMapEntry { -public: const char* m_name; KeyID m_id; }; struct KeyModifierNameMapEntry { -public: const char* m_name; KeyModifierMask m_mask; }; @@ -300,11 +298,11 @@ A table of key names to the corresponding KeyID. Only the keys listed above plus non-alphanumeric ASCII characters are in the table. The end of the table is the first pair with a NULL m_name. */ -extern const KeyNameMapEntry kKeyNameMap[]; +extern const struct KeyNameMapEntry kKeyNameMap[]; //! Modifier key name to KeyModifierMask table /*! A table of modifier key names to the corresponding KeyModifierMask. The end of the table is the first pair with a NULL m_name. */ -extern const KeyModifierNameMapEntry kModifierNameMap[]; +extern const struct KeyModifierNameMapEntry kModifierNameMap[]; diff --git a/src/test/unittests/synergy/KeyStateTests.h b/src/test/unittests/synergy/KeyStateTests.h index 236bf3dc..8a9846c0 100644 --- a/src/test/unittests/synergy/KeyStateTests.h +++ b/src/test/unittests/synergy/KeyStateTests.h @@ -45,6 +45,7 @@ public: MOCK_METHOD0(fakeCtrlAltDel, bool()); MOCK_METHOD1(getKeyMap, void(synergy::KeyMap&)); MOCK_METHOD1(fakeKey, void(const Keystroke&)); + MOCK_METHOD2(fakeMediaKey, bool(KeyID, bool)); MOCK_CONST_METHOD1(pollPressedKeys, void(KeyButtonSet&)); };