From 657acc90e4514a7d4f4c1844382f334e6869bbb8 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Thu, 23 May 2024 01:20:25 +0200 Subject: [PATCH] input: fix ingame raw mouse enumeration --- rpcs3/Input/raw_mouse_handler.cpp | 97 ++++++++++++++++++++----------- rpcs3/Input/raw_mouse_handler.h | 5 +- 2 files changed, 66 insertions(+), 36 deletions(-) diff --git a/rpcs3/Input/raw_mouse_handler.cpp b/rpcs3/Input/raw_mouse_handler.cpp index 02f42a3084..7adc1ccb70 100644 --- a/rpcs3/Input/raw_mouse_handler.cpp +++ b/rpcs3/Input/raw_mouse_handler.cpp @@ -313,7 +313,58 @@ void raw_mouse_handler::update_devices() max_connect = m_info.max_connect; } - enumerate_devices(max_connect); + { + std::map enumerated = enumerate_devices(max_connect); + + std::lock_guard lock(m_raw_mutex); + + if (m_is_for_gui) + { + // Use the new devices + m_raw_mice = std::move(enumerated); + } + else + { + // Integrate the new devices + std::map updated_mice; + + for (u32 i = 0; i < std::min(max_connect, ::size32(g_cfg_raw_mouse.players)); i++) + { + const auto& player = ::at32(g_cfg_raw_mouse.players, i); + const std::string device_name = player->device.to_string(); + + // Check if the configured device for this player is connected + if (auto it = std::find_if(enumerated.begin(), enumerated.end(), [&device_name](const auto& entry){ return entry.second.device_name() == device_name; }); + it != enumerated.end()) + { + // Check if the device was already known + auto it_exists = m_raw_mice.find(it->first); + const bool exists = it_exists != m_raw_mice.end(); + + // Copy by value to allow for the same device for multiple players + raw_mouse& mouse = updated_mice[it->first]; + mouse = exists ? it_exists->second : it->second; + mouse.set_index(i); + + if (!exists) + { + input_log.notice("raw_mouse_handler: added new device for player %d: '%s'", i, device_name); + } + } + } + + // Log disconnected devices + for (const auto& [handle, mouse] : m_raw_mice) + { + if (!updated_mice.contains(handle)) + { + input_log.notice("raw_mouse_handler: removed device for player %d: '%s'", mouse.index(), mouse.device_name()); + } + } + + m_raw_mice = std::move(updated_mice); + } + } // Update mouse info std::set connected_mice{}; @@ -388,17 +439,15 @@ u32 raw_mouse_handler::get_now_connect(std::set& connected_mice) return now_connect; } -void raw_mouse_handler::enumerate_devices(u32 max_connect) +std::map raw_mouse_handler::enumerate_devices(u32 max_connect) { - input_log.notice("raw_mouse_handler: enumerating devices (max_connect=%d)", max_connect); + input_log.trace("raw_mouse_handler: enumerating devices (max_connect=%d)", max_connect); - std::lock_guard lock(m_raw_mutex); - - m_raw_mice.clear(); + std::map raw_mice; if (max_connect == 0) { - return; + return raw_mice; } Timer timer{}; @@ -409,12 +458,12 @@ void raw_mouse_handler::enumerate_devices(u32 max_connect) if (res == umax) { input_log.error("raw_mouse_handler: GetRawInputDeviceList (count) failed: %s", fmt::win_error{GetLastError(), nullptr}); - return; + return raw_mice; } if (num_devices == 0) { - return; + return raw_mice; } std::vector device_list(num_devices); @@ -423,16 +472,11 @@ void raw_mouse_handler::enumerate_devices(u32 max_connect) if (res == umax) { input_log.error("raw_mouse_handler: GetRawInputDeviceList (fetch) failed: %s", fmt::win_error{GetLastError(), nullptr}); - return; + return raw_mice; } for (RAWINPUTDEVICELIST& device : device_list) { - if (m_raw_mice.size() >= max_connect) - { - return; - } - if (device.dwType != RIM_TYPEMOUSE) { continue; @@ -460,29 +504,14 @@ void raw_mouse_handler::enumerate_devices(u32 max_connect) } const std::string device_name = wchar_to_utf8(buf.data()); + input_log.trace("raw_mouse_handler: found device: '%s'", device_name); - if (m_is_for_gui) - { - input_log.notice("raw_mouse_handler: adding device %d: '%s'", m_raw_mice.size(), device_name); - m_raw_mice[device.hDevice] = raw_mouse(::size32(m_raw_mice), device_name, device.hDevice, this); - continue; - } - - for (u32 i = 0; i < std::min(max_connect, ::size32(g_cfg_raw_mouse.players)); i++) - { - const auto& player = ::at32(g_cfg_raw_mouse.players, i); - - if (player && player->device.to_string() == device_name) - { - input_log.notice("raw_mouse_handler: adding device %d: '%s'", m_raw_mice.size(), device_name); - m_raw_mice[device.hDevice] = raw_mouse(i, device_name, device.hDevice, this); - break; - } - } + raw_mice[device.hDevice] = raw_mouse(::size32(raw_mice), device_name, device.hDevice, this); } #endif - input_log.notice("raw_mouse_handler: found %d devices in %f ms", m_raw_mice.size(), timer.GetElapsedTimeInMilliSec()); + input_log.trace("raw_mouse_handler: found %d devices in %f ms", raw_mice.size(), timer.GetElapsedTimeInMilliSec()); + return raw_mice; } #ifdef _WIN32 diff --git a/rpcs3/Input/raw_mouse_handler.h b/rpcs3/Input/raw_mouse_handler.h index 933f5d65d8..a49ecdeb66 100644 --- a/rpcs3/Input/raw_mouse_handler.h +++ b/rpcs3/Input/raw_mouse_handler.h @@ -3,7 +3,7 @@ #include "Emu/Io/MouseHandler.h" #include "Emu/RSX/display.h" #include "Utilities/Config.h" -#include "Utilities/Mutex.h" +#include "Utilities/mutex.h" #include "Utilities/Thread.h" #ifdef _WIN32 @@ -42,6 +42,7 @@ public: const std::string& device_name() const { return m_device_name; } u32 index() const { return m_index; } + void set_index(u32 index) { m_index = index; } private: static std::pair get_mouse_button(const cfg::string& button); @@ -94,7 +95,7 @@ public: private: u32 get_now_connect(std::set& connected_mice); - void enumerate_devices(u32 max_connect); + std::map enumerate_devices(u32 max_connect); #ifdef _WIN32 void register_raw_input_devices();