Coordinates from mouse low level hook messages are not mapped the same way than WM_MOUSEMOVE or GetCursorPos. This causes problems on programs that make use of both values to calculate mouse movement, like the wine DirectInput implementation.
I'm marking this as a draft since I was not able to find a way to write a test for this. I'm able to easily reproduce it on Proton, because it creates a scaled full screen window, on Wine this doesn't happen so the coordinates are not required to be mapped to a scaled window.
Edit: I didn't realize that modesetting emulation was an experimental option! So, I was able to reproduce the bug by enabling it.
-- v3: dinput: Set per monitor aware DPI when handling WM_MOUSEMOVE. win32u: Map raw coordinates to virtual screen in low-level hooks.
From: Santino Mazza smazza@codeweavers.com
--- dlls/win32u/message.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index 2a824dbdab3..7cdec243189 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -2948,8 +2948,13 @@ int peek_message( MSG *msg, const struct peek_message_filter *filter ) } else if (info.msg.message == WH_MOUSE_LL && size >= sizeof(msg_data->hardware)) { + RECT rect = {info.msg.pt.x, info.msg.pt.y, info.msg.pt.x, info.msg.pt.y}; MSLLHOOKSTRUCT hook;
+ rect = map_rect_raw_to_virt( rect, 0 ); + info.msg.pt.x = rect.left; + info.msg.pt.y = rect.top; + hook.pt = info.msg.pt; hook.mouseData = info.msg.lParam; hook.flags = msg_data->hardware.flags;
From: Santino Mazza smazza@codeweavers.com
--- dlls/dinput/mouse.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/dinput/mouse.c b/dlls/dinput/mouse.c index eec022974b5..0cf2c4cd4dd 100644 --- a/dlls/dinput/mouse.c +++ b/dlls/dinput/mouse.c @@ -209,12 +209,17 @@ int dinput_mouse_hook( IDirectInputDevice8W *iface, WPARAM wparam, LPARAM lparam switch(wparam) { case WM_MOUSEMOVE: { + DPI_AWARENESS_CONTEXT context; POINT pt, pt1;
+ context = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE); + GetCursorPos(&pt); state->lX += pt.x = hook->pt.x - pt.x; state->lY += pt.y = hook->pt.y - pt.y;
+ SetThreadDpiAwarenessContext(context); + if (impl->base.user_format.dwFlags & DIDF_ABSAXIS) { pt1.x = state->lX;
This merge request was closed by Rémi Bernon.