diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 71dea5512c..8f7bed3af1 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -59,7 +59,7 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi) m_populating_devices_counter = 1; #ifdef CIFACE_USE_WIN32 - ciface::Win32::Init(wsi.render_window); + m_input_backends.emplace_back(ciface::Win32::CreateInputBackend(this)); #endif #ifdef CIFACE_USE_XLIB m_input_backends.emplace_back(ciface::XInput2::CreateInputBackend(this)); @@ -135,9 +135,8 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) { m_populating_devices_counter.fetch_add(1); - // No need to do anything else in this case. - // Only (Win32) DInput needs the window handle to be updated. - ciface::Win32::ChangeWindow(m_wsi.render_window); + for (auto& backend : m_input_backends) + backend->HandleWindowChange(); if (m_populating_devices_counter.fetch_sub(1) == 1) InvokeDevicesChangedCallbacks(); @@ -159,9 +158,6 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) // do it async, to not risk the emulated controllers default config loading not finding a default // device. -#ifdef CIFACE_USE_WIN32 - ciface::Win32::PopulateDevices(m_wsi.render_window); -#endif #ifdef CIFACE_USE_ANDROID ciface::Android::PopulateDevices(); #endif @@ -204,9 +200,6 @@ void ControllerInterface::Shutdown() // Update control references so shared_ptrs are freed up BEFORE we shutdown the backends. ClearDevices(); -#ifdef CIFACE_USE_WIN32 - ciface::Win32::DeInit(); -#endif #ifdef CIFACE_USE_ANDROID ciface::Android::Shutdown(); #endif diff --git a/Source/Core/InputCommon/ControllerInterface/InputBackend.cpp b/Source/Core/InputCommon/ControllerInterface/InputBackend.cpp index 422d7e911c..7b52f55caa 100644 --- a/Source/Core/InputCommon/ControllerInterface/InputBackend.cpp +++ b/Source/Core/InputCommon/ControllerInterface/InputBackend.cpp @@ -16,6 +16,10 @@ void InputBackend::UpdateInput(std::vector>& { } +void InputBackend::HandleWindowChange() +{ +} + ControllerInterface& InputBackend::GetControllerInterface() { return m_controller_interface; diff --git a/Source/Core/InputCommon/ControllerInterface/InputBackend.h b/Source/Core/InputCommon/ControllerInterface/InputBackend.h index 80ced7e194..7d75603851 100644 --- a/Source/Core/InputCommon/ControllerInterface/InputBackend.h +++ b/Source/Core/InputCommon/ControllerInterface/InputBackend.h @@ -28,6 +28,8 @@ public: // just add them to the removal list if necessary. virtual void UpdateInput(std::vector>& devices_to_remove); + virtual void HandleWindowChange(); + ControllerInterface& GetControllerInterface(); private: diff --git a/Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp b/Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp index 21e9847964..36b847aa91 100644 --- a/Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Win32/Win32.cpp @@ -20,13 +20,25 @@ #pragma comment(lib, "OneCoreUAP.Lib") -// Dolphin's render window -static HWND s_hwnd; static std::mutex s_populate_mutex; // TODO is this really needed? static Common::Flag s_first_populate_devices_asked; static HCMNOTIFICATION s_notify_handle; +namespace ciface::Win32 +{ +class InputBackend final : public ciface::InputBackend +{ +public: + InputBackend(ControllerInterface* controller_interface); + ~InputBackend(); + + void PopulateDevices() override; + void HandleWindowChange() override; + HWND GetHWND(); +}; +} // namespace ciface::Win32 + _Pre_satisfies_(EventDataSize >= sizeof(CM_NOTIFY_EVENT_DATA)) static DWORD CALLBACK OnDevicesChanged(_In_ HCMNOTIFICATION hNotify, _In_opt_ PVOID Context, _In_ CM_NOTIFY_ACTION Action, @@ -43,8 +55,9 @@ _Pre_satisfies_(EventDataSize >= sizeof(CM_NOTIFY_EVENT_DATA)) static DWORD CALL std::lock_guard lk_population(s_populate_mutex); // TODO: we could easily use the message passed alongside this event, which tells // whether a device was added or removed, to avoid removing old, still connected, devices - g_controller_interface.PlatformPopulateDevices([] { - ciface::DInput::PopulateDevices(s_hwnd); + g_controller_interface.PlatformPopulateDevices([&] { + ciface::DInput::PopulateDevices( + static_cast(Context)->GetHWND()); ciface::XInput::PopulateDevices(); }); } @@ -52,10 +65,21 @@ _Pre_satisfies_(EventDataSize >= sizeof(CM_NOTIFY_EVENT_DATA)) static DWORD CALL return ERROR_SUCCESS; } -void ciface::Win32::Init(void* hwnd) +namespace ciface::Win32 { - s_hwnd = static_cast(hwnd); +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface) +{ + return std::make_unique(controller_interface); +} +HWND InputBackend::GetHWND() +{ + return static_cast(GetControllerInterface().GetWindowSystemInfo().render_window); +} + +InputBackend::InputBackend(ControllerInterface* controller_interface) + : ciface::InputBackend(controller_interface) +{ XInput::Init(); WGInput::Init(); @@ -63,35 +87,32 @@ void ciface::Win32::Init(void* hwnd) .FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE, .u{.DeviceInterface{.ClassGuid = GUID_DEVINTERFACE_HID}}}; const CONFIGRET cfg_rv = - CM_Register_Notification(¬ify_filter, nullptr, OnDevicesChanged, &s_notify_handle); + CM_Register_Notification(¬ify_filter, this, OnDevicesChanged, &s_notify_handle); if (cfg_rv != CR_SUCCESS) { ERROR_LOG_FMT(CONTROLLERINTERFACE, "CM_Register_Notification failed: {:x}", cfg_rv); } } -void ciface::Win32::PopulateDevices(void* hwnd) +void InputBackend::PopulateDevices() { - s_hwnd = static_cast(hwnd); std::lock_guard lk_population(s_populate_mutex); s_first_populate_devices_asked.Set(); - ciface::DInput::PopulateDevices(s_hwnd); + ciface::DInput::PopulateDevices(GetHWND()); ciface::XInput::PopulateDevices(); ciface::WGInput::PopulateDevices(); } -void ciface::Win32::ChangeWindow(void* hwnd) +void InputBackend::HandleWindowChange() { - s_hwnd = static_cast(hwnd); std::lock_guard lk_population(s_populate_mutex); - ciface::DInput::ChangeWindow(s_hwnd); + ciface::DInput::ChangeWindow(GetHWND()); } -void ciface::Win32::DeInit() +InputBackend::~InputBackend() { s_first_populate_devices_asked.Clear(); DInput::DeInit(); - s_hwnd = nullptr; if (s_notify_handle) { @@ -106,3 +127,5 @@ void ciface::Win32::DeInit() XInput::DeInit(); WGInput::DeInit(); } + +} // namespace ciface::Win32 diff --git a/Source/Core/InputCommon/ControllerInterface/Win32/Win32.h b/Source/Core/InputCommon/ControllerInterface/Win32/Win32.h index c842b5c6b5..17e46c54b9 100644 --- a/Source/Core/InputCommon/ControllerInterface/Win32/Win32.h +++ b/Source/Core/InputCommon/ControllerInterface/Win32/Win32.h @@ -3,10 +3,9 @@ #pragma once +#include "InputCommon/ControllerInterface/InputBackend.h" + namespace ciface::Win32 { -void Init(void* hwnd); -void PopulateDevices(void* hwnd); -void ChangeWindow(void* hwnd); -void DeInit(); +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface); } // namespace ciface::Win32