1 /* 2 * synergy -- mouse and keyboard sharing utility 3 * Copyright (C) 2012-2016 Symless Ltd. 4 * Copyright (C) 2004 Chris Schoeneman 5 * 6 * This package is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License 8 * found in the file LICENSE that should have accompanied this file. 9 * 10 * This package is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <http://www.gnu.org/licenses/>. 17 */ 18 19 #pragma once 20 21 #include "synergy/KeyState.h" 22 #include "common/stdmap.h" 23 #include "common/stdset.h" 24 #include "common/stdvector.h" 25 26 #include <Carbon/Carbon.h> 27 28 class IOSXKeyResource; 29 30 31 //! OS X key state 32 /*! 33 A key state for OS X. 34 */ 35 class OSXKeyState : public KeyState { 36 public: 37 typedef std::vector<KeyID> KeyIDs; 38 39 OSXKeyState(IEventQueue* events); 40 OSXKeyState(IEventQueue* events, synergy::KeyMap& keyMap); 41 virtual ~OSXKeyState(); 42 43 //! @name modifiers 44 //@{ 45 46 //! Handle modifier key change 47 /*! 48 Determines which modifier keys have changed and updates the modifier 49 state and sends key events as appropriate. 50 */ 51 void handleModifierKeys(void* target, 52 KeyModifierMask oldMask, KeyModifierMask newMask); 53 54 //@} 55 //! @name accessors 56 //@{ 57 58 //! Convert OS X modifier mask to synergy mask 59 /*! 60 Returns the synergy modifier mask corresponding to the OS X modifier 61 mask in \p mask. 62 */ 63 KeyModifierMask mapModifiersFromOSX(UInt32 mask) const; 64 65 //! Convert CG flags-style modifier mask to old-style Carbon 66 /*! 67 Still required in a few places for translation calls. 68 */ 69 KeyModifierMask mapModifiersToCarbon(UInt32 mask) const; 70 71 //! Map key event to keys 72 /*! 73 Converts a key event into a sequence of KeyIDs and the shadow modifier 74 state to a modifier mask. The KeyIDs list, in order, the characters 75 generated by the key press/release. It returns the id of the button 76 that was pressed or released, or 0 if the button doesn't map to a known 77 KeyID. 78 */ 79 KeyButton mapKeyFromEvent(KeyIDs& ids, 80 KeyModifierMask* maskOut, CGEventRef event) const; 81 82 //! Map key and mask to native values 83 /*! 84 Calculates mac virtual key and mask for a key \p key and modifiers 85 \p mask. Returns \c true if the key can be mapped, \c false otherwise. 86 */ 87 bool mapSynergyHotKeyToMac(KeyID key, KeyModifierMask mask, 88 UInt32& macVirtualKey, 89 UInt32& macModifierMask) const; 90 91 //@} 92 93 // IKeyState overrides 94 virtual bool fakeCtrlAltDel(); 95 virtual bool fakeMediaKey(KeyID id); 96 virtual KeyModifierMask 97 pollActiveModifiers() const; 98 virtual SInt32 pollActiveGroup() const; 99 virtual void pollPressedKeys(KeyButtonSet& pressedKeys) const; 100 101 CGEventFlags getModifierStateAsOSXFlags(); 102 protected: 103 // KeyState overrides 104 virtual void getKeyMap(synergy::KeyMap& keyMap); 105 virtual void fakeKey(const Keystroke& keystroke); 106 107 private: 108 class KeyResource; 109 typedef void(*CFDeallocator)(CFTypeRef); 110 typedef std::unique_ptr<const __CFArray, CFDeallocator> GroupList; 111 typedef std::unique_ptr<const __CFDictionary, CFDeallocator> AutoCFDictionary; 112 typedef std::unique_ptr<__TISInputSource, CFDeallocator> AutoTISInputSourceRef; 113 114 115 // Add hard coded special keys to a synergy::KeyMap. 116 void getKeyMapForSpecialKeys( 117 synergy::KeyMap& keyMap, SInt32 group) const; 118 119 // Convert keyboard resource to a key map 120 bool getKeyMap(synergy::KeyMap& keyMap, 121 SInt32 group, const IOSXKeyResource& r) const; 122 123 // Get the available keyboard groups 124 bool getGroups(GroupList&) const; 125 126 // Change active keyboard group to group 127 void setGroup(SInt32 group); 128 129 // Send an event for the given modifier key 130 void handleModifierKey(void* target, 131 UInt32 virtualKey, KeyID id, 132 bool down, KeyModifierMask newMask); 133 134 // Checks if any in \p ids is a glyph key and if \p isCommand is false. 135 // If so it adds the AltGr modifier to \p mask. This allows OS X 136 // servers to use the option key both as AltGr and as a modifier. If 137 // option is acting as AltGr (i.e. it generates a glyph and there are 138 // no command modifiers active) then we don't send the super modifier 139 // to clients because they'd try to match it as a command modifier. 140 void adjustAltGrModifier(const KeyIDs& ids, 141 KeyModifierMask* mask, bool isCommand) const; 142 143 // Maps an OS X virtual key id to a KeyButton. This simply remaps 144 // the ids so we don't use KeyButton 0. 145 static KeyButton mapVirtualKeyToKeyButton(UInt32 keyCode); 146 147 // Maps a KeyButton to an OS X key code. This is the inverse of 148 // mapVirtualKeyToKeyButton. 149 static UInt32 mapKeyButtonToVirtualKey(KeyButton keyButton); 150 151 void init(); 152 153 // Post a key event to HID manager. It posts an event to HID client, a 154 // much lower level than window manager which's the target from carbon 155 // CGEventPost 156 void postHIDVirtualKey(const UInt8 virtualKeyCode, 157 const bool postDown); 158 159 private: 160 // OS X uses a physical key if 0 for the 'A' key. synergy reserves 161 // KeyButton 0 so we offset all OS X physical key ids by this much 162 // when used as a KeyButton and by minus this much to map a KeyButton 163 // to a physical button. 164 enum { 165 KeyButtonOffset = 1 166 }; 167 168 typedef std::map<CFDataRef, SInt32> GroupMap; 169 typedef std::map<UInt32, KeyID> VirtualKeyMap; 170 171 VirtualKeyMap m_virtualKeyMap; 172 mutable UInt32 m_deadKeyState; 173 GroupList m_groups{nullptr, CFRelease}; 174 GroupMap m_groupMap; 175 bool m_shiftPressed; 176 bool m_controlPressed; 177 bool m_altPressed; 178 bool m_superPressed; 179 bool m_capsPressed; 180 }; 181