diff --git a/src/SFML/Window/macOS/HIDInputManager.hpp b/src/SFML/Window/macOS/HIDInputManager.hpp index d7cd1f2c2..5778477d4 100644 --- a/src/SFML/Window/macOS/HIDInputManager.hpp +++ b/src/SFML/Window/macOS/HIDInputManager.hpp @@ -41,7 +41,7 @@ namespace sf::priv { -using IOHIDElements = std::vector; +using IOHIDElements = std::vector>; //////////////////////////////////////////////////////////// /// \brief sf::priv::InputImpl helper diff --git a/src/SFML/Window/macOS/HIDInputManager.mm b/src/SFML/Window/macOS/HIDInputManager.mm index 18d04a129..3f2b78f4e 100644 --- a/src/SFML/Window/macOS/HIDInputManager.mm +++ b/src/SFML/Window/macOS/HIDInputManager.mm @@ -796,7 +796,7 @@ void HIDInputManager::loadKey(IOHIDElementRef key) if (code != Keyboard::Scan::Unknown) { CFRetain(key); - m_keys[code].push_back(key); + m_keys[code].emplace_back(key); } } @@ -920,15 +920,8 @@ void HIDInputManager::freeUp() m_manager.reset(); if (m_keysInitialized) - { for (auto& key : m_keys) - { - for (IOHIDElementRef iohidElementRef : key) - CFRelease(iohidElementRef); - key.clear(); - } - } m_keysInitialized = false; } @@ -961,13 +954,12 @@ bool HIDInputManager::isPressed(IOHIDElements& elements) const { IOHIDValueRef value = nil; - IOHIDDeviceRef device = IOHIDElementGetDevice(*it); - IOHIDDeviceGetValue(device, *it, &value); + IOHIDDeviceRef device = IOHIDElementGetDevice(it->get()); + IOHIDDeviceGetValue(device, it->get(), &value); if (!value) { // This means some kind of error / disconnection so we remove this element from our database. - CFRelease(*it); it = elements.erase(it); } else diff --git a/src/SFML/Window/macOS/JoystickImpl.cpp b/src/SFML/Window/macOS/JoystickImpl.cpp index de62d5e69..91d80d962 100644 --- a/src/SFML/Window/macOS/JoystickImpl.cpp +++ b/src/SFML/Window/macOS/JoystickImpl.cpp @@ -218,11 +218,12 @@ bool JoystickImpl::open(unsigned int index) const CFIndex elementsCount = CFArrayGetCount(elements.get()); for (int i = 0; i < elementsCount; ++i) { - auto* element = static_cast(const_cast(CFArrayGetValueAtIndex(elements.get(), i))); - switch (IOHIDElementGetUsagePage(element)) + auto element = std::shared_ptr(CFPtr<__IOHIDElement>( + static_cast(const_cast(CFArrayGetValueAtIndex(elements.get(), i))))); + switch (IOHIDElementGetUsagePage(element.get())) { case kHIDPage_GenericDesktop: - switch (IOHIDElementGetUsage(element)) + switch (IOHIDElementGetUsage(element.get())) { case kHIDUsage_GD_X: m_axis[Joystick::Axis::X] = element; @@ -255,8 +256,8 @@ bool JoystickImpl::open(unsigned int index) // We assume this model here as well. Hence, with 4 switches and intermediate // positions we have 8 values (0-7) plus the "null" state (8). { - const CFIndex min = IOHIDElementGetLogicalMin(element); - const CFIndex max = IOHIDElementGetLogicalMax(element); + const CFIndex min = IOHIDElementGetLogicalMin(element.get()); + const CFIndex max = IOHIDElementGetLogicalMax(element.get()); if (min != 0 || max != 7) { @@ -275,18 +276,18 @@ bool JoystickImpl::open(unsigned int index) // We assume a game pad is an application collection, meaning it doesn't hold // any values per say. They kind of "emit" the joystick's usages. // See ยง3.4.3 Usage Types (Collection) of HUT v1.12 - if (IOHIDElementGetCollectionType(element) != kIOHIDElementCollectionTypeApplication) + if (IOHIDElementGetCollectionType(element.get()) != kIOHIDElementCollectionTypeApplication) { sf::err() << std::hex << "Gamepage (vendor/product id: 0x" << m_identification.vendorId << "/0x" << m_identification.productId << ") is not an CA but a 0x" - << IOHIDElementGetCollectionType(element) << std::dec << std::endl; + << IOHIDElementGetCollectionType(element.get()) << std::dec << std::endl; } break; default: #ifdef SFML_DEBUG sf::err() << "Unexpected usage for element of Page Generic Desktop: 0x" << std::hex - << IOHIDElementGetUsage(element) << std::dec << std::endl; + << IOHIDElementGetUsage(element.get()) << std::dec << std::endl; #endif break; } @@ -307,21 +308,7 @@ bool JoystickImpl::open(unsigned int index) // HID Usage (assigned by manufacturer and/or a driver). std::sort(m_buttons.begin(), m_buttons.end(), - [](IOHIDElementRef b1, IOHIDElementRef b2) { return IOHIDElementGetUsage(b1) < IOHIDElementGetUsage(b2); }); - - // Retain all these objects for personal use - for (IOHIDElementRef iohidElementRef : m_buttons) - CFRetain(iohidElementRef); - - for (const auto& [axis, iohidElementRef] : m_axis) - CFRetain(iohidElementRef); - - if (m_hat != nullptr) - CFRetain(m_hat); - - // Note: we didn't retain element in the switch because we might have multiple - // Axis X (for example) and we want to keep only the last one. To prevent - // leaking we retain objects 'only' now. + [](auto b1, auto b2) { return IOHIDElementGetUsage(b1.get()) < IOHIDElementGetUsage(b2.get()); }); return true; } @@ -332,20 +319,9 @@ void JoystickImpl::close() { const AutoreleasePool pool; - for (IOHIDElementRef iohidElementRef : m_buttons) - CFRelease(iohidElementRef); - m_buttons.clear(); - - for (const auto& [axis, iohidElementRef] : m_axis) - CFRelease(iohidElementRef); - m_axis.clear(); - - if (m_hat != nullptr) - CFRelease(m_hat); - - m_hat = nullptr; + m_hat.reset(); // And we unregister this joystick m_locationIDs[m_index] = 0; @@ -418,11 +394,10 @@ JoystickState JoystickImpl::update() return disconnectedState; // Update buttons' state - unsigned int i = 0; - for (auto it = m_buttons.begin(); it != m_buttons.end(); ++it, ++i) + for (std::size_t i = 0; i < m_buttons.size(); ++i) { IOHIDValueRef value = nil; - IOHIDDeviceGetValue(IOHIDElementGetDevice(*it), *it, &value); + IOHIDDeviceGetValue(IOHIDElementGetDevice(m_buttons[i].get()), m_buttons[i].get(), &value); // Check for plug out. if (!value) @@ -438,7 +413,7 @@ JoystickState JoystickImpl::update() for (const auto& [axis, iohidElementRef] : m_axis) { IOHIDValueRef value = nil; - IOHIDDeviceGetValue(IOHIDElementGetDevice(iohidElementRef), iohidElementRef, &value); + IOHIDDeviceGetValue(IOHIDElementGetDevice(iohidElementRef.get()), iohidElementRef.get(), &value); // Check for plug out. if (!value) @@ -456,8 +431,8 @@ JoystickState JoystickImpl::update() // This method might not be very accurate (the "0 position" can be // slightly shift with some device) but we don't care because most // of devices are so sensitive that this is not relevant. - const auto physicalMax = static_cast(IOHIDElementGetPhysicalMax(iohidElementRef)); - const auto physicalMin = static_cast(IOHIDElementGetPhysicalMin(iohidElementRef)); + const auto physicalMax = static_cast(IOHIDElementGetPhysicalMax(iohidElementRef.get())); + const auto physicalMin = static_cast(IOHIDElementGetPhysicalMin(iohidElementRef.get())); const double scaledMin = -100; const double scaledMax = 100; const double physicalValue = IOHIDValueGetScaledValue(value, kIOHIDValueScaleTypePhysical); @@ -475,7 +450,7 @@ JoystickState JoystickImpl::update() if (m_hat != nullptr) { IOHIDValueRef value = nil; - IOHIDDeviceGetValue(IOHIDElementGetDevice(m_hat), m_hat, &value); + IOHIDDeviceGetValue(IOHIDElementGetDevice(m_hat.get()), m_hat.get(), &value); // Check for plug out. if (!value) diff --git a/src/SFML/Window/macOS/JoystickImpl.hpp b/src/SFML/Window/macOS/JoystickImpl.hpp index a6961aab5..9097e0278 100644 --- a/src/SFML/Window/macOS/JoystickImpl.hpp +++ b/src/SFML/Window/macOS/JoystickImpl.hpp @@ -111,14 +111,14 @@ private: // Member data //////////////////////////////////////////////////////////// using Location = long; - using AxisMap = std::unordered_map; - using ButtonsVector = std::vector; + using AxisMap = std::unordered_map>; + using ButtonsVector = std::vector>; - AxisMap m_axis; ///< Axes (but not POV/Hat) of the joystick - IOHIDElementRef m_hat{}; ///< POV/Hat axis of the joystick - ButtonsVector m_buttons; ///< Buttons of the joystick - unsigned int m_index{}; ///< SFML index - Joystick::Identification m_identification; ///< Joystick identification + AxisMap m_axis; ///< Axes (but not POV/Hat) of the joystick + std::shared_ptr<__IOHIDElement> m_hat; ///< POV/Hat axis of the joystick + ButtonsVector m_buttons; ///< Buttons of the joystick + unsigned int m_index{}; ///< SFML index + Joystick::Identification m_identification; ///< Joystick identification // NOLINTNEXTLINE(readability-identifier-naming) static inline std::array m_locationIDs{}; ///< Global Joystick register