1 //////////////////////////////////////////////////////////// 2 // 3 // SFML - Simple and Fast Multimedia Library 4 // Copyright (C) 2007-2018 Marco Antognini (antognini.marco@gmail.com), 5 // Laurent Gomila (laurent@sfml-dev.org) 6 // 7 // This software is provided 'as-is', without any express or implied warranty. 8 // In no event will the authors be held liable for any damages arising from the use of this software. 9 // 10 // Permission is granted to anyone to use this software for any purpose, 11 // including commercial applications, and to alter it and redistribute it freely, 12 // subject to the following restrictions: 13 // 14 // 1. The origin of this software must not be misrepresented; 15 // you must not claim that you wrote the original software. 16 // If you use this software in a product, an acknowledgment 17 // in the product documentation would be appreciated but is not required. 18 // 19 // 2. Altered source versions must be plainly marked as such, 20 // and must not be misrepresented as being the original software. 21 // 22 // 3. This notice may not be removed or altered from any source distribution. 23 // 24 //////////////////////////////////////////////////////////// 25 26 #ifndef SFML_HIDINPUTMANAGER_HPP 27 #define SFML_HIDINPUTMANAGER_HPP 28 29 //////////////////////////////////////////////////////////// 30 // Headers 31 //////////////////////////////////////////////////////////// 32 #include <SFML/Window/JoystickImpl.hpp> 33 #include <SFML/Window/Keyboard.hpp> 34 #include <SFML/System/NonCopyable.hpp> 35 #include <Carbon/Carbon.h> 36 #include <IOKit/hid/IOHIDDevice.h> 37 #include <IOKit/hid/IOHIDManager.h> 38 #include <vector> 39 40 namespace sf 41 { 42 namespace priv 43 { 44 45 typedef std::vector<IOHIDElementRef> IOHIDElements; 46 47 //////////////////////////////////////////////////////////// 48 /// \brief sf::priv::InputImpl helper 49 /// 50 /// This class manage as a singleton instance the keyboard state. 51 /// Its purpose is to help sf::priv::InputImpl class. 52 /// 53 //////////////////////////////////////////////////////////// 54 class HIDInputManager : NonCopyable 55 { 56 public: 57 58 //////////////////////////////////////////////////////////// 59 /// \brief Get the unique instance of the class 60 /// 61 /// \note Private use only 62 /// 63 /// \return Reference to the HIDInputManager instance 64 /// 65 //////////////////////////////////////////////////////////// 66 static HIDInputManager& getInstance(); 67 68 //////////////////////////////////////////////////////////// 69 /// \brief Check if a key is pressed 70 /// 71 /// \param key Key to check 72 /// 73 /// \return True if the key is pressed, false otherwise 74 /// 75 //////////////////////////////////////////////////////////// 76 bool isKeyPressed(Keyboard::Key key); 77 78 public: 79 80 //////////////////////////////////////////////////////////// 81 /// \brief Get the usb location ID of a given device 82 /// 83 /// This location ID is unique and can be used a usb port identifier 84 /// 85 /// \param device HID device to query 86 /// \return the device's location ID or 0 if something went wrong 87 /// 88 //////////////////////////////////////////////////////////// 89 static long getLocationID(IOHIDDeviceRef device); 90 91 //////////////////////////////////////////////////////////// 92 /// \brief Create a mask (dictionary) for an IOHIDManager 93 /// 94 /// \param page HID page 95 /// \param usage HID usage page 96 /// \return a retained CFDictionaryRef 97 /// 98 //////////////////////////////////////////////////////////// 99 static CFDictionaryRef copyDevicesMask(UInt32 page, UInt32 usage); 100 101 //////////////////////////////////////////////////////////// 102 /// Try to convert a character into a SFML key code. 103 /// 104 /// Return sf::Keyboard::Unknown if it doesn't match any 'localized' keys. 105 /// 106 /// By 'localized' I mean keys that depend on the keyboard layout 107 /// and might not be the same as the US keycode in some country 108 /// (e.g. the keys 'Y' and 'Z' are switched on QWERTZ keyboard and 109 /// US keyboard layouts.) 110 /// 111 //////////////////////////////////////////////////////////// 112 static Keyboard::Key localizedKeys(UniChar ch); 113 114 //////////////////////////////////////////////////////////// 115 /// Try to convert a virtual keycode into a SFML key code. 116 /// 117 /// Return sf::Keyboard::Unknown if the keycode is unknown. 118 /// 119 //////////////////////////////////////////////////////////// 120 static Keyboard::Key nonLocalizedKeys(UniChar virtualKeycode); 121 122 private: 123 124 //////////////////////////////////////////////////////////// 125 /// \brief Default constructor 126 /// 127 //////////////////////////////////////////////////////////// 128 HIDInputManager(); 129 130 //////////////////////////////////////////////////////////// 131 /// \brief Destructor 132 /// 133 //////////////////////////////////////////////////////////// 134 ~HIDInputManager(); 135 136 //////////////////////////////////////////////////////////// 137 /// \brief Initialize the keyboard part of this class 138 /// 139 /// If something went wrong freeUp is called 140 /// 141 //////////////////////////////////////////////////////////// 142 void initializeKeyboard(); 143 144 //////////////////////////////////////////////////////////// 145 /// \brief Load the given keyboard into m_keys 146 /// 147 /// If the given keyboard has no key this function simply 148 /// returns. freeUp is _not_ called because this is not fatal. 149 /// 150 /// \param keyboard Keyboard to load 151 /// 152 //////////////////////////////////////////////////////////// 153 void loadKeyboard(IOHIDDeviceRef keyboard); 154 155 //////////////////////////////////////////////////////////// 156 /// \brief Load the given key into m_keys 157 /// 158 /// freeUp is _not_ called by this function. 159 /// 160 /// \param key Key to load 161 /// 162 //////////////////////////////////////////////////////////// 163 void loadKey(IOHIDElementRef key); 164 165 //////////////////////////////////////////////////////////// 166 /// \brief Release all resources 167 /// 168 /// Close all connections to any devices, if required 169 /// Set m_isValid to false 170 /// 171 //////////////////////////////////////////////////////////// 172 void freeUp(); 173 174 //////////////////////////////////////////////////////////// 175 /// \brief Filter the devices and return them 176 /// 177 /// freeUp is _not_ called by this function. 178 /// 179 /// \param page HID page like kHIDPage_GenericDesktop 180 /// \param usage HID usage page like kHIDUsage_GD_Keyboard or kHIDUsage_GD_Mouse 181 /// \return a retained CFSetRef of IOHIDDeviceRef or NULL 182 /// 183 //////////////////////////////////////////////////////////// 184 CFSetRef copyDevices(UInt32 page, UInt32 usage); 185 186 //////////////////////////////////////////////////////////// 187 /// \brief Check if a key is pressed 188 /// 189 /// \param elements HID elements mapping to this key 190 /// 191 /// \return True if the key is pressed, false otherwise 192 /// 193 /// \see isKeyPressed, isMouseButtonPressed 194 /// 195 //////////////////////////////////////////////////////////// 196 bool isPressed(IOHIDElements& elements); 197 198 //////////////////////////////////////////////////////////// 199 /// \brief Convert a HID key usage to its corresponding virtual code 200 /// 201 /// See IOHIDUsageTables.h 202 /// 203 /// \param usage Any kHIDUsage_Keyboard* usage 204 /// \return the virtual code associate with the given HID key usage 205 /// or 0xff if it is associate with no virtual code 206 /// 207 //////////////////////////////////////////////////////////// 208 static UInt8 usageToVirtualCode(UInt32 usage); 209 210 private: 211 212 //////////////////////////////////////////////////////////// 213 // Member data 214 //////////////////////////////////////////////////////////// 215 bool m_isValid; ///< If any error occurs this variable is false 216 CFDataRef m_layoutData; ///< CFData containing the layout 217 UCKeyboardLayout* m_layout; ///< Current Keyboard Layout 218 IOHIDManagerRef m_manager; ///< HID Manager 219 220 IOHIDElements m_keys[Keyboard::KeyCount]; ///< All the keys on any connected keyboard 221 222 //////////////////////////////////////////////////////////// 223 /// m_keys' index corresponds to sf::Keyboard::Key enum. 224 /// if no key is assigned with key XYZ then m_keys[XYZ].size() == 0. 225 /// if there are several keyboards connected and several HID keys associate 226 /// with the same sf::Keyboard::Key then m_keys[XYZ] contains all these 227 /// HID keys. 228 /// 229 //////////////////////////////////////////////////////////// 230 }; 231 232 } // namespace priv 233 234 } // namespace sf 235 236 #endif 237