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.
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..89d8eb826fb 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, get_thread_dpi() ); + 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;
Rémi Bernon (@rbernon) commented about dlls/win32u/message.c:
} 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, get_thread_dpi() );
info.msg.pt.x = rect.left;
info.msg.pt.y = rect.top;
I'm not very confident about hook chain logic but I think this only happens when the first hook is called. It then raises the question to whether this is the right place to do this, or whether it would be better in `call_hook`, right before the hook is actually called. In particular `get_thread_dpi` could return different values depending on the thread / process DPI awareness, and that also raises the question to whether ll-hook pointer position needs to be DPI mapped or not.
On Wed Aug 6 15:44:03 2025 +0000, Rémi Bernon wrote:
I'm not very confident about hook chain logic but I think this only happens when the first hook is called, and the other hooks in the chain then dispatched/called using WM_WINE_MOUSE_LL_HOOK internal messages. It then raises the question to whether this is the right place to do this, or whether it would be better in `call_hook`, right before the hook is actually called. In particular `get_thread_dpi` could return different values depending on the thread / process DPI awareness, and that also raises the question to whether ll-hook pointer position needs to be DPI mapped or not.
I did more testing on Windows, WH_MOUSE_LL messages are not DPI scaled. So I suppose, instead of `get_thread_dpi`, I should just put 0 so it doesn't do any DPI scaling? Also, because WH_MOUSE_LL is not DPI scaled, I think there are still going to be issues on the way mouse movement is currently calculated by DirectInput.
How would we write a test for this? On Windows I can just increase the scaling of the display in the settings, but I'm not sure how to do it programmatically.