From 9941c54911e8ab713aad1f156511bf6552ca4b3b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Mar 2024 01:31:05 -0500 Subject: [PATCH 1/8] InputCommon: Provide WindowSystemInfo getter for ControllerInterface. --- .../InputCommon/ControllerInterface/ControllerInterface.cpp | 5 +++++ .../InputCommon/ControllerInterface/ControllerInterface.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index b7a9c7f307..24653acdd1 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -423,6 +423,11 @@ ciface::InputChannel ControllerInterface::GetCurrentInputChannel() return tls_input_channel; } +WindowSystemInfo ControllerInterface::GetWindowSystemInfo() const +{ + return m_wsi; +} + void ControllerInterface::SetAspectRatioAdjustment(float value) { m_aspect_ratio_adjustment = value; diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h index 837e5135d5..d3998a4839 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.h @@ -122,6 +122,8 @@ public: static void SetCurrentInputChannel(ciface::InputChannel); static ciface::InputChannel GetCurrentInputChannel(); + WindowSystemInfo GetWindowSystemInfo() const; + private: void ClearDevices(); From 498584ac777ac4fc452a83a4380889ef2c99d216 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Mar 2024 01:31:30 -0500 Subject: [PATCH 2/8] InputCommon: Add Quartz InputBackend class. --- .../ControllerInterface.cpp | 11 +--------- .../ControllerInterface/Quartz/Quartz.h | 5 +++-- .../ControllerInterface/Quartz/Quartz.mm | 22 ++++++++++++++----- .../Quartz/QuartzKeyboardAndMouse.mm | 1 + 4 files changed, 21 insertions(+), 18 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 24653acdd1..ba3740214a 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -65,7 +65,7 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi) // nothing needed #endif #ifdef CIFACE_USE_OSX -// nothing needed for Quartz + m_input_backends.emplace_back(ciface::Quartz::CreateInputBackend(this)); #endif #ifdef CIFACE_USE_SDL m_input_backends.emplace_back(ciface::SDL::CreateInputBackend(this)); @@ -166,12 +166,6 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) if (m_wsi.type == WindowSystemType::X11) ciface::XInput2::PopulateDevices(m_wsi.render_window); #endif -#ifdef CIFACE_USE_OSX - if (m_wsi.type == WindowSystemType::MacOS) - { - ciface::Quartz::PopulateDevices(m_wsi.render_window); - } -#endif #ifdef CIFACE_USE_ANDROID ciface::Android::PopulateDevices(); #endif @@ -223,9 +217,6 @@ void ControllerInterface::Shutdown() #ifdef CIFACE_USE_XLIB // nothing needed #endif -#ifdef CIFACE_USE_OSX - ciface::Quartz::DeInit(); -#endif #ifdef CIFACE_USE_ANDROID ciface::Android::Shutdown(); #endif diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h index 8818425344..34219e9828 100644 --- a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h +++ b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h @@ -3,8 +3,9 @@ #pragma once +#include "InputCommon/ControllerInterface/InputBackend.h" + namespace ciface::Quartz { -void PopulateDevices(void* window); -void DeInit(); +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface); } // namespace ciface::Quartz diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm index 22dc4074d9..75054f08b9 100644 --- a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm +++ b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm @@ -7,15 +7,25 @@ namespace ciface::Quartz { -void PopulateDevices(void* window) +class InputBackend final : public ciface::InputBackend { - if (!window) +public: + using ciface::InputBackend::InputBackend; + void PopulateDevices() override; +}; + +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface) +{ + return std::make_unique(controller_interface); +} + +void InputBackend::PopulateDevices() +{ + const WindowSystemInfo wsi = GetControllerInterface().GetWindowSystemInfo(); + if (wsi.type != WindowSystemType::MacOS) return; - g_controller_interface.AddDevice(std::make_shared(window)); + GetControllerInterface().AddDevice(std::make_shared(wsi.render_window)); } -void DeInit() -{ -} } // namespace ciface::Quartz diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm b/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm index e41c370edf..b21eb48ab4 100644 --- a/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm +++ b/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm @@ -12,6 +12,7 @@ #include "Core/Host.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "InputCommon/ControllerInterface/Quartz/Quartz.h" /// Helper class to get window position data from threads other than the main thread @interface DolWindowPositionObserver : NSObject From 8098be3dfa07aa529f61ea2ec4ff4077ef01b2d8 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Mar 2024 01:42:32 -0500 Subject: [PATCH 3/8] InputCommon: Add XInput2 InputBackend class. --- .../ControllerInterface.cpp | 9 +------ .../ControllerInterface/Xlib/XInput2.cpp | 24 ++++++++++++++++--- .../ControllerInterface/Xlib/XInput2.h | 3 ++- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index ba3740214a..fa44e8bf79 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -62,7 +62,7 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi) ciface::Win32::Init(wsi.render_window); #endif #ifdef CIFACE_USE_XLIB -// nothing needed + m_input_backends.emplace_back(ciface::XInput2::CreateInputBackend(this)); #endif #ifdef CIFACE_USE_OSX m_input_backends.emplace_back(ciface::Quartz::CreateInputBackend(this)); @@ -162,10 +162,6 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) #ifdef CIFACE_USE_WIN32 ciface::Win32::PopulateDevices(m_wsi.render_window); #endif -#ifdef CIFACE_USE_XLIB - if (m_wsi.type == WindowSystemType::X11) - ciface::XInput2::PopulateDevices(m_wsi.render_window); -#endif #ifdef CIFACE_USE_ANDROID ciface::Android::PopulateDevices(); #endif @@ -214,9 +210,6 @@ void ControllerInterface::Shutdown() #ifdef CIFACE_USE_WIN32 ciface::Win32::DeInit(); #endif -#ifdef CIFACE_USE_XLIB -// nothing needed -#endif #ifdef CIFACE_USE_ANDROID ciface::Android::Shutdown(); #endif diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp index f041dd16a1..5de0840354 100644 --- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp @@ -66,9 +66,27 @@ constexpr int XINPUT_MAJOR = 2, XINPUT_MINOR = 1; namespace ciface::XInput2 { -// This function will add zero or more KeyboardMouse objects to devices. -void PopulateDevices(void* const hwnd) +class InputBackend final : public ciface::InputBackend { +public: + using ciface::InputBackend::InputBackend; + void PopulateDevices() override; +}; + +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface) +{ + return std::make_unique(controller_interface); +} + +// This function will add zero or more KeyboardMouse objects to devices. +void InputBackend::PopulateDevices() +{ + const WindowSystemInfo wsi = GetControllerInterface().GetWindowSystemInfo(); + if (wsi.type != WindowSystemType::X11) + return; + + const auto hwnd = wsi.render_window; + Display* dpy = XOpenDisplay(nullptr); // xi_opcode is important; it will be used to identify XInput events by @@ -119,7 +137,7 @@ void PopulateDevices(void* const hwnd) } // Since current_master is a master pointer, its attachment must // be a master keyboard. - g_controller_interface.AddDevice( + GetControllerInterface().AddDevice( std::make_shared((Window)hwnd, xi_opcode, current_master->deviceid, current_master->attachment, scroll_increment)); } diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h index a8960c1d23..427c81b18a 100644 --- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h +++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.h @@ -16,10 +16,11 @@ extern "C" { #include "Common/CommonTypes.h" #include "Common/Matrix.h" #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "InputCommon/ControllerInterface/InputBackend.h" namespace ciface::XInput2 { -void PopulateDevices(void* const hwnd); +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface); class KeyboardMouse : public Core::Device { From 2ac59bf5813ab44dc3e7f067913b0e951e8b6199 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Mar 2024 01:46:33 -0500 Subject: [PATCH 4/8] InputCommon: Add Pipes InputBackend class. --- .../ControllerInterface/ControllerInterface.cpp | 5 +---- .../ControllerInterface/Pipes/Pipes.cpp | 14 +++++++++++++- .../InputCommon/ControllerInterface/Pipes/Pipes.h | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index fa44e8bf79..71dea5512c 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -77,7 +77,7 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi) m_input_backends.emplace_back(ciface::evdev::CreateInputBackend(this)); #endif #ifdef CIFACE_USE_PIPES -// nothing needed + m_input_backends.emplace_back(ciface::Pipes::CreateInputBackend(this)); #endif #ifdef CIFACE_USE_DUALSHOCKUDPCLIENT m_input_backends.emplace_back(ciface::DualShockUDPClient::CreateInputBackend(this)); @@ -165,9 +165,6 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) #ifdef CIFACE_USE_ANDROID ciface::Android::PopulateDevices(); #endif -#ifdef CIFACE_USE_PIPES - ciface::Pipes::PopulateDevices(); -#endif for (auto& backend : m_input_backends) backend->PopulateDevices(); diff --git a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp index af7ad7dc6f..1a2052089e 100644 --- a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.cpp @@ -39,7 +39,19 @@ static double StringToDouble(const std::string& text) return result; } -void PopulateDevices() +class InputBackend final : public ciface::InputBackend +{ +public: + using ciface::InputBackend::InputBackend; + void PopulateDevices() override; +}; + +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface) +{ + return std::make_unique(controller_interface); +} + +void InputBackend::PopulateDevices() { // Search the Pipes directory for files that we can open in read-only, // non-blocking mode. The device name is the virtual name of the file. diff --git a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h index 53fefd0cb5..857d5e8128 100644 --- a/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h +++ b/Source/Core/InputCommon/ControllerInterface/Pipes/Pipes.h @@ -21,7 +21,7 @@ namespace ciface::Pipes // SET {L, R} [0, 1] // SET {MAIN, C} [0, 1] [0, 1] -void PopulateDevices(); +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface); class PipeDevice : public Core::Device { From 341f99a3f1feaf981bb704909b2dc3b3a0b70245 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Mar 2024 02:09:31 -0500 Subject: [PATCH 5/8] InputCommon: Add Win32 InputBackend class. --- .../ControllerInterface.cpp | 13 ++--- .../ControllerInterface/InputBackend.cpp | 4 ++ .../ControllerInterface/InputBackend.h | 2 + .../ControllerInterface/Win32/Win32.cpp | 53 +++++++++++++------ .../ControllerInterface/Win32/Win32.h | 7 ++- 5 files changed, 50 insertions(+), 29 deletions(-) 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 From 3665f7abac4d5c93936f0325fe40bba73703813d Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Mar 2024 02:20:54 -0500 Subject: [PATCH 6/8] InputCommon: Implement xlib window change logic. --- .../ControllerInterface/ControllerInterface.cpp | 2 +- .../ControllerInterface/Xlib/XInput2.cpp | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 8f7bed3af1..9c272fdec4 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -128,7 +128,7 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) // or removing them as we are populating them (causing missing or duplicate devices). std::lock_guard lk_population(m_devices_population_mutex); -#if defined(CIFACE_USE_WIN32) && !defined(CIFACE_USE_XLIB) && !defined(CIFACE_USE_OSX) +#if defined(CIFACE_USE_WIN32) && !defined(CIFACE_USE_OSX) // If only the window changed, avoid removing and re-adding all devices. // Instead only refresh devices that require the window handle. if (reason == RefreshReason::WindowChangeOnly) diff --git a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp index 5de0840354..e4b717e3af 100644 --- a/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Xlib/XInput2.cpp @@ -66,11 +66,14 @@ constexpr int XINPUT_MAJOR = 2, XINPUT_MINOR = 1; namespace ciface::XInput2 { +constexpr std::string_view SOURCE_NAME = "XInput2"; + class InputBackend final : public ciface::InputBackend { public: using ciface::InputBackend::InputBackend; void PopulateDevices() override; + void HandleWindowChange() override; }; std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface) @@ -78,6 +81,14 @@ std::unique_ptr CreateInputBackend(ControllerInterface* co return std::make_unique(controller_interface); } +void InputBackend::HandleWindowChange() +{ + GetControllerInterface().RemoveDevice( + [](const auto* dev) { return dev->GetSource() == SOURCE_NAME; }, true); + + PopulateDevices(); +} + // This function will add zero or more KeyboardMouse objects to devices. void InputBackend::PopulateDevices() { @@ -400,7 +411,7 @@ std::string KeyboardMouse::GetName() const std::string KeyboardMouse::GetSource() const { - return "XInput2"; + return std::string(SOURCE_NAME); } KeyboardMouse::Key::Key(Display* const display, KeyCode keycode, const char* keyboard) From 8583b6751abe08334329c7cae99c83df82683ce2 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Mar 2024 02:28:18 -0500 Subject: [PATCH 7/8] InputCommon: Handle window change in Quartz. --- .../ControllerInterface/ControllerInterface.cpp | 3 +-- .../ControllerInterface/Quartz/Quartz.h | 4 ++++ .../ControllerInterface/Quartz/Quartz.mm | 15 +++++++++++++++ .../Quartz/QuartzKeyboardAndMouse.mm | 2 +- 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index 9c272fdec4..b82cba645e 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -128,7 +128,6 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) // or removing them as we are populating them (causing missing or duplicate devices). std::lock_guard lk_population(m_devices_population_mutex); -#if defined(CIFACE_USE_WIN32) && !defined(CIFACE_USE_OSX) // If only the window changed, avoid removing and re-adding all devices. // Instead only refresh devices that require the window handle. if (reason == RefreshReason::WindowChangeOnly) @@ -140,9 +139,9 @@ void ControllerInterface::RefreshDevices(RefreshReason reason) if (m_populating_devices_counter.fetch_sub(1) == 1) InvokeDevicesChangedCallbacks(); + return; } -#endif m_populating_devices_counter.fetch_add(1); diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h index 34219e9828..b2c6906e42 100644 --- a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h +++ b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.h @@ -3,9 +3,13 @@ #pragma once +#include + #include "InputCommon/ControllerInterface/InputBackend.h" namespace ciface::Quartz { +std::string GetSourceName(); + std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface); } // namespace ciface::Quartz diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm index 75054f08b9..5d52595835 100644 --- a/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm +++ b/Source/Core/InputCommon/ControllerInterface/Quartz/Quartz.mm @@ -7,11 +7,17 @@ namespace ciface::Quartz { +std::string GetSourceName() +{ + return "Quartz"; +} + class InputBackend final : public ciface::InputBackend { public: using ciface::InputBackend::InputBackend; void PopulateDevices() override; + void HandleWindowChange() override; }; std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface) @@ -19,6 +25,15 @@ std::unique_ptr CreateInputBackend(ControllerInterface* co return std::make_unique(controller_interface); } +void InputBackend::HandleWindowChange() +{ + const std::string source_name = GetSourceName(); + GetControllerInterface().RemoveDevice( + [&](const auto* dev) { return dev->GetSource() == source_name; }, true); + + PopulateDevices(); +} + void InputBackend::PopulateDevices() { const WindowSystemInfo wsi = GetControllerInterface().GetWindowSystemInfo(); diff --git a/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm b/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm index b21eb48ab4..55f212900d 100644 --- a/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm +++ b/Source/Core/InputCommon/ControllerInterface/Quartz/QuartzKeyboardAndMouse.mm @@ -280,7 +280,7 @@ std::string KeyboardAndMouse::GetName() const std::string KeyboardAndMouse::GetSource() const { - return "Quartz"; + return Quartz::GetSourceName(); } ControlState KeyboardAndMouse::Cursor::GetState() const From a9a9fdd9e903d47ec83aa7385e7be54871abbf0b Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 11 Mar 2024 02:36:07 -0500 Subject: [PATCH 8/8] InputCommon: Add Android InputBackend class. --- .../ControllerInterface/Android/Android.cpp | 30 +++++++++++++++---- .../ControllerInterface/Android/Android.h | 7 ++--- .../ControllerInterface.cpp | 10 +------ 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp index 50858cd3de..69f0e5b5ec 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.cpp @@ -23,6 +23,7 @@ #include "InputCommon/ControllerInterface/ControllerInterface.h" +#include "InputCommon/ControllerInterface/InputBackend.h" #include "jni/AndroidCommon/AndroidCommon.h" #include "jni/AndroidCommon/IDCache.h" #include "jni/Input/CoreDevice.h" @@ -444,6 +445,23 @@ std::shared_ptr FindDevice(jint device_id) namespace ciface::Android { +class InputBackend final : public ciface::InputBackend +{ +public: + using ciface::InputBackend::InputBackend; + ~InputBackend(); + void PopulateDevices() override; + +private: + void AddDevice(JNIEnv* env, int device_id); + void AddSensorDevice(JNIEnv* env); +}; + +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface) +{ + return std::make_unique(controller_interface); +} + class AndroidInput : public Core::Device::Input { public: @@ -885,7 +903,7 @@ void Init() s_controller_interface_register_input_device_listener); } -void Shutdown() +InputBackend::~InputBackend() { JNIEnv* env = IDCache::GetEnvForThread(); @@ -903,7 +921,7 @@ void Shutdown() env->DeleteGlobalRef(s_keycodes_array); } -static void AddDevice(JNIEnv* env, int device_id) +void InputBackend::AddDevice(JNIEnv* env, int device_id) { jobject input_device = env->CallStaticObjectMethod(s_input_device_class, s_input_device_get_device, device_id); @@ -921,7 +939,7 @@ static void AddDevice(JNIEnv* env, int device_id) if (device->Inputs().empty() && device->Outputs().empty()) return; - g_controller_interface.AddDevice(device); + GetControllerInterface().AddDevice(device); Core::DeviceQualifier qualifier; qualifier.FromDevice(device.get()); @@ -936,7 +954,7 @@ static void AddDevice(JNIEnv* env, int device_id) env->DeleteLocalRef(j_qualifier); } -static void AddSensorDevice(JNIEnv* env) +void InputBackend::AddSensorDevice(JNIEnv* env) { // Device sensors (accelerometer, etc.) aren't associated with any Android InputDevice. // Create an otherwise empty Dolphin input device so that they have somewhere to live. @@ -946,7 +964,7 @@ static void AddSensorDevice(JNIEnv* env) if (device->Inputs().empty() && device->Outputs().empty()) return; - g_controller_interface.AddDevice(device); + GetControllerInterface().AddDevice(device); Core::DeviceQualifier qualifier; qualifier.FromDevice(device.get()); @@ -959,7 +977,7 @@ static void AddSensorDevice(JNIEnv* env) env->DeleteLocalRef(j_qualifier); } -void PopulateDevices() +void InputBackend::PopulateDevices() { INFO_LOG_FMT(CONTROLLERINTERFACE, "Android populating devices"); diff --git a/Source/Core/InputCommon/ControllerInterface/Android/Android.h b/Source/Core/InputCommon/ControllerInterface/Android/Android.h index 8b8478d7ac..e63ac4f2da 100644 --- a/Source/Core/InputCommon/ControllerInterface/Android/Android.h +++ b/Source/Core/InputCommon/ControllerInterface/Android/Android.h @@ -3,11 +3,10 @@ #pragma once +#include "InputCommon/ControllerInterface/InputBackend.h" + namespace ciface::Android { -void Init(); -void Shutdown(); - -void PopulateDevices(); +std::unique_ptr CreateInputBackend(ControllerInterface* controller_interface); } // namespace ciface::Android diff --git a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp index b82cba645e..ab266292bc 100644 --- a/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp +++ b/Source/Core/InputCommon/ControllerInterface/ControllerInterface.cpp @@ -71,7 +71,7 @@ void ControllerInterface::Initialize(const WindowSystemInfo& wsi) m_input_backends.emplace_back(ciface::SDL::CreateInputBackend(this)); #endif #ifdef CIFACE_USE_ANDROID - ciface::Android::Init(); + m_input_backends.emplace_back(ciface::Android::CreateInputBackend(this)); #endif #ifdef CIFACE_USE_EVDEV m_input_backends.emplace_back(ciface::evdev::CreateInputBackend(this)); @@ -157,10 +157,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_ANDROID - ciface::Android::PopulateDevices(); -#endif - for (auto& backend : m_input_backends) backend->PopulateDevices(); @@ -199,10 +195,6 @@ void ControllerInterface::Shutdown() // Update control references so shared_ptrs are freed up BEFORE we shutdown the backends. ClearDevices(); -#ifdef CIFACE_USE_ANDROID - ciface::Android::Shutdown(); -#endif - // Empty the container of input backends to deconstruct and deinitialize them. m_input_backends.clear();