diff options
| author | Jordan Woyak <jordan.woyak@gmail.com> | 2019-01-10 09:02:38 -0600 |
|---|---|---|
| committer | Jordan Woyak <jordan.woyak@gmail.com> | 2019-01-10 18:32:16 -0600 |
| commit | b425f86121c8c9f3b4a510e522d03e432677dcea (patch) | |
| tree | ec0a34d787c7962cdd61b1967d79c2bf2386c482 /Source/Core/InputCommon | |
| parent | c2afcb0f6bba761c248031ee715a1db3fd4dbe05 (diff) | |
ControllerInterface: Allow hotplug callbacks to be unregistered and don't reload the entire config from the ini file on hotplug, just update the control references. This should fix a crash on shutdown on Android.
Diffstat (limited to 'Source/Core/InputCommon')
4 files changed, 39 insertions, 4 deletions
diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 318b288434..3da92e8b75 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -249,10 +249,20 @@ void ControllerInterface::UpdateInput() // Register a callback to be called when a device is added or removed (as from the input backends' // hotplug thread), or when devices are refreshed -void ControllerInterface::RegisterDevicesChangedCallback(std::function<void()> callback) +// Returns a handle for later removing the callback. +ControllerInterface::HotplugCallbackHandle +ControllerInterface::RegisterDevicesChangedCallback(std::function<void()> callback) { std::lock_guard<std::mutex> lk(m_callbacks_mutex); m_devices_changed_callbacks.emplace_back(std::move(callback)); + return std::prev(m_devices_changed_callbacks.end()); +} + +// Unregister a device callback. +void ControllerInterface::UnregisterDevicesChangedCallback(const HotplugCallbackHandle& handle) +{ + std::lock_guard<std::mutex> lk(m_callbacks_mutex); + m_devices_changed_callbacks.erase(handle); } // Invoke all callbacks that were registered diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h index 0d712e5245..7330172421 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h @@ -6,9 +6,9 @@ #include <atomic> #include <functional> +#include <list> #include <memory> #include <mutex> -#include <vector> #include "Common/WindowSystemInfo.h" #include "InputCommon/ControllerInterface/Device.h" @@ -40,6 +40,8 @@ class ControllerInterface : public ciface::Core::DeviceContainer { public: + using HotplugCallbackHandle = std::list<std::function<void()>>::iterator; + ControllerInterface() : m_is_init(false) {} void Initialize(const WindowSystemInfo& wsi); void ChangeWindow(void* hwnd); @@ -50,11 +52,12 @@ public: bool IsInit() const { return m_is_init; } void UpdateInput(); - void RegisterDevicesChangedCallback(std::function<void(void)> callback); + HotplugCallbackHandle RegisterDevicesChangedCallback(std::function<void(void)> callback); + void UnregisterDevicesChangedCallback(const HotplugCallbackHandle& handle); void InvokeDevicesChangedCallbacks() const; private: - std::vector<std::function<void()>> m_devices_changed_callbacks; + std::list<std::function<void()>> m_devices_changed_callbacks; mutable std::mutex m_callbacks_mutex; std::atomic<bool> m_is_init; std::atomic<bool> m_is_populating_devices{false}; diff --git a/Source/Core/InputCommon/InputConfig.cpp b/Source/Core/InputCommon/InputConfig.cpp index dfc677d70a..65cfdef086 100644 --- a/Source/Core/InputCommon/InputConfig.cpp +++ b/Source/Core/InputCommon/InputConfig.cpp @@ -147,6 +147,21 @@ std::size_t InputConfig::GetControllerCount() const return m_controllers.size(); } +void InputConfig::RegisterHotplugCallback() +{ + // Update control references on all controllers + // as configured devices may have been added or removed. + m_hotplug_callback_handle = g_controller_interface.RegisterDevicesChangedCallback([this] { + for (auto& controller : m_controllers) + controller->UpdateReferences(g_controller_interface); + }); +} + +void InputConfig::UnregisterHotplugCallback() +{ + g_controller_interface.UnregisterDevicesChangedCallback(m_hotplug_callback_handle); +} + bool InputConfig::IsControllerControlledByGamepadDevice(int index) const { if (static_cast<size_t>(index) >= m_controllers.size()) diff --git a/Source/Core/InputCommon/InputConfig.h b/Source/Core/InputCommon/InputConfig.h index 004e4be8bb..37d6e06b96 100644 --- a/Source/Core/InputCommon/InputConfig.h +++ b/Source/Core/InputCommon/InputConfig.h @@ -9,6 +9,8 @@ #include <utility> #include <vector> +#include "InputCommon/ControllerInterface/ControllerInterface.h" + namespace ControllerEmu { class EmulatedController; @@ -40,7 +42,12 @@ public: std::string GetProfileName() const { return m_profile_name; } std::size_t GetControllerCount() const; + // These should be used after creating all controllers and before clearing them, respectively. + void RegisterHotplugCallback(); + void UnregisterHotplugCallback(); + private: + ControllerInterface::HotplugCallbackHandle m_hotplug_callback_handle; std::vector<std::unique_ptr<ControllerEmu::EmulatedController>> m_controllers; const std::string m_ini_name; const std::string m_gui_name; |
