Qt: Make mouse screen locking DPI aware

Also removed some global mouse hook stuff. Don't ever want to use that anyways.
This commit is contained in:
Ty Lamontagne 2025-10-16 19:01:54 -04:00 committed by Ty
parent 6ba3f96f27
commit 08ef9e2bd9
2 changed files with 35 additions and 72 deletions

View File

@ -100,54 +100,16 @@ void Common::SetMousePosition(int x, int y)
SetCursorPos(x, y); SetCursorPos(x, y);
} }
/*
static HHOOK mouseHook = nullptr;
static std::function<void(int, int)> fnMouseMoveCb;
LRESULT CALLBACK Mousecb(int nCode, WPARAM wParam, LPARAM lParam)
{
if (nCode >= 0 && wParam == WM_MOUSEMOVE)
{
MSLLHOOKSTRUCT* mouse = (MSLLHOOKSTRUCT*)lParam;
fnMouseMoveCb(mouse->pt.x, mouse->pt.y);
}
return CallNextHookEx(mouseHook, nCode, wParam, lParam);
}
*/
// This (and the above) works, but is not recommended on Windows and is only here for consistency.
// Defer to using raw input instead.
bool Common::AttachMousePositionCb(std::function<void(int, int)> cb) bool Common::AttachMousePositionCb(std::function<void(int, int)> cb)
{ {
/* // We use raw input messages which are handled by the windows message loop.
if (mouseHook) // The alternative is to use a low-level mouse hook, but this passes Windows all mouse messages to PCSX2.
Common::DetachMousePositionCb(); // If PCSX2 hangs, or you attach a debugger, the mouse will stop working system-wide.
fnMouseMoveCb = cb;
mouseHook = SetWindowsHookEx(WH_MOUSE_LL, Mousecb, GetModuleHandle(NULL), 0);
if (!mouseHook)
{
Console.Warning("Failed to set mouse hook: %d", GetLastError());
return false;
}
#if defined(PCSX2_DEBUG) || defined(PCSX2_DEVBUILD)
static bool warned = false;
if (!warned)
{
Console.Warning("Mouse hooks are enabled, and this isn't a release build! Using a debugger, or loading symbols, _will_ stall the hook and cause global mouse lag.");
warned = true;
}
#endif
*/
return true; return true;
} }
void Common::DetachMousePositionCb() void Common::DetachMousePositionCb()
{ {
/*
UnhookWindowsHookEx(mouseHook);
mouseHook = nullptr;
*/
} }
bool Common::PlaySoundAsync(const char* path) bool Common::PlaySoundAsync(const char* path)

View File

@ -2323,19 +2323,24 @@ bool MainWindow::nativeEvent(const QByteArray& eventType, void* message, qintptr
if (msg->message == WM_INPUT) if (msg->message == WM_INPUT)
{ {
UINT dwSize = 40; UINT dwSize = 0;
static BYTE lpb[40]; GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, nullptr, &dwSize, sizeof(RAWINPUTHEADER));
if (GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, lpb, &dwSize, sizeof(RAWINPUTHEADER)))
if (dwSize > 0)
{ {
const RAWINPUT* raw = (RAWINPUT*)lpb; std::vector<BYTE> lpb(dwSize);
if (raw->header.dwType == RIM_TYPEMOUSE) if (GetRawInputData((HRAWINPUT)msg->lParam, RID_INPUT, lpb.data(), &dwSize, sizeof(RAWINPUTHEADER)) == dwSize)
{ {
const RAWMOUSE& mouse = raw->data.mouse; const RAWINPUT* raw = reinterpret_cast<const RAWINPUT*>(lpb.data());
if (mouse.usFlags == MOUSE_MOVE_ABSOLUTE || mouse.usFlags == MOUSE_MOVE_RELATIVE) if (raw->header.dwType == RIM_TYPEMOUSE)
{ {
POINT cursorPos; const RAWMOUSE& mouse = raw->data.mouse;
GetCursorPos(&cursorPos); if (mouse.usFlags == MOUSE_MOVE_ABSOLUTE || mouse.usFlags == MOUSE_MOVE_RELATIVE)
checkMousePosition(cursorPos.x, cursorPos.y); {
POINT cursorPos;
if (GetCursorPos(&cursorPos))
checkMousePosition(cursorPos.x, cursorPos.y);
}
} }
} }
} }
@ -2639,30 +2644,26 @@ void MainWindow::checkMousePosition(int x, int y)
if (!shouldMouseLock()) if (!shouldMouseLock())
return; return;
const QPoint globalCursorPos = {x, y}; // physical mouse position
QRect windowBounds = isRenderingFullscreen() ? screen()->geometry() : geometry(); const QPoint physicalPos(x, y);
if (windowBounds.contains(globalCursorPos))
// logical (DIP) frame rect
QRectF logicalBounds = isRenderingFullscreen() ? screen()->geometry() : geometry();
// physical frame rect
const qreal scale = window()->devicePixelRatioF();
QRectF physicalBounds(
logicalBounds.x() * scale,
logicalBounds.y() * scale,
logicalBounds.width() * scale,
logicalBounds.height() * scale);
if (physicalBounds.contains(physicalPos))
return; return;
Common::SetMousePosition( Common::SetMousePosition(
std::clamp(globalCursorPos.x(), windowBounds.left(), windowBounds.right()), std::clamp(physicalPos.x(), (int)physicalBounds.left(), (int)physicalBounds.right()),
std::clamp(globalCursorPos.y(), windowBounds.top(), windowBounds.bottom())); std::clamp(physicalPos.y(), (int)physicalBounds.top(), (int)physicalBounds.bottom()));
/*
Provided below is how we would handle this if we were using low level hooks (What is used in Common::AttachMouseCb)
We currently use rawmouse on Windows, so Common::SetMousePosition called directly works fine.
*/
#if 0
// We are currently in a low level hook. SetCursorPos here (what is in Common::SetMousePosition) will not work!
// Let's (a)buse Qt's event loop to dispatch the call at a later time, outside of the hook.
QMetaObject::invokeMethod(
this, [=]() {
Common::SetMousePosition(
std::clamp(globalCursorPos.x(), windowBounds.left(), windowBounds.right()),
std::clamp(globalCursorPos.y(), windowBounds.top(), windowBounds.bottom()));
},
Qt::QueuedConnection);
#endif
} }
void MainWindow::saveDisplayWindowGeometryToConfig() void MainWindow::saveDisplayWindowGeometryToConfig()