diff --git a/src/SFML/Window/OSX/HIDInputManager.hpp b/src/SFML/Window/OSX/HIDInputManager.hpp index aee34dc53..e6e13ad9a 100644 --- a/src/SFML/Window/OSX/HIDInputManager.hpp +++ b/src/SFML/Window/OSX/HIDInputManager.hpp @@ -127,6 +127,14 @@ private : //////////////////////////////////////////////////////////// void InitializeKeyboard(); + //////////////////////////////////////////////////////////// + /// \brief Initialize the mouse part of this class + /// + /// If something went wrong FreeUp is called + /// + //////////////////////////////////////////////////////////// + void InitializeMouse(); + //////////////////////////////////////////////////////////// /// \brief Load the given keyboard into myKeys /// @@ -138,6 +146,17 @@ private : //////////////////////////////////////////////////////////// void LoadKeyboard(IOHIDDeviceRef keyboard); + //////////////////////////////////////////////////////////// + /// \brief Load the given mouse into myButtons + /// + /// If the given mouse has no button this function simply + /// returns. FreeUp is _not_ called because this is not fatal. + /// + /// \param mouse Mouse to load + /// + //////////////////////////////////////////////////////////// + void LoadMouse(IOHIDDeviceRef mouse); + //////////////////////////////////////////////////////////// /// \brief Load the given key into myKeys /// @@ -148,6 +167,16 @@ private : //////////////////////////////////////////////////////////// void LoadKey(IOHIDElementRef key); + //////////////////////////////////////////////////////////// + /// \brief Load the given button into myButtons + /// + /// FreeUp is _not_ called by this function. + /// + /// \param button Button to load + /// + //////////////////////////////////////////////////////////// + void LoadButton(IOHIDElementRef button); + //////////////////////////////////////////////////////////// /// \brief Release all resources /// @@ -202,7 +231,8 @@ private : IOHIDManagerRef myManager; ///< HID Manager typedef std::vector IOHIDElements; - IOHIDElements myKeys[Keyboard::KeyCount]; ///< All the keys on the current keyboard + IOHIDElements myKeys[Keyboard::KeyCount]; ///< All the keys on any connected keyboard + IOHIDElements myButtons[Mouse::ButtonCount];///< All the buttons on any connected mouse //////////////////////////////////////////////////////////// /// myKeys' index corresponds to sf::Keyboard::Key enum. @@ -211,6 +241,8 @@ private : /// with the same sf::Keyboard::Key then myKeys[XYZ] contains all these /// HID keys. /// + /// myButtons works the same way. + /// //////////////////////////////////////////////////////////// }; diff --git a/src/SFML/Window/OSX/HIDInputManager.mm b/src/SFML/Window/OSX/HIDInputManager.mm index d92057bc7..a8118db8f 100644 --- a/src/SFML/Window/OSX/HIDInputManager.mm +++ b/src/SFML/Window/OSX/HIDInputManager.mm @@ -67,16 +67,12 @@ bool HIDInputManager::IsKeyPressed(Keyboard::Key key) CFRelease(*it); it = myKeys[key].erase(it); - - sf::Err() << key - << " is dead (cannot access its value)." - << std::endl; } else if (IOHIDValueGetIntegerValue(value) == 1) { // This means the key is pressed state = true; - break; // Stop here. + break; // Stop here } else { @@ -97,8 +93,38 @@ bool HIDInputManager::IsMouseButtonPressed(Mouse::Button button) return false; } - // @to be implemented - return false; + // state = true if at least one corresponding HID button is pressed + bool state = false; + + for (IOHIDElements::iterator it = myButtons[button].begin(); it != myButtons[button].end(); ++it) { + + IOHIDValueRef value = 0; + + IOHIDDeviceRef device = IOHIDElementGetDevice(*it); + IOHIDDeviceGetValue(device, *it, &value); + + if (!value) { + + // This means some kind of error / deconnection so we remove this + // element from our buttons + + CFRelease(*it); + it = myButtons[button].erase(it); + + } else if (IOHIDValueGetIntegerValue(value) == 1) { + + // This means the button is pressed + state = true; + break; // Stop here + + } else { + + // This means the button is released + } + + } + + return state; } @@ -147,7 +173,12 @@ HIDInputManager::HIDInputManager() return; // Something went wrong } - // TODO init mouse + // Initialize the mouse + InitializeMouse(); + + if (!amIValid) { + return; // Something went wrong + } } @@ -193,6 +224,42 @@ void HIDInputManager::InitializeKeyboard() } +//////////////////////////////////////////////////////////// +void HIDInputManager::InitializeMouse() +{ + //////////////////////////////////////////////////////////// + // The purpose of this function is to initalize myButtons so we can get + // the associate IOHIDElementRef with a sf::Mouse::Button in ~constant~ time. + + // Get only mouses + CFSetRef mouses = CopyDevices(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse); + if (mouses == NULL) { + + // FreeUp was already called + return; + } + + CFIndex mouseCount = CFSetGetCount(mouses); // >= 1 (asserted by CopyDevices) + + // Get an iterable array + CFTypeRef devicesArray[mouseCount]; + CFSetGetValues(mouses, devicesArray); + + for (CFIndex i = 0; i < mouseCount; ++i) { + + IOHIDDeviceRef mouse = (IOHIDDeviceRef)devicesArray[i]; + + LoadMouse(mouse); + } + + // Release unused stuff + CFRelease(mouses); + + //////////////////////////////////////////////////////////// + // At this point myButtons is filled with as many IOHIDElementRef as possible +} + + //////////////////////////////////////////////////////////// void HIDInputManager::LoadKeyboard(IOHIDDeviceRef keyboard) { @@ -232,6 +299,44 @@ void HIDInputManager::LoadKeyboard(IOHIDDeviceRef keyboard) } +//////////////////////////////////////////////////////////// +void HIDInputManager::LoadMouse(IOHIDDeviceRef mouse) +{ + CFArrayRef buttons = IOHIDDeviceCopyMatchingElements(mouse, + NULL, + kIOHIDOptionsTypeNone); + if (buttons == NULL) { + sf::Err() << "We got a mouse without any buttons (1)" << std::endl; + return; + } + + // How many elements are there ? + CFIndex buttonCount = CFArrayGetCount(buttons); + + if (buttonCount == 0) { + sf::Err() << "We got a mouse without any buttons (2)" << std::endl; + CFRelease(buttons); + return; + } + + // Go through all connected elements. + for (CFIndex i = 0; i < buttonCount; ++i) { + + IOHIDElementRef aButton = (IOHIDElementRef) CFArrayGetValueAtIndex(buttons, i); + + // Skip non-matching keys elements + if (IOHIDElementGetUsagePage(aButton) != kHIDPage_Button) { + continue; + } + + LoadButton(aButton); + } + + // Release unused stuff + CFRelease(buttons); +} + + //////////////////////////////////////////////////////////// void HIDInputManager::LoadKey(IOHIDElementRef key) { @@ -330,6 +435,36 @@ void HIDInputManager::LoadKey(IOHIDElementRef key) } +//////////////////////////////////////////////////////////// +void HIDInputManager::LoadButton(IOHIDElementRef button) +{ + // Identify the button + UInt32 usage = IOHIDElementGetUsage(button); + Mouse::Button dest = Mouse::ButtonCount; + + // Extends kHIDUsage_Button_* enum with : +#define kHIDUsage_Button_5 0x05 + + switch (usage) { + case kHIDUsage_Button_1: dest = Mouse::Left; break; + case kHIDUsage_Button_2: dest = Mouse::Right; break; + case kHIDUsage_Button_3: dest = Mouse::Middle; break; + case kHIDUsage_Button_4: dest = Mouse::XButton1; break; + case kHIDUsage_Button_5: dest = Mouse::XButton2; break; + default: dest = Mouse::ButtonCount; break; + } + + if (dest != Mouse::ButtonCount) { + // We know what kind of button it is! + + myButtons[dest].push_back(button); + + // And don't forget to keep the reference alive for our usage + CFRetain(myButtons[dest].back()); + } +} + + //////////////////////////////////////////////////////////// void HIDInputManager::FreeUp() { @@ -345,6 +480,13 @@ void HIDInputManager::FreeUp() } myKeys[i].clear(); } + + for (unsigned int i = 0; i < Mouse::ButtonCount; ++i) { + for (IOHIDElements::iterator it = myButtons[i].begin(); it != myButtons[i].end(); ++it) { + CFRelease(*it); + } + myButtons[i].clear(); + } }