input/qt: enumerate raw mouse devices once a seconds in the config dialog

This commit is contained in:
Megamouse 2024-05-22 00:39:08 +02:00
parent 5cc05d082d
commit fa144d3307
4 changed files with 138 additions and 52 deletions

View file

@ -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<named_thread<std::function<void()>>>("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<named_thread<std::function<void()>>>("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<u32> 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<u32> 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);

View file

@ -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<u32>& 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<void*, raw_mouse> m_raw_mice;
std::function<void(const std::string&, s32, bool)> m_mouse_press_callback;

View file

@ -6,6 +6,7 @@
#include "Input/raw_mouse_handler.h"
#include "util/asm.hpp"
#include <QAbstractItemView>
#include <QGroupBox>
#include <QMessageBox>
#include <QVBoxLayout>
@ -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<int>::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);
}

View file

@ -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;
};