mirror of
https://github.com/RPCSX/rpcsx.git
synced 2026-04-04 14:08:37 +00:00
input: implement raw_mouse_handler
This commit is contained in:
parent
f6f8996aa9
commit
68f3df4975
18 changed files with 654 additions and 52 deletions
|
|
@ -33,12 +33,14 @@ void basic_mouse_handler::Init(const u32 max_connect)
|
|||
m_info.status[0] = CELL_MOUSE_STATUS_CONNECTED; // (TODO: Support for more mice)
|
||||
m_info.vendor_id[0] = 0x1234;
|
||||
m_info.product_id[0] = 0x1234;
|
||||
|
||||
type = mouse_handler::basic;
|
||||
}
|
||||
|
||||
/* Sets the target window for the event handler, and also installs an event filter on the target. */
|
||||
void basic_mouse_handler::SetTargetWindow(QWindow* target)
|
||||
{
|
||||
if (target != nullptr)
|
||||
if (target)
|
||||
{
|
||||
m_target = target;
|
||||
target->installEventFilter(this);
|
||||
|
|
@ -86,33 +88,33 @@ bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev)
|
|||
|
||||
void basic_mouse_handler::MouseButtonDown(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_1, true);
|
||||
else if (event->button() == Qt::RightButton) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_2, true);
|
||||
else if (event->button() == Qt::MiddleButton) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_3, true);
|
||||
if (event->button() == Qt::LeftButton) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_1, true);
|
||||
else if (event->button() == Qt::RightButton) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_2, true);
|
||||
else if (event->button() == Qt::MiddleButton) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_3, true);
|
||||
// TODO: verify these
|
||||
else if (event->button() == Qt::ExtraButton1) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_4, true);
|
||||
else if (event->button() == Qt::ExtraButton2) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_5, true);
|
||||
else if (event->button() == Qt::ExtraButton3) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_6, true);
|
||||
else if (event->button() == Qt::ExtraButton4) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_7, true);
|
||||
else if (event->button() == Qt::ExtraButton5) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_8, true);
|
||||
else if (event->button() == Qt::ExtraButton1) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_4, true);
|
||||
else if (event->button() == Qt::ExtraButton2) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_5, true);
|
||||
else if (event->button() == Qt::ExtraButton3) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_6, true);
|
||||
else if (event->button() == Qt::ExtraButton4) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_7, true);
|
||||
else if (event->button() == Qt::ExtraButton5) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_8, true);
|
||||
}
|
||||
|
||||
void basic_mouse_handler::MouseButtonUp(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_1, false);
|
||||
else if (event->button() == Qt::RightButton) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_2, false);
|
||||
else if (event->button() == Qt::MiddleButton) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_3, false);
|
||||
if (event->button() == Qt::LeftButton) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_1, false);
|
||||
else if (event->button() == Qt::RightButton) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_2, false);
|
||||
else if (event->button() == Qt::MiddleButton) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_3, false);
|
||||
// TODO: verify these
|
||||
else if (event->button() == Qt::ExtraButton1) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_4, false);
|
||||
else if (event->button() == Qt::ExtraButton2) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_5, false);
|
||||
else if (event->button() == Qt::ExtraButton3) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_6, false);
|
||||
else if (event->button() == Qt::ExtraButton4) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_7, false);
|
||||
else if (event->button() == Qt::ExtraButton5) MouseHandlerBase::Button(CELL_MOUSE_BUTTON_8, false);
|
||||
else if (event->button() == Qt::ExtraButton1) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_4, false);
|
||||
else if (event->button() == Qt::ExtraButton2) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_5, false);
|
||||
else if (event->button() == Qt::ExtraButton3) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_6, false);
|
||||
else if (event->button() == Qt::ExtraButton4) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_7, false);
|
||||
else if (event->button() == Qt::ExtraButton5) MouseHandlerBase::Button(0, CELL_MOUSE_BUTTON_8, false);
|
||||
}
|
||||
|
||||
void basic_mouse_handler::MouseScroll(QWheelEvent* event)
|
||||
{
|
||||
MouseHandlerBase::Scroll(event->angleDelta().y());
|
||||
MouseHandlerBase::Scroll(0, event->angleDelta().y());
|
||||
}
|
||||
|
||||
bool basic_mouse_handler::get_mouse_lock_state() const
|
||||
|
|
@ -152,11 +154,12 @@ void basic_mouse_handler::MouseMove(QMouseEvent* event)
|
|||
p_real.setY(std::clamp(p_real.y() + p_delta.y(), 0, screen.height()));
|
||||
|
||||
// pass the 'real' position and the current delta to the screen center
|
||||
MouseHandlerBase::Move(p_real.x(), p_real.y(), screen.width(), screen.height(), true, p_delta.x(), p_delta.y());
|
||||
MouseHandlerBase::Move(0, p_real.x(), p_real.y(), screen.width(), screen.height(), true, p_delta.x(), p_delta.y());
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseHandlerBase::Move(e_pos.x(), e_pos.y(), screen.width(), screen.height());
|
||||
// pass the absolute position
|
||||
MouseHandlerBase::Move(0, e_pos.x(), e_pos.y(), screen.width(), screen.height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
79
rpcs3/Input/raw_mouse_config.h
Normal file
79
rpcs3/Input/raw_mouse_config.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
#pragma once
|
||||
|
||||
#include "Utilities/Config.h"
|
||||
#include "Utilities/mutex.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
LOG_CHANNEL(cfg_log, "CFG");
|
||||
|
||||
struct raw_mouse_config : cfg::node
|
||||
{
|
||||
public:
|
||||
using cfg::node::node;
|
||||
|
||||
cfg::_float<10, 1000> mouse_acceleration{ this, "Mouse Acceleration", 100.0f, true };
|
||||
};
|
||||
|
||||
struct raw_mice_config : cfg::node
|
||||
{
|
||||
raw_mice_config()
|
||||
{
|
||||
for (u32 i = 0; i < ::size32(players); i++)
|
||||
{
|
||||
players.at(i) = std::make_shared<raw_mouse_config>(this, fmt::format("Player %d", i + 1));
|
||||
}
|
||||
}
|
||||
|
||||
shared_mutex m_mutex;
|
||||
static constexpr std::string_view cfg_id = "raw_mouse";
|
||||
std::array<std::shared_ptr<raw_mouse_config>, 4> players;
|
||||
|
||||
bool load()
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
bool result = false;
|
||||
const std::string cfg_name = fmt::format("%sconfig/%s.yml", fs::get_config_dir(), cfg_id);
|
||||
cfg_log.notice("Loading %s config: %s", cfg_id, cfg_name);
|
||||
|
||||
from_default();
|
||||
|
||||
if (fs::file cfg_file{ cfg_name, fs::read })
|
||||
{
|
||||
if (std::string content = cfg_file.to_string(); !content.empty())
|
||||
{
|
||||
result = from_string(content);
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mutex.unlock();
|
||||
save();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void save()
|
||||
{
|
||||
std::lock_guard lock(m_mutex);
|
||||
|
||||
const std::string cfg_name = fmt::format("%sconfig/%s.yml", fs::get_config_dir(), cfg_id);
|
||||
cfg_log.notice("Saving %s config to '%s'", cfg_id, cfg_name);
|
||||
|
||||
if (!fs::create_path(fs::get_parent_dir(cfg_name)))
|
||||
{
|
||||
cfg_log.fatal("Failed to create path: %s (%s)", cfg_name, fs::g_tls_error);
|
||||
}
|
||||
|
||||
if (!cfg::node::save(cfg_name))
|
||||
{
|
||||
cfg_log.error("Failed to save %s config to '%s' (error=%s)", cfg_id, cfg_name, fs::g_tls_error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
extern raw_mice_config g_cfg_raw_mouse;
|
||||
366
rpcs3/Input/raw_mouse_handler.cpp
Normal file
366
rpcs3/Input/raw_mouse_handler.cpp
Normal file
|
|
@ -0,0 +1,366 @@
|
|||
#include "stdafx.h"
|
||||
#include "raw_mouse_handler.h"
|
||||
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
#include "Emu/RSX/RSXThread.h"
|
||||
#include "Emu/Io/interception.h"
|
||||
#include "Input/raw_mouse_config.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <hidusage.h>
|
||||
#endif
|
||||
|
||||
#define RAW_MOUSE_DEBUG_CURSOR_ENABLED 0
|
||||
#if RAW_MOUSE_DEBUG_CURSOR_ENABLED
|
||||
#include "Emu/RSX/Overlays/overlay_cursor.h"
|
||||
static inline void draw_overlay_cursor(u32 index, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
|
||||
{
|
||||
const u16 x = static_cast<u16>(x_pos / (x_max / static_cast<f32>(rsx::overlays::overlay::virtual_width)));
|
||||
const u16 y = static_cast<u16>(y_pos / (y_max / static_cast<f32>(rsx::overlays::overlay::virtual_height)));
|
||||
|
||||
const color4f color = { 1.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
rsx::overlays::set_cursor(rsx::overlays::cursor_offset::last + index, x, y, color, 2'000'000, false);
|
||||
}
|
||||
#else
|
||||
static inline void draw_overlay_cursor(u32, s32, s32, s32, s32) {}
|
||||
#endif
|
||||
|
||||
LOG_CHANNEL(input_log, "Input");
|
||||
|
||||
raw_mice_config g_cfg_raw_mouse;
|
||||
|
||||
raw_mouse::raw_mouse(u32 index, const std::string& device_name, void* handle, raw_mouse_handler* handler)
|
||||
: m_index(index), m_device_name(device_name), m_handle(handle), m_handler(handler)
|
||||
{
|
||||
if (m_index < ::size32(g_cfg_raw_mouse.players))
|
||||
{
|
||||
if (const auto& player = ::at32(g_cfg_raw_mouse.players, m_index))
|
||||
{
|
||||
m_mouse_acceleration = static_cast<float>(player->mouse_acceleration.get()) / 100.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
raw_mouse::~raw_mouse()
|
||||
{
|
||||
}
|
||||
|
||||
void raw_mouse::update_window_handle()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (GSRender* render = static_cast<GSRender*>(g_fxo->try_get<rsx::thread>()))
|
||||
{
|
||||
if (GSFrameBase* frame = render->get_frame())
|
||||
{
|
||||
if (display_handle_t window_handle = frame->handle(); window_handle && window_handle == GetActiveWindow())
|
||||
{
|
||||
m_window_handle = window_handle;
|
||||
m_window_width = frame->client_width();
|
||||
m_window_height = frame->client_height();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
m_window_handle = {};
|
||||
m_window_width = 0;
|
||||
m_window_height = 0;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void raw_mouse::update_values(const RAWMOUSE& state)
|
||||
{
|
||||
ensure(m_handler != nullptr);
|
||||
|
||||
// Update window handle and size
|
||||
update_window_handle();
|
||||
|
||||
// Check if the window handle is active
|
||||
if (!m_window_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const auto get_button_pressed = [this](u8 button, int button_flags, int down, int up)
|
||||
{
|
||||
// Only update the value if either down or up flags are present
|
||||
if ((button_flags & down))
|
||||
{
|
||||
m_handler->Button(m_index, button, true);
|
||||
}
|
||||
else if ((button_flags & up))
|
||||
{
|
||||
m_handler->Button(m_index, button, false);
|
||||
}
|
||||
};
|
||||
|
||||
// Get mouse buttons
|
||||
get_button_pressed(CELL_MOUSE_BUTTON_1, state.usButtonFlags, RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP);
|
||||
get_button_pressed(CELL_MOUSE_BUTTON_2, state.usButtonFlags, RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP);
|
||||
get_button_pressed(CELL_MOUSE_BUTTON_3, state.usButtonFlags, RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP);
|
||||
get_button_pressed(CELL_MOUSE_BUTTON_4, state.usButtonFlags, RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP);
|
||||
get_button_pressed(CELL_MOUSE_BUTTON_5, state.usButtonFlags, RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP);
|
||||
|
||||
// Get vertical mouse wheel
|
||||
if ((state.usButtonFlags & RI_MOUSE_WHEEL))
|
||||
{
|
||||
m_handler->Scroll(m_index, static_cast<s16>(state.usButtonData));
|
||||
}
|
||||
|
||||
// Get horizontal mouse wheel. Ignored until needed.
|
||||
//if ((state.usButtonFlags & RI_MOUSE_HWHEEL))
|
||||
//{
|
||||
// m_handler->Scroll(m_index, static_cast<s16>(state.usButtonData));
|
||||
//}
|
||||
|
||||
// Get mouse movement
|
||||
if ((state.usFlags & MOUSE_MOVE_ABSOLUTE))
|
||||
{
|
||||
// Get absolute mouse movement
|
||||
|
||||
if (m_window_handle && m_window_width && m_window_height)
|
||||
{
|
||||
// Convert virtual coordinates to screen coordinates
|
||||
const bool is_virtual_desktop = (state.usFlags & MOUSE_VIRTUAL_DESKTOP) == MOUSE_VIRTUAL_DESKTOP;
|
||||
const int width = GetSystemMetrics(is_virtual_desktop ? SM_CXVIRTUALSCREEN : SM_CXSCREEN);
|
||||
const int height = GetSystemMetrics(is_virtual_desktop ? SM_CYVIRTUALSCREEN : SM_CYSCREEN);
|
||||
|
||||
if (width && height)
|
||||
{
|
||||
POINT pt {
|
||||
.x = long(state.lLastX / 65535.0f * width),
|
||||
.y = long(state.lLastY / 65535.0f * height)
|
||||
};
|
||||
|
||||
if (ScreenToClient(m_window_handle, &pt))
|
||||
{
|
||||
// Move mouse with absolute position
|
||||
m_handler->Move(m_index, pt.x, pt.y, m_window_width, m_window_height);
|
||||
draw_overlay_cursor(m_index, pt.x, pt.y, m_window_width, m_window_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (state.lLastX || state.lLastY)
|
||||
{
|
||||
// Get relative mouse movement (units most likely in raw dpi)
|
||||
|
||||
if (m_window_handle && m_window_width && m_window_height)
|
||||
{
|
||||
// Apply mouse acceleration
|
||||
const int delta_x = static_cast<int>(state.lLastX * m_mouse_acceleration);
|
||||
const int delta_y = static_cast<int>(state.lLastY * m_mouse_acceleration);
|
||||
|
||||
// Calculate new position
|
||||
m_pos_x = std::max(0, std::min(m_pos_x + delta_x, m_window_width - 1));
|
||||
m_pos_y = std::max(0, std::min(m_pos_y + delta_y, m_window_height - 1));
|
||||
|
||||
// Move mouse relative to old position
|
||||
m_handler->Move(m_index, m_pos_x, m_pos_y, m_window_width, m_window_height, true, delta_x, delta_y);
|
||||
draw_overlay_cursor(m_index, m_pos_x, m_pos_y, m_window_width, m_window_height);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
raw_mouse_handler::~raw_mouse_handler()
|
||||
{
|
||||
if (m_raw_mice.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
std::vector<RAWINPUTDEVICE> raw_input_devices;
|
||||
raw_input_devices.push_back(RAWINPUTDEVICE {
|
||||
.usUsagePage = HID_USAGE_PAGE_GENERIC,
|
||||
.usUsage = HID_USAGE_GENERIC_MOUSE,
|
||||
.dwFlags = RIDEV_REMOVE,
|
||||
.hwndTarget = nullptr
|
||||
});
|
||||
if (!RegisterRawInputDevices(raw_input_devices.data(), ::size32(raw_input_devices), sizeof(RAWINPUTDEVICE)))
|
||||
{
|
||||
input_log.error("raw_mouse_handler: RegisterRawInputDevices (destructor) failed: %s", fmt::win_error{GetLastError(), nullptr});
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void raw_mouse_handler::Init(const u32 max_connect)
|
||||
{
|
||||
if (m_info.max_connect > 0)
|
||||
{
|
||||
// Already initialized
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_cfg_raw_mouse.load())
|
||||
{
|
||||
input_log.notice("raw_mouse_handler: Could not load raw mouse config. Using defaults.");
|
||||
}
|
||||
|
||||
enumerate_devices(max_connect);
|
||||
|
||||
m_mice.clear();
|
||||
|
||||
for (u32 i = 0; i < std::min(::size32(m_raw_mice), max_connect); i++)
|
||||
{
|
||||
m_mice.emplace_back(Mouse());
|
||||
}
|
||||
|
||||
m_info = {};
|
||||
m_info.max_connect = max_connect;
|
||||
m_info.now_connect = std::min(::size32(m_mice), max_connect);
|
||||
m_info.info = input::g_mice_intercepted ? CELL_MOUSE_INFO_INTERCEPTED : 0; // Ownership of mouse data: 0=Application, 1=System
|
||||
|
||||
for (u32 i = 0; i < m_info.now_connect; i++)
|
||||
{
|
||||
m_info.status[i] = CELL_MOUSE_STATUS_CONNECTED;
|
||||
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;
|
||||
m_info.product_id[0] = 0x1234;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (max_connect && !m_raw_mice.empty())
|
||||
{
|
||||
// Get the window handle of the first mouse
|
||||
raw_mouse& mouse = m_raw_mice.begin()->second;
|
||||
mouse.update_window_handle();
|
||||
|
||||
std::vector<RAWINPUTDEVICE> raw_input_devices;
|
||||
raw_input_devices.push_back(RAWINPUTDEVICE {
|
||||
.usUsagePage = HID_USAGE_PAGE_GENERIC,
|
||||
.usUsage = HID_USAGE_GENERIC_MOUSE,
|
||||
.dwFlags = 0,
|
||||
.hwndTarget = mouse.window_handle()
|
||||
});
|
||||
if (!RegisterRawInputDevices(raw_input_devices.data(), ::size32(raw_input_devices), sizeof(RAWINPUTDEVICE)))
|
||||
{
|
||||
input_log.error("raw_mouse_handler: RegisterRawInputDevices failed: %s", fmt::win_error{GetLastError(), nullptr});
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
type = mouse_handler::raw;
|
||||
}
|
||||
|
||||
void raw_mouse_handler::enumerate_devices(u32 max_connect)
|
||||
{
|
||||
input_log.notice("raw_mouse_handler: enumerating devices (max_connect=%d)", max_connect);
|
||||
|
||||
m_raw_mice.clear();
|
||||
|
||||
if (max_connect == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
u32 num_devices{};
|
||||
u32 res = GetRawInputDeviceList(nullptr, &num_devices, sizeof(RAWINPUTDEVICELIST));
|
||||
if (res == umax)
|
||||
{
|
||||
input_log.error("raw_mouse_handler: GetRawInputDeviceList (count) failed: %s", fmt::win_error{GetLastError(), nullptr});
|
||||
return;
|
||||
}
|
||||
|
||||
if (num_devices == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<RAWINPUTDEVICELIST> device_list(num_devices);
|
||||
|
||||
res = GetRawInputDeviceList(device_list.data(), &num_devices, sizeof(RAWINPUTDEVICELIST));
|
||||
if (res == umax)
|
||||
{
|
||||
input_log.error("raw_mouse_handler: GetRawInputDeviceList (fetch) failed: %s", fmt::win_error{GetLastError(), nullptr});
|
||||
return;
|
||||
}
|
||||
|
||||
for (RAWINPUTDEVICELIST& device : device_list)
|
||||
{
|
||||
if (m_raw_mice.size() >= max_connect)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (device.dwType != RIM_TYPEMOUSE)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
u32 size = 0;
|
||||
res = GetRawInputDeviceInfoW(device.hDevice, RIDI_DEVICENAME, nullptr, &size);
|
||||
if (res == umax)
|
||||
{
|
||||
input_log.error("raw_mouse_handler: GetRawInputDeviceInfoA (RIDI_DEVICENAME count) failed: %s", fmt::win_error{GetLastError(), nullptr});
|
||||
continue;
|
||||
}
|
||||
|
||||
if (size == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
std::vector<wchar_t> buf(size);
|
||||
res = GetRawInputDeviceInfoW(device.hDevice, RIDI_DEVICENAME, buf.data(), &size);
|
||||
if (res == umax)
|
||||
{
|
||||
input_log.error("raw_mouse_handler: GetRawInputDeviceInfoA (RIDI_DEVICENAME fetch) failed: %s", fmt::win_error{GetLastError(), nullptr});
|
||||
continue;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
m_raw_mice[device.hDevice] = raw_mouse(::size32(m_raw_mice), device_name, device.hDevice, this);
|
||||
}
|
||||
#endif
|
||||
|
||||
input_log.notice("raw_mouse_handler: found %d devices", m_raw_mice.size());
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void raw_mouse_handler::handle_native_event(const MSG& msg)
|
||||
{
|
||||
if (msg.message != WM_INPUT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (GET_RAWINPUT_CODE_WPARAM(msg.wParam) != RIM_INPUT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RAWINPUT raw_input{};
|
||||
UINT size = sizeof(RAWINPUT);
|
||||
|
||||
u32 res = GetRawInputData(reinterpret_cast<HRAWINPUT>(msg.lParam), RID_INPUT, &raw_input, &size, sizeof(RAWINPUTHEADER));
|
||||
if (res == umax)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
switch (raw_input.header.dwType)
|
||||
{
|
||||
case RIM_TYPEMOUSE:
|
||||
{
|
||||
if (auto it = m_raw_mice.find(raw_input.header.hDevice); it != m_raw_mice.end())
|
||||
{
|
||||
it->second.update_values(raw_input.data.mouse);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
56
rpcs3/Input/raw_mouse_handler.h
Normal file
56
rpcs3/Input/raw_mouse_handler.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
|
||||
#include "Emu/Io/MouseHandler.h"
|
||||
#include "Emu/RSX/display.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
class raw_mouse_handler;
|
||||
|
||||
class raw_mouse
|
||||
{
|
||||
public:
|
||||
raw_mouse() {}
|
||||
raw_mouse(u32 index, const std::string& device_name, void* handle, raw_mouse_handler* handler);
|
||||
virtual ~raw_mouse();
|
||||
|
||||
void update_window_handle();
|
||||
display_handle_t window_handle() const { return m_window_handle; }
|
||||
|
||||
#ifdef _WIN32
|
||||
void update_values(const RAWMOUSE& state);
|
||||
#endif
|
||||
|
||||
private:
|
||||
u32 m_index = 0;
|
||||
std::string m_device_name;
|
||||
void* m_handle{};
|
||||
display_handle_t m_window_handle{};
|
||||
int m_window_width{};
|
||||
int m_window_height{};
|
||||
int m_pos_x{};
|
||||
int m_pos_y{};
|
||||
float m_mouse_acceleration = 1.0f;
|
||||
raw_mouse_handler* m_handler{};
|
||||
};
|
||||
|
||||
class raw_mouse_handler final : public MouseHandlerBase
|
||||
{
|
||||
using MouseHandlerBase::MouseHandlerBase;
|
||||
|
||||
public:
|
||||
virtual ~raw_mouse_handler();
|
||||
|
||||
void Init(const u32 max_connect) override;
|
||||
|
||||
#ifdef _WIN32
|
||||
void handle_native_event(const MSG& msg);
|
||||
#endif
|
||||
|
||||
private:
|
||||
void enumerate_devices(u32 max_connect);
|
||||
|
||||
std::map<void*, raw_mouse> m_raw_mice;
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue