diff --git a/rpcs3/rpcs3qt/gs_frame.cpp b/rpcs3/rpcs3qt/gs_frame.cpp index db66ce68a4..012e3ba097 100644 --- a/rpcs3/rpcs3qt/gs_frame.cpp +++ b/rpcs3/rpcs3qt/gs_frame.cpp @@ -62,6 +62,13 @@ namespace pad extern atomic_t g_home_menu_requested; } +// Mouse-based motion sensor emulation state (defined in pad_thread) +extern std::atomic g_mouse_gyro_rmb; +extern std::atomic g_mouse_gyro_dx; +extern std::atomic g_mouse_gyro_dy; +extern std::atomic g_mouse_gyro_wheel; +extern std::atomic g_mouse_gyro_reset; + gs_frame::gs_frame(QScreen* screen, const QRect& geometry, const QIcon& appIcon, std::shared_ptr gui_settings, bool force_fullscreen) : QWindow() , m_initial_geometry(geometry) @@ -1216,6 +1223,73 @@ bool gs_frame::event(QEvent* ev) // This will make the cursor visible again if it was hidden by the mouse idle timeout handle_cursor(visibility(), false, false, true); } + + // Hardcoded mouse-based motion input. + // Captures mouse events while the game window is focused. + // Accumulates deltas for motion sensor emulation when RMB is held. + // Intentionally independent of chosen pad configuration. + if (Emu.IsRunning()) + { + switch (ev->type()) + { + case QEvent::MouseButtonPress: + { + auto* e = static_cast(ev); + if (e->button() == Qt::RightButton) + { + // Enable mouse-driven gyro emulation while RMB is held. + g_mouse_gyro_rmb.store(true, std::memory_order_relaxed); + } + break; + } + case QEvent::MouseButtonRelease: + { + auto* e = static_cast(ev); + if (e->button() == Qt::RightButton) + { + // Disable gyro emulation and request a one-shot motion reset. + g_mouse_gyro_rmb.store(false, std::memory_order_relaxed); + g_mouse_gyro_reset.store(true, std::memory_order_relaxed); + } + break; + } + case QEvent::MouseMove: + { + // Track relative mouse movement using a persistent last cursor position. + static QPoint last; + auto* e = static_cast(ev); + const QPoint cur = e->pos(); + + // Initialize reference position on first event. + if (last.isNull()) + last = cur; + + const s32 dx = cur.x() - last.x(); + const s32 dy = cur.y() - last.y(); + last = cur; + + // Accumulate deltas while gyro emulation is active. + if (g_mouse_gyro_rmb.load(std::memory_order_relaxed)) + { + g_mouse_gyro_dx.fetch_add(dx, std::memory_order_relaxed); + g_mouse_gyro_dy.fetch_add(dy, std::memory_order_relaxed); + } + break; + } + case QEvent::Wheel: + { + // Accumulate mouse wheel steps while gyro emulation is active. + auto* e = static_cast(ev); + if (g_mouse_gyro_rmb.load(std::memory_order_relaxed)) + { + const s32 steps = e->angleDelta().y() / 120; + g_mouse_gyro_wheel.fetch_add(steps, std::memory_order_relaxed); + } + break; + } + } + } + return QWindow::event(ev); } diff --git a/rpcs3/rpcs3qt/gui_application.cpp b/rpcs3/rpcs3qt/gui_application.cpp index 26795e2b13..113f5a6ebb 100644 --- a/rpcs3/rpcs3qt/gui_application.cpp +++ b/rpcs3/rpcs3qt/gui_application.cpp @@ -70,13 +70,6 @@ LOG_CHANNEL(gui_log, "GUI"); -// Mouse-based motion sensor emulation state (defined in pad_thread) -extern std::atomic g_mouse_gyro_rmb; -extern std::atomic g_mouse_gyro_dx; -extern std::atomic g_mouse_gyro_dy; -extern std::atomic g_mouse_gyro_wheel; -extern std::atomic g_mouse_gyro_reset; - std::unique_ptr g_raw_mouse_handler; s32 gui_application::m_language_id = static_cast(CELL_SYSUTIL_LANG_ENGLISH_US); @@ -1363,9 +1356,7 @@ bool gui_application::native_event_filter::nativeEventFilter([[maybe_unused]] co if (eventType == "windows_generic_MSG") { - if (MSG* msg = static_cast(message); msg && (msg->message == WM_INPUT || msg->message == WM_KEYDOWN || msg->message == WM_KEYUP || msg->message == WM_DEVICECHANGE - || msg->message == WM_MOUSEMOVE || msg->message == WM_MOUSEWHEEL - || msg->message == WM_LBUTTONDOWN || msg->message == WM_LBUTTONUP || msg->message == WM_RBUTTONDOWN || msg->message == WM_RBUTTONUP)) + if (MSG* msg = static_cast(message); msg && (msg->message == WM_INPUT || msg->message == WM_KEYDOWN || msg->message == WM_KEYUP || msg->message == WM_DEVICECHANGE)) { if (msg->message == WM_DEVICECHANGE && (msg->wParam == DBT_DEVICEARRIVAL || msg->wParam == DBT_DEVICEREMOVECOMPLETE)) { @@ -1376,66 +1367,6 @@ bool gui_application::native_event_filter::nativeEventFilter([[maybe_unused]] co return false; } - // Hardcoded mouse-based motion input. - // Captures native mouse events while the game window is focused. - // Accumulates deltas for motion sensor emulation when RMB is held. - // Intentionally independent of chosen pad configuration. - if (Emu.IsRunning() && GetForegroundWindow() == msg->hwnd) - { - switch (msg->message) - { - case WM_RBUTTONDOWN: - // Enable mouse-driven gyro emulation while RMB is held. - g_mouse_gyro_rmb.store(true, std::memory_order_relaxed); - break; - - case WM_RBUTTONUP: - // Disable gyro emulation and request a one-shot motion reset. - g_mouse_gyro_rmb.store(false, std::memory_order_relaxed); - g_mouse_gyro_reset.store(true, std::memory_order_relaxed); - break; - - case WM_MOUSEMOVE: - { - // Track relative mouse movement using a persistent last cursor position. - static POINT last{}; - POINT cur; - cur.x = static_cast(LOWORD(msg->lParam)); - cur.y = static_cast(HIWORD(msg->lParam)); - - // Initialize reference position on first event. - if (last.x == 0 && last.y == 0) - last = cur; - - const s32 dx = cur.x - last.x; - const s32 dy = cur.y - last.y; - last = cur; - - // Accumulate deltas only while gyro emulation is active. - if (g_mouse_gyro_rmb.load(std::memory_order_relaxed)) - { - g_mouse_gyro_dx.fetch_add(dx, std::memory_order_relaxed); - g_mouse_gyro_dy.fetch_add(dy, std::memory_order_relaxed); - } - break; - } - - case WM_MOUSEWHEEL: - { - // Accumulate mouse wheel steps as motion input as well. - if (g_mouse_gyro_rmb.load(std::memory_order_relaxed)) - { - const s32 steps = GET_WHEEL_DELTA_WPARAM(msg->wParam) / WHEEL_DELTA; - g_mouse_gyro_wheel.fetch_add(steps, std::memory_order_relaxed); - } - break; - } - - default: - break; - } - } - if (auto* handler = g_fxo->try_get(); handler && handler->type == mouse_handler::raw) { static_cast(handler)->handle_native_event(*msg);