From 5a08ae4f4159db185fe100b697e082a30d569754 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Mon, 20 May 2024 14:01:20 +0200 Subject: [PATCH] input/qt: let user choose raw mouse device --- rpcs3/Input/raw_mouse_config.h | 2 + rpcs3/Input/raw_mouse_handler.cpp | 38 ++++++++++-- rpcs3/Input/raw_mouse_handler.h | 10 +++- rpcs3/rpcs3qt/gui_application.cpp | 9 ++- rpcs3/rpcs3qt/gui_application.h | 3 + rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp | 65 +++++++++++++++++++-- rpcs3/rpcs3qt/raw_mouse_settings_dialog.h | 4 ++ 7 files changed, 118 insertions(+), 13 deletions(-) diff --git a/rpcs3/Input/raw_mouse_config.h b/rpcs3/Input/raw_mouse_config.h index eb9b5f5a69..e44ed01f96 100644 --- a/rpcs3/Input/raw_mouse_config.h +++ b/rpcs3/Input/raw_mouse_config.h @@ -12,6 +12,8 @@ struct raw_mouse_config : cfg::node public: using cfg::node::node; + cfg::string device{this, "Device", ""}; + cfg::_float<10, 1000> mouse_acceleration{ this, "Mouse Acceleration", 100.0f, true }; cfg::string mouse_button_1{this, "Button 1", "Button 1"}; diff --git a/rpcs3/Input/raw_mouse_handler.cpp b/rpcs3/Input/raw_mouse_handler.cpp index e691b8fce4..ccd585a620 100644 --- a/rpcs3/Input/raw_mouse_handler.cpp +++ b/rpcs3/Input/raw_mouse_handler.cpp @@ -214,6 +214,12 @@ void raw_mouse::update_values(const RAWMOUSE& state) } #endif +raw_mouse_handler::raw_mouse_handler(bool ignore_config) + : MouseHandlerBase() + , m_ignore_config(ignore_config) +{ +} + raw_mouse_handler::~raw_mouse_handler() { if (m_raw_mice.empty()) @@ -253,7 +259,16 @@ void raw_mouse_handler::Init(const u32 max_connect) m_mice.clear(); - for (u32 i = 0; i < std::min(::size32(m_raw_mice), max_connect); i++) + // Get max device index + u32 now_connect = 0; + std::set connected_mice{}; + for (const auto& [handle, mouse] : m_raw_mice) + { + now_connect = std::max(now_connect, mouse.index()); + connected_mice.insert(mouse.index()); + } + + for (u32 i = 0; i < now_connect; i++) { m_mice.emplace_back(Mouse()); } @@ -265,7 +280,7 @@ void raw_mouse_handler::Init(const u32 max_connect) for (u32 i = 0; i < m_info.now_connect; i++) { - m_info.status[i] = CELL_MOUSE_STATUS_CONNECTED; + m_info.status[i] = connected_mice.contains(i) ? CELL_MOUSE_STATUS_CONNECTED : CELL_MOUSE_STATUS_DISCONNECTED; m_info.mode[i] = CELL_MOUSE_INFO_TABLET_MOUSE_MODE; m_info.tablet_is_supported[i] = CELL_MOUSE_INFO_TABLET_NOT_SUPPORTED; m_info.vendor_id[0] = 0x1234; @@ -371,9 +386,24 @@ void raw_mouse_handler::enumerate_devices(u32 max_connect) const std::string device_name = wchar_to_utf8(buf.data()); - input_log.notice("raw_mouse_handler: adding device %d: '%s'", m_raw_mice.size(), device_name); + if (m_ignore_config) + { + 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; + } - m_raw_mice[device.hDevice] = raw_mouse(::size32(m_raw_mice), device_name, device.hDevice, this); + 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; + } + } } #endif diff --git a/rpcs3/Input/raw_mouse_handler.h b/rpcs3/Input/raw_mouse_handler.h index e2af43a9e2..9f4494d91a 100644 --- a/rpcs3/Input/raw_mouse_handler.h +++ b/rpcs3/Input/raw_mouse_handler.h @@ -2,6 +2,7 @@ #include "Emu/Io/MouseHandler.h" #include "Emu/RSX/display.h" +#include "Utilities/Config.h" #ifdef _WIN32 #include @@ -37,6 +38,9 @@ public: void update_values(const RAWMOUSE& state); #endif + const std::string& device_name() const { return m_device_name; } + u32 index() const { return m_index; } + private: static std::pair get_mouse_button(const cfg::string& button); @@ -57,13 +61,14 @@ private: class raw_mouse_handler final : public MouseHandlerBase { - using MouseHandlerBase::MouseHandlerBase; - public: + raw_mouse_handler(bool ignore_config = false); virtual ~raw_mouse_handler(); void Init(const u32 max_connect) override; + const std::map& get_mice() const { return m_raw_mice; }; + #ifdef _WIN32 void handle_native_event(const MSG& msg); #endif @@ -71,5 +76,6 @@ public: private: void enumerate_devices(u32 max_connect); + bool m_ignore_config = false; std::map m_raw_mice; }; diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index a9c7ed8a4f..1079cb6efa 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -1,3 +1,4 @@ +#include "stdafx.h" #include "gui_application.h" #include "qt_utils.h" @@ -22,7 +23,6 @@ #include "Emu/vfs_config.h" #include "util/init_mutex.hpp" #include "util/console.h" -#include "Input/raw_mouse_handler.h" #include "trophy_notification_helper.h" #include "save_data_dialog.h" #include "msg_dialog_frame.h" @@ -58,6 +58,8 @@ LOG_CHANNEL(gui_log, "GUI"); +std::unique_ptr g_raw_mouse_handler; + [[noreturn]] void report_fatal_error(std::string_view text, bool is_html = false, bool include_help_text = true); gui_application::gui_application(int& argc, char** argv) : QApplication(argc, argv) @@ -1124,6 +1126,11 @@ bool gui_application::native_event_filter::nativeEventFilter([[maybe_unused]] co { static_cast(handler)->handle_native_event(*msg); } + + if (g_raw_mouse_handler) + { + g_raw_mouse_handler->handle_native_event(*msg); + } } } #endif diff --git a/rpcs3/rpcs3qt/gui_application.h b/rpcs3/rpcs3qt/gui_application.h index 6a0be442c8..87b86d9bc3 100644 --- a/rpcs3/rpcs3qt/gui_application.h +++ b/rpcs3/rpcs3qt/gui_application.h @@ -13,6 +13,7 @@ #include "main_application.h" #include "Emu/System.h" +#include "Input/raw_mouse_handler.h" #include #include @@ -24,6 +25,8 @@ class gui_settings; class emu_settings; class persistent_settings; +extern std::unique_ptr g_raw_mouse_handler; // Only used for GUI + /** RPCS3 GUI Application Class * The main point of this class is to do application initialization, to hold the main and game windows and to initialize callbacks. */ diff --git a/rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp b/rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp index ac52fff8cd..f737545063 100644 --- a/rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp +++ b/rpcs3/rpcs3qt/raw_mouse_settings_dialog.cpp @@ -1,12 +1,12 @@ #include "stdafx.h" #include "raw_mouse_settings_dialog.h" #include "localized_emu.h" +#include "gui_application.h" #include "Input/raw_mouse_config.h" #include "Input/raw_mouse_handler.h" #include "util/asm.hpp" #include -#include #include #include #include @@ -68,6 +68,9 @@ raw_mouse_settings_dialog::raw_mouse_settings_dialog(QWidget* parent) cfg_log.notice("Could not load raw mouse config. Using defaults."); } + g_raw_mouse_handler = std::make_unique(true); + g_raw_mouse_handler->Init(::size32(g_cfg_raw_mouse.players)); + add_tabs(tabs); v_layout->addWidget(tabs); @@ -75,6 +78,11 @@ raw_mouse_settings_dialog::raw_mouse_settings_dialog(QWidget* parent) setLayout(v_layout); } +raw_mouse_settings_dialog::~raw_mouse_settings_dialog() +{ + g_raw_mouse_handler.reset(); +} + void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) { ensure(!!tabs); @@ -92,6 +100,9 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) m_combos.resize(players); + ensure(g_raw_mouse_handler); + const auto& mice = g_raw_mouse_handler->get_mice(); + for (usz player = 0; player < players; player++) { QWidget* widget = new QWidget(this); @@ -99,7 +110,38 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) auto& config = ::at32(g_cfg_raw_mouse.players, player); - for (int i = 0, row = 0, col = 0; i < static_cast(button_count); i++, row++) + 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); + } + combo->setCurrentText(QString::fromStdString(config->device.to_string())); + connect(combo, QOverload::of(&QComboBox::currentIndexChanged), this, [this, player, combo](int index) + { + if (index < 0 || !combo) + return; + + const QVariant data = combo->itemData(index); + if (!data.isValid() || !data.canConvert()) + return; + + auto& config = ::at32(g_cfg_raw_mouse.players, player)->device; + config.from_string(data.toString().toStdString()); + }); + + h_layout->addWidget(combo); + gb->setLayout(h_layout); + grid_layout->addWidget(gb, 0, 0, 1, 2); + + const int first_row = grid_layout->rowCount(); + + for (int i = 0, row = first_row, col = 0; i < static_cast(button_count); i++, row++) { const int cell_code = get_mouse_button_code(i); const QString translated_cell_button = localized_emu::translated_mouse_button(cell_code); @@ -134,9 +176,9 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) ::at32(g_cfg_raw_mouse.players, player)->get_button(cell_code).from_string(data.toString().toStdString()); }); - if (row >= rows) + if (row >= rows + first_row) { - row = 0; + row = first_row; col++; } @@ -146,9 +188,10 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs) grid_layout->addWidget(gb, row, col); } - QHBoxLayout* h_layout = new QHBoxLayout(this); - QGroupBox* gb = new QGroupBox(tr("Mouse Acceleration"), this); + h_layout = new QHBoxLayout(this); + gb = new QGroupBox(tr("Mouse Acceleration"), this); QDoubleSpinBox* mouse_acceleration_spin_box = new QDoubleSpinBox(this); + m_accel_spin_boxes.push_back(mouse_acceleration_spin_box); mouse_acceleration_spin_box->setRange(0.1, 10.0); mouse_acceleration_spin_box->setValue(config->mouse_acceleration.get() / 100.0); connect(mouse_acceleration_spin_box, QOverload::of(&QDoubleSpinBox::valueChanged), this, [player](double value) @@ -188,5 +231,15 @@ void raw_mouse_settings_dialog::reset_config() combo->setCurrentIndex(combo->findData(def_btn_id, button_role::button_name)); } + + if (QComboBox* combo = ::at32(m_device_combos, player)) + { + combo->setCurrentIndex(combo->findData(QString::fromStdString(config->device.to_string()))); + } + + if (QDoubleSpinBox* sb = ::at32(m_accel_spin_boxes, player)) + { + sb->setValue(config->mouse_acceleration.get() / 100.0); + } } } diff --git a/rpcs3/rpcs3qt/raw_mouse_settings_dialog.h b/rpcs3/rpcs3qt/raw_mouse_settings_dialog.h index 1cffe60b03..325fcb4785 100644 --- a/rpcs3/rpcs3qt/raw_mouse_settings_dialog.h +++ b/rpcs3/rpcs3qt/raw_mouse_settings_dialog.h @@ -2,6 +2,7 @@ #include #include +#include #include #include @@ -12,11 +13,14 @@ class raw_mouse_settings_dialog : public QDialog public: raw_mouse_settings_dialog(QWidget* parent = nullptr); + virtual ~raw_mouse_settings_dialog(); private: void add_tabs(QTabWidget* tabs); void reset_config(); + std::vector m_device_combos; + std::vector m_accel_spin_boxes; std::vector> m_combos; };