diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 54974aed7a..b84e8af571 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -64,9 +64,7 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi) // nothing needed #endif #ifdef CIFACE_USE_OSX - if (m_wsi.type == WindowSystemType::MacOS) - ciface::OSX::Init(wsi.render_window); -// nothing needed for Quartz +// nothing needed for OSX and Quartz #endif #ifdef CIFACE_USE_SDL ciface::SDL::Init(); @@ -118,6 +116,18 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) if (!m_is_init) return; +#ifdef CIFACE_USE_OSX + if (m_wsi.type == WindowSystemType::MacOS) + { + std::lock_guard lk_pre_population(m_pre_population_mutex); + // This is needed to stop its threads before locking our mutexes, to avoid deadlocks + // (in case it tried to add a device after we had locked m_devices_population_mutex). + // There doesn't seem to be an easy to way to repopulate OSX devices without restarting + // its hotplug thread. This will not release its devices, that's still done below. + ciface::OSX::DeInit(); + } +#endif + // This lock has two main functions: // -Avoid a deadlock between m_devices_mutex and ControllerEmu::s_state_mutex when // InvokeDevicesChangedCallbacks() is called concurrently by two different threads. @@ -152,7 +162,10 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) #ifdef CIFACE_USE_OSX if (m_wsi.type == WindowSystemType::MacOS) { - ciface::OSX::PopulateDevices(m_wsi.render_window); + { + std::lock_guard lk_pre_population(m_pre_population_mutex); + ciface::OSX::Init(); + } ciface::Quartz::PopulateDevices(m_wsi.render_window); } #endif diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h index 826659941d..9c91d853e7 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h @@ -116,6 +116,7 @@ private: std::list> m_devices_changed_callbacks; mutable std::recursive_mutex m_devices_population_mutex; + mutable std::mutex m_pre_population_mutex; mutable std::mutex m_callbacks_mutex; std::atomic m_is_init; // This is now always protected by m_devices_population_mutex, so diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h index 955b426f5e..f4ebc1a911 100644 --- a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h +++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.h @@ -6,8 +6,7 @@ namespace ciface::OSX { -void Init(void* window); -void PopulateDevices(void* window); +void Init(); void DeInit(); void DeviceElementDebugPrint(const void*, void*); diff --git a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm index 63bddf499e..8c80e9f529 100644 --- a/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm +++ b/Source/Core/InputCommon/ControllerInterface/OSX/OSX.mm @@ -135,8 +135,6 @@ static void DeviceDebugPrint(IOHIDDeviceRef device) #endif } -static void* g_window; - static std::string GetDeviceRefName(IOHIDDeviceRef inIOHIDDeviceRef) { const NSString* name = reinterpret_cast( @@ -172,10 +170,8 @@ static void DeviceMatchingCallback(void* inContext, IOReturn inResult, void* inS } } -void Init(void* window) +void Init() { - g_window = window; - HIDManager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone); if (!HIDManager) ERROR_LOG_FMT(CONTROLLERINTERFACE, "Failed to create HID Manager reference"); @@ -210,19 +206,17 @@ void Init(void* window) }); } -void PopulateDevices(void* window) -{ - DeInit(); - Init(window); -} - void DeInit() { - s_stopper.Signal(); - s_hotplug_thread.join(); + if (HIDManager) + { + s_stopper.Signal(); + s_hotplug_thread.join(); - // This closes all devices as well - IOHIDManagerClose(HIDManager, kIOHIDOptionsTypeNone); - CFRelease(HIDManager); + // This closes all devices as well + IOHIDManagerClose(HIDManager, kIOHIDOptionsTypeNone); + CFRelease(HIDManager); + HIDManager = nullptr; + } } } // namespace ciface::OSX