From fa144d3307ae3b2685495fff8beb38a8c20b5d69 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 22 May 2024 00:39:08 +0200 Subject: [PATCH] input/qt: enumerate raw mouse devices once a seconds in the config dialog --- rpcs3/Input/raw_mouse_handler.cpp | 62 +++++++---- rpcs3/Input/raw_mouse_handler.h | 9 +- rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp | 112 +++++++++++++++----- rpcs3/rpcs3qt/raw_mouse_settings_dialog.h | 7 +- 4 files changed, 138 insertions(+), 52 deletions(-) diff --git a/rpcs3/Input/raw_mouse_handler.cpp b/rpcs3/Input/raw_mouse_handler.cpp index 5afbac3c29..02f42a3084 100644 --- a/rpcs3/Input/raw_mouse_handler.cpp +++ b/rpcs3/Input/raw_mouse_handler.cpp @@ -211,9 +211,9 @@ void raw_mouse::update_values(const RAWMOUSE& state) } #endif -raw_mouse_handler::raw_mouse_handler(bool ignore_config) +raw_mouse_handler::raw_mouse_handler(bool is_for_gui) : MouseHandlerBase() - , m_ignore_config(ignore_config) + , m_is_for_gui(is_for_gui) { } @@ -284,31 +284,20 @@ void raw_mouse_handler::Init(const u32 max_connect) type = mouse_handler::raw; - m_thread = std::make_unique>>("Raw Mouse Thread", [this, max_connect]() + if (m_is_for_gui) + { + // No need for a thread. We call update_devices manually. + return; + } + + m_thread = std::make_unique>>("Raw Mouse Thread", [this]() { input_log.notice("raw_mouse_handler: thread started"); while (thread_ctrl::state() != thread_state::aborting) { - enumerate_devices(max_connect); + update_devices(); - // Update mouse info - std::set connected_mice{}; - const u32 now_connect = get_now_connect(connected_mice); - { - std::lock_guard lock(mutex); - - m_info.now_connect = std::min(now_connect, max_connect); - - for (u32 i = 0; i < m_info.max_connect; i++) - { - m_info.status[i] = connected_mice.contains(i) ? CELL_MOUSE_STATUS_CONNECTED : CELL_MOUSE_STATUS_DISCONNECTED; - } - } - -#ifdef _WIN32 - register_raw_input_devices(); -#endif thread_ctrl::wait_for(1'000'000); } @@ -316,6 +305,35 @@ void raw_mouse_handler::Init(const u32 max_connect) }); } +void raw_mouse_handler::update_devices() +{ + u32 max_connect; + { + std::lock_guard lock(mutex); + max_connect = m_info.max_connect; + } + + enumerate_devices(max_connect); + + // Update mouse info + std::set connected_mice{}; + const u32 now_connect = get_now_connect(connected_mice); + { + std::lock_guard lock(mutex); + + m_info.now_connect = std::min(now_connect, m_info.max_connect); + + for (u32 i = 0; i < m_info.max_connect; i++) + { + m_info.status[i] = connected_mice.contains(i) ? CELL_MOUSE_STATUS_CONNECTED : CELL_MOUSE_STATUS_DISCONNECTED; + } + } + +#ifdef _WIN32 + register_raw_input_devices(); +#endif +} + #ifdef _WIN32 void raw_mouse_handler::register_raw_input_devices() { @@ -443,7 +461,7 @@ void raw_mouse_handler::enumerate_devices(u32 max_connect) const std::string device_name = wchar_to_utf8(buf.data()); - if (m_ignore_config) + 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); diff --git a/rpcs3/Input/raw_mouse_handler.h b/rpcs3/Input/raw_mouse_handler.h index 7f43d534c5..933f5d65d8 100644 --- a/rpcs3/Input/raw_mouse_handler.h +++ b/rpcs3/Input/raw_mouse_handler.h @@ -64,7 +64,7 @@ private: class raw_mouse_handler final : public MouseHandlerBase { public: - raw_mouse_handler(bool ignore_config = false); + raw_mouse_handler(bool is_for_gui = false); virtual ~raw_mouse_handler(); void Init(const u32 max_connect) override; @@ -84,10 +84,14 @@ public: } } + void update_devices(); + #ifdef _WIN32 void handle_native_event(const MSG& msg); #endif + shared_mutex m_raw_mutex; + private: u32 get_now_connect(std::set& connected_mice); void enumerate_devices(u32 max_connect); @@ -97,8 +101,7 @@ private: bool m_registered_raw_input_devices = false; #endif - bool m_ignore_config = false; - shared_mutex m_raw_mutex; + bool m_is_for_gui = false; std::map m_raw_mice; std::function m_mouse_press_callback; diff --git a/rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp b/rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp index 5d8e45f667..c3dab9057e 100644 --- a/rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp @@ -6,6 +6,7 @@ #include "Input/raw_mouse_handler.h" #include "util/asm.hpp" +#include #include #include #include @@ -74,6 +75,8 @@ raw_mouse_settings_dialog::raw_mouse_settings_dialog(QWidget* parent) m_buttons = new QButtonGroup(this); connect(m_buttons, &QButtonGroup::idClicked, this, &raw_mouse_settings_dialog::on_button_click); + connect(&m_update_timer, &QTimer::timeout, this, &raw_mouse_settings_dialog::on_enumeration); + connect(&m_remap_timer, &QTimer::timeout, this, [this]() { auto button = m_buttons->button(m_button_id); @@ -117,7 +120,11 @@ raw_mouse_settings_dialog::raw_mouse_settings_dialog(QWidget* parent) handle_device_change(get_current_device_name(index)); }); + on_enumeration(); + handle_device_change(get_current_device_name(0)); + + m_update_timer.start(1000ms); } raw_mouse_settings_dialog::~raw_mouse_settings_dialog() @@ -125,6 +132,54 @@ raw_mouse_settings_dialog::~raw_mouse_settings_dialog() g_raw_mouse_handler.reset(); } +void raw_mouse_settings_dialog::update_combo_box(usz player) +{ + auto& config = ::at32(g_cfg_raw_mouse.players, player); + const std::string device_name = config->device.to_string(); + const QString current_device = QString::fromStdString(device_name); + bool found_device = false; + + QComboBox* combo = ::at32(m_device_combos, player); + + combo->blockSignals(true); + combo->clear(); + combo->addItem(tr("Disabled"), QString()); + + { + std::lock_guard lock(g_raw_mouse_handler->m_raw_mutex); + + const auto& mice = g_raw_mouse_handler->get_mice(); + + for (const auto& [handle, mouse] : mice) + { + const QString name = QString::fromStdString(mouse.device_name()); + const QString& pretty_name = name; // Same ugly device path for now + combo->addItem(pretty_name, name); + + if (current_device == name) + { + found_device = true; + } + } + } + + // Keep configured device in list even if it is not connected + if (!found_device && !current_device.isEmpty()) + { + const QString& pretty_name = current_device; // Same ugly device path for now + combo->addItem(pretty_name, current_device); + } + + // Select index + combo->setCurrentIndex(std::max(0, combo->findData(current_device))); + combo->blockSignals(false); + + if (player == m_tab_widget->currentIndex()) + { + handle_device_change(device_name); + } +} + void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) { ensure(!!tabs); @@ -137,12 +192,11 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) rows = utils::aligned_div(button_count, ++cols); } - const usz players = g_cfg_raw_mouse.players.size(); + constexpr usz players = g_cfg_raw_mouse.players.size(); m_push_buttons.resize(players); ensure(g_raw_mouse_handler); - const auto& mice = g_raw_mouse_handler->get_mice(); const auto insert_button = [this](int id, QPushButton* button) { @@ -156,35 +210,13 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) QGridLayout* grid_layout = new QGridLayout(this); auto& config = ::at32(g_cfg_raw_mouse.players, player); - const QString current_device = QString::fromStdString(config->device.to_string()); - bool found_device = false; QHBoxLayout* h_layout = new QHBoxLayout(this); QGroupBox* gb = new QGroupBox(tr("Device"), this); QComboBox* combo = new QComboBox(this); m_device_combos.push_back(combo); - combo->addItem(tr("Disabled"), QString()); - for (const auto& [handle, mouse] : mice) - { - const QString name = QString::fromStdString(mouse.device_name()); - const QString& pretty_name = name; // Same ugly device path for now - combo->addItem(pretty_name, name); - if (current_device == name) - { - found_device = true; - } - } - - // Keep configured device in list even if it is not connected - if (!found_device && !current_device.isEmpty()) - { - const QString& pretty_name = current_device; // Same ugly device path for now - combo->addItem(pretty_name, current_device); - } - - // Select index - combo->setCurrentIndex(std::max(0, combo->findData(current_device))); + update_combo_box(player); connect(combo, QOverload::of(&QComboBox::currentIndexChanged), this, [this, player, combo](int index) { @@ -257,6 +289,31 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) } } +void raw_mouse_settings_dialog::on_enumeration() +{ + if (!g_raw_mouse_handler) + { + return; + } + + const int player = m_tab_widget->currentIndex(); + QComboBox* combo = ::at32(m_device_combos, player); + + // Don't enumerate while the current dropdown is open + if (combo && combo->view()->isVisible()) + { + return; + } + + g_raw_mouse_handler->update_devices(); + + // Update all dropdowns + for (usz player = 0; player < g_cfg_raw_mouse.players.size(); player++) + { + update_combo_box(player); + } +} + void raw_mouse_settings_dialog::reset_config() { g_cfg_raw_mouse.from_default(); @@ -334,6 +391,8 @@ bool raw_mouse_settings_dialog::is_device_active(const std::string& device_name) return false; } + std::lock_guard lock(g_raw_mouse_handler->m_raw_mutex); + const auto& mice = g_raw_mouse_handler->get_mice(); return std::any_of(mice.cbegin(), mice.cend(), [&device_name](const auto& entry){ return entry.second.device_name() == device_name; }); @@ -394,6 +453,8 @@ void raw_mouse_settings_dialog::on_button_click(int id) return; } + m_update_timer.stop(); + for (auto sb : m_accel_spin_boxes) { sb->setEnabled(false); @@ -480,4 +541,5 @@ void raw_mouse_settings_dialog::reactivate_buttons() m_tab_widget->setEnabled(true); m_mouse_release_timer.start(100ms); + m_update_timer.start(1000ms); } diff --git a/rpcs3/rpcs3qt/raw_mouse_settings_dialog.h b/rpcs3/rpcs3qt/raw_mouse_settings_dialog.h index 91702a0c7c..1ed13efe99 100644 --- a/rpcs3/rpcs3qt/raw_mouse_settings_dialog.h +++ b/rpcs3/rpcs3qt/raw_mouse_settings_dialog.h @@ -25,10 +25,10 @@ public: virtual ~raw_mouse_settings_dialog(); private: + void update_combo_box(usz player); void add_tabs(QTabWidget* tabs); - + void on_enumeration(); void reset_config(); - void on_button_click(int id); void mouse_press(const std::string& device_name, s32 cell_code, bool pressed); void handle_device_change(const std::string& device_name); @@ -56,6 +56,9 @@ private: QTimer m_mouse_release_timer; bool m_disable_mouse_release_event = false; + // Update Timer + QTimer m_update_timer; + protected: bool eventFilter(QObject* object, QEvent* event) override; };