Adds the registry key HKEY_CURRENT_USER\Software\Wine\Wayland Driver\rawinput witch allows mouse raw input. This makes it easier to calculate the same sensitivity in different games, use sensitivity calculators, and easily change values when changing mouse DPI and do not depend on the compositor or OS.
For example, you want to set the sensitivity to half as much, but sensitivity curves in libinput are more difficult to calculate than mouse sensitivity in the games.
Implementation of ideas written in the comments: https://gitlab.winehq.org/wine/wine/-/merge_requests/4698
-- v4: winewayland.drv: Add mouse rawinput support server: Add send_hardware_message flags for rawinput translation.
From: Grigory Vasilyev h0tc0d3@gmail.com
--- dlls/win32u/message.c | 2 ++ include/wine/server_protocol.h | 3 ++- server/protocol.def | 1 + server/queue.c | 27 ++++++++++++++++++++------- 4 files changed, 25 insertions(+), 8 deletions(-)
diff --git a/dlls/win32u/message.c b/dlls/win32u/message.c index d1f49ca3ed9..22965835316 100644 --- a/dlls/win32u/message.c +++ b/dlls/win32u/message.c @@ -3495,6 +3495,7 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA req->input.mouse.flags = input->mi.dwFlags; req->input.mouse.time = input->mi.time; req->input.mouse.info = input->mi.dwExtraInfo; + if (flags & SEND_HWMSG_RAWINPUT) req->flags |= SEND_HWMSG_RAWINPUT; affects_key_state = !!(input->mi.dwFlags & (MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP | MOUSEEVENTF_RIGHTDOWN | MOUSEEVENTF_RIGHTUP | MOUSEEVENTF_MIDDLEDOWN | MOUSEEVENTF_MIDDLEUP | @@ -3523,6 +3524,7 @@ NTSTATUS send_hardware_message( HWND hwnd, UINT flags, const INPUT *input, LPARA req->input.kbd.flags = input->ki.dwFlags & ~KEYEVENTF_SCANCODE; req->input.kbd.time = input->ki.time; req->input.kbd.info = input->ki.dwExtraInfo; + if (flags & SEND_HWMSG_RAWINPUT) req->flags |= SEND_HWMSG_RAWINPUT; affects_key_state = TRUE; break; case INPUT_HARDWARE: diff --git a/include/wine/server_protocol.h b/include/wine/server_protocol.h index 8a5ae71b856..a4d4480561c 100644 --- a/include/wine/server_protocol.h +++ b/include/wine/server_protocol.h @@ -2885,6 +2885,7 @@ struct send_hardware_message_reply char __pad_28[4]; }; #define SEND_HWMSG_INJECTED 0x01 +#define SEND_HWMSG_RAWINPUT 0x02
@@ -6534,7 +6535,7 @@ union generic_reply
/* ### protocol_version begin ### */
-#define SERVER_PROTOCOL_VERSION 806 +#define SERVER_PROTOCOL_VERSION 807
/* ### protocol_version end ### */
diff --git a/server/protocol.def b/server/protocol.def index 25184641082..0802dbcca13 100644 --- a/server/protocol.def +++ b/server/protocol.def @@ -2161,6 +2161,7 @@ enum message_type int new_y; @END #define SEND_HWMSG_INJECTED 0x01 +#define SEND_HWMSG_RAWINPUT 0x02
/* Get a message from the current queue */ diff --git a/server/queue.c b/server/queue.c index 5a6f954bc4d..0581b7d8bce 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1791,7 +1791,7 @@ static struct thread *get_foreground_thread( struct desktop *desktop, user_handl #define WINE_KEYBOARD_HANDLE 2
static void rawmouse_init( struct rawinput *header, RAWMOUSE *rawmouse, int x, int y, unsigned int flags, - unsigned int buttons, lparam_t info ) + unsigned int buttons, lparam_t info, unsigned int req_flags ) { static const unsigned int button_flags[] = { @@ -1811,6 +1811,14 @@ static void rawmouse_init( struct rawinput *header, RAWMOUSE *rawmouse, int x, i header->usage = MAKELONG(HID_USAGE_GENERIC_MOUSE, HID_USAGE_PAGE_GENERIC);
rawmouse->usFlags = MOUSE_MOVE_RELATIVE; + + if(req_flags & SEND_HWMSG_RAWINPUT) + { + rawmouse->usFlags = 0; + if (flags & MOUSEEVENTF_ABSOLUTE) rawmouse->usFlags |= MOUSE_MOVE_ABSOLUTE; + if (flags & MOUSEEVENTF_VIRTUALDESK) rawmouse->usFlags |= MOUSE_VIRTUAL_DESKTOP; + } + rawmouse->usButtonFlags = 0; rawmouse->usButtonData = 0; for (i = 1; i < ARRAY_SIZE(button_flags); ++i) @@ -1839,8 +1847,8 @@ static void rawmouse_init( struct rawinput *header, RAWMOUSE *rawmouse, int x, i }
rawmouse->ulRawButtons = 0; - rawmouse->lLastX = x; - rawmouse->lLastY = y; + rawmouse->lLastX = (flags & MOUSEEVENTF_MOVE) ? x : 0; + rawmouse->lLastY = (flags & MOUSEEVENTF_MOVE) ? y : 0; rawmouse->ulExtraInformation = info; }
@@ -1980,7 +1988,7 @@ static void dispatch_rawinput_message( struct desktop *desktop, struct rawinput_
/* queue a hardware message for a mouse event */ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, const hw_input_t *input, - unsigned int origin, struct msg_queue *sender ) + unsigned int origin, struct msg_queue *sender, unsigned int req_flags ) { struct hardware_msg_data *msg_data; struct rawinput_message raw_msg; @@ -2043,8 +2051,13 @@ static int queue_mouse_message( struct desktop *desktop, user_handle_t win, cons raw_msg.time = time; raw_msg.message = WM_INPUT; raw_msg.flags = flags; - rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, x - desktop->cursor.x, y - desktop->cursor.y, - raw_msg.flags, input->mouse.data, input->mouse.info ); + + if(req_flags & SEND_HWMSG_RAWINPUT) + rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, input->mouse.x, input->mouse.y, + raw_msg.flags, input->mouse.data, input->mouse.info, req_flags ); + else + rawmouse_init( &raw_msg.rawinput, &raw_msg.data.mouse, x - desktop->cursor.x, y - desktop->cursor.y, + raw_msg.flags, input->mouse.data, input->mouse.info, req_flags );
dispatch_rawinput_message( desktop, &raw_msg ); release_object( foreground ); @@ -2981,7 +2994,7 @@ DECL_HANDLER(send_hardware_message) switch (req->input.type) { case INPUT_MOUSE: - wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender ); + wait = queue_mouse_message( desktop, req->win, &req->input, origin, sender, req->flags ); break; case INPUT_KEYBOARD: wait = queue_keyboard_message( desktop, req->win, &req->input, origin, sender, 0 );
From: Grigory Vasilyev h0tc0d3@gmail.com
Adds the registry key HKEY_CURRENT_USER\Software\Wine\Wayland Driver\rawinput witch allows mouse raw input. This makes it easier to calculate the same sensitivity in different games, use sensitivity calculators, and easily change values when changing mouse DPI and do not depend on the compositor or OS.
For example, you want to set the sensitivity to half as much, but sensitivity curves in libinput are more difficult to calculate than mouse sensitivity in the games. --- dlls/winewayland.drv/Makefile.in | 1 + dlls/winewayland.drv/dllmain.c | 42 ++++++++++++++++++++++++++ dlls/winewayland.drv/unixlib.h | 1 + dlls/winewayland.drv/wayland_pointer.c | 33 +++++++++++++++----- dlls/winewayland.drv/waylanddrv_main.c | 10 ++++++ 5 files changed, 79 insertions(+), 8 deletions(-)
diff --git a/dlls/winewayland.drv/Makefile.in b/dlls/winewayland.drv/Makefile.in index 9ad1ad6889d..bee478257ae 100644 --- a/dlls/winewayland.drv/Makefile.in +++ b/dlls/winewayland.drv/Makefile.in @@ -2,6 +2,7 @@ MODULE = winewayland.drv UNIXLIB = winewayland.so UNIX_CFLAGS = $(EGL_CFLAGS) $(WAYLAND_CLIENT_CFLAGS) $(WAYLAND_EGL_CFLAGS) $(XKBCOMMON_CFLAGS) $(XKBREGISTRY_CFLAGS) UNIX_LIBS = -lwin32u $(WAYLAND_CLIENT_LIBS) $(WAYLAND_EGL_LIBS) $(XKBCOMMON_LIBS) $(XKBREGISTRY_LIBS) $(PTHREAD_LIBS) -lm +IMPORTS = advapi32
SOURCES = \ display.c \ diff --git a/dlls/winewayland.drv/dllmain.c b/dlls/winewayland.drv/dllmain.c index d040620957b..a958533fc27 100644 --- a/dlls/winewayland.drv/dllmain.c +++ b/dlls/winewayland.drv/dllmain.c @@ -20,7 +20,9 @@
#include "waylanddrv_dll.h"
+#include "winreg.h" #include "wine/debug.h" +#include "wine/server_protocol.h"
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
@@ -38,12 +40,52 @@ static DWORD WINAPI wayland_read_events_thread(void *arg) BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved) { DWORD tid; + DWORD regRes; + DWORD regValueSize; + LPWSTR regValue = NULL; + HKEY hSubKey = NULL; + UINT rawinput_flag = 0;
if (reason != DLL_PROCESS_ATTACH) return TRUE;
DisableThreadLibraryCalls(instance); if (__wine_init_unix_call()) return FALSE;
+ regRes = RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\Wine\Wayland Driver", 0, KEY_READ, &hSubKey); + if (regRes != ERROR_SUCCESS) + { + WINE_TRACE("Registry key HKCU\Software\Wine\Wayland Driver not exist.\n"); + goto close_registry; + } + + regRes = RegQueryValueExW(hSubKey, L"rawinput", NULL, NULL, NULL, ®ValueSize); + if (regRes != ERROR_SUCCESS) + { + WINE_ERR("Can't get value size for HKCU\Software\Wine\Wayland Driver\rawinput. Error: %ld\n", regRes); + goto close_registry; + } + + regValue = calloc(regValueSize + 1, sizeof(*regValue)); + + regRes = RegQueryValueExW(hSubKey, L"rawinput", NULL, NULL, (LPBYTE)regValue, ®ValueSize); + if (regRes != ERROR_SUCCESS) + { + WINE_ERR("Can't get value for HKCU\Software\Wine\Wayland Driver\rawinput. Error: %ld\n", regRes); + free(regValue); + goto close_registry; + } + + WINE_TRACE("Registry HKCU\Software\Wine\Wayland Driver\rawinput value=%hs.\n", regValue); + if(*regValue) + rawinput_flag = SEND_HWMSG_RAWINPUT; + + free(regValue); + +close_registry: + RegCloseKey(hSubKey); + + WAYLANDDRV_UNIX_CALL(set_rawinput_flag, &rawinput_flag); + if (WAYLANDDRV_UNIX_CALL(init, NULL)) return FALSE;
diff --git a/dlls/winewayland.drv/unixlib.h b/dlls/winewayland.drv/unixlib.h index dc3bfdf8893..cf81b88498d 100644 --- a/dlls/winewayland.drv/unixlib.h +++ b/dlls/winewayland.drv/unixlib.h @@ -27,6 +27,7 @@ enum waylanddrv_unix_func { waylanddrv_unix_func_init, waylanddrv_unix_func_read_events, + waylanddrv_unix_func_set_rawinput_flag, waylanddrv_unix_func_count, };
diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index 1d8acaeabd2..51f3c202f5a 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -31,9 +31,12 @@
#include "waylanddrv.h" #include "wine/debug.h" +#include "wine/server_protocol.h"
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
+extern UINT waylanddrv_rawinput_flag; + static HWND wayland_pointer_get_focused_hwnd(void) { struct wayland_pointer *pointer = &process_wayland.pointer; @@ -86,7 +89,7 @@ static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy) hwnd, wl_fixed_to_double(sx), wl_fixed_to_double(sy), (int)screen.x, (int)screen.y);
- NtUserSendHardwareInput(hwnd, 0, &input, 0); + NtUserSendHardwareInput(hwnd, waylanddrv_rawinput_flag, &input, 0); }
static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer, @@ -185,7 +188,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
TRACE("hwnd=%p button=%#x state=%u\n", hwnd, button, state);
- NtUserSendHardwareInput(hwnd, 0, &input, 0); + NtUserSendHardwareInput(hwnd, waylanddrv_rawinput_flag, &input, 0); }
static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer, @@ -232,7 +235,7 @@ static void pointer_handle_axis_discrete(void *data, struct wl_pointer *wl_point
TRACE("hwnd=%p axis=%u discrete=%d\n", hwnd, axis, discrete);
- NtUserSendHardwareInput(hwnd, 0, &input, 0); + NtUserSendHardwareInput(hwnd, waylanddrv_rawinput_flag, &input, 0); }
static const struct wl_pointer_listener pointer_listener = @@ -259,15 +262,28 @@ static void relative_pointer_v1_relative_motion(void *data, POINT screen, origin; struct wayland_surface *surface; RECT window_rect; + double delta_x; + double delta_y;
if (!(hwnd = wayland_pointer_get_focused_hwnd())) return; if (!(surface = wayland_surface_lock_hwnd(hwnd))) return;
window_rect = surface->window.rect;
+ if(waylanddrv_rawinput_flag & SEND_HWMSG_RAWINPUT) + { + delta_x = wl_fixed_to_double(dx_unaccel); + delta_y = wl_fixed_to_double(dy_unaccel); + } + else + { + delta_x = wl_fixed_to_double(dx); + delta_y = wl_fixed_to_double(dy); + } + wayland_surface_coords_to_window(surface, - wl_fixed_to_double(dx), - wl_fixed_to_double(dy), + delta_x, + delta_y, (int *)&screen.x, (int *)&screen.y);
pthread_mutex_unlock(&surface->mutex); @@ -313,11 +329,12 @@ static void relative_pointer_v1_relative_motion(void *data, input.mi.dy = screen.y; input.mi.dwFlags = MOUSEEVENTF_MOVE;
- TRACE("hwnd=%p wayland_dxdy=%.2f,%.2f screen_dxdy=%d,%d\n", - hwnd, wl_fixed_to_double(dx), wl_fixed_to_double(dy), + TRACE("hwnd=%p rawinput=%d wayland_dxdy=%.2f,%.2f screen_dxdy=%d,%d\n", + hwnd, waylanddrv_rawinput_flag, delta_x, delta_y, (int)screen.x, (int)screen.y);
- NtUserSendHardwareInput(hwnd, 0, &input, 0); + NtUserSendHardwareInput(hwnd, waylanddrv_rawinput_flag, &input, 0); + }
static const struct zwp_relative_pointer_v1_listener relative_pointer_v1_listener = diff --git a/dlls/winewayland.drv/waylanddrv_main.c b/dlls/winewayland.drv/waylanddrv_main.c index 47c1299dd01..5b3e56a286b 100644 --- a/dlls/winewayland.drv/waylanddrv_main.c +++ b/dlls/winewayland.drv/waylanddrv_main.c @@ -80,6 +80,14 @@ static void wayland_init_process_name(void) } }
+UINT waylanddrv_rawinput_flag; + +static NTSTATUS waylanddrv_unix_set_rawinput_flag(void *arg) +{ + waylanddrv_rawinput_flag = arg ? *((UINT *)arg) : 0; + return 0; +} + static NTSTATUS waylanddrv_unix_init(void *arg) { /* Set the user driver functions now so that they are available during @@ -111,6 +119,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = { waylanddrv_unix_init, waylanddrv_unix_read_events, + waylanddrv_unix_set_rawinput_flag, };
C_ASSERT(ARRAYSIZE(__wine_unix_call_funcs) == waylanddrv_unix_func_count); @@ -121,6 +130,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = { waylanddrv_unix_init, waylanddrv_unix_read_events, + waylanddrv_unix_set_rawinput_flag, };
C_ASSERT(ARRAYSIZE(__wine_unix_call_wow64_funcs) == waylanddrv_unix_func_count);
On Tue Jun 18 18:39:38 2024 +0000, Grigory Vasilyev wrote:
@rbernon I also don’t fully understand whether I should change rawmouse->usFlags as in the wine-staging patch.
- rawmouse->usFlags = MOUSE_MOVE_RELATIVE; + rawmouse->usFlags = 0; + if (flags & MOUSEEVENTF_ABSOLUTE) rawmouse->usFlags |= MOUSE_MOVE_ABSOLUTE; + if (flags & MOUSEEVENTF_VIRTUALDESK) rawmouse->usFlags |= MOUSE_VIRTUAL_DESKTOP;
I'm confused by these changes in Proton. https://github.com/ValveSoftware/wine/commit/8fa1095bb13ea7f366ade8c4345bb3a... https://github.com/ValveSoftware/wine/commit/dda751149ea103082d9530f15b701b7...
The important part from [0001-server-Add-support-for-absolute-rawinput-mouse-messa.patch](https://gitlab.winehq.org/wine/wine-staging/-/blob/0c3e34dc139cb78a6cd55311f...) is that x and y go in unmodified (the `x - desktop->cursor.x` is now just `x`).
On Tue Jun 18 18:43:49 2024 +0000, Errno Ebadf wrote:
The important part from [0001-server-Add-support-for-absolute-rawinput-mouse-messa.patch](https://gitlab.winehq.org/wine/wine-staging/-/blob/0c3e34dc139cb78a6cd55311f...) is that x and y go in unmodified (the `x - desktop->cursor.x` is now just `x`).
@EBADF I know it. See my patches.
Errno Ebadf (@EBADF) commented about dlls/winewayland.drv/wayland_pointer.c:
input.mi.dy = screen.y; input.mi.dwFlags = MOUSEEVENTF_MOVE;
- TRACE("hwnd=%p wayland_dxdy=%.2f,%.2f screen_dxdy=%d,%d\n",
hwnd, wl_fixed_to_double(dx), wl_fixed_to_double(dy),
- TRACE("hwnd=%p rawinput=%d wayland_dxdy=%.2f,%.2f screen_dxdy=%d,%d\n",
hwnd, waylanddrv_rawinput_flag, delta_x, delta_y, (int)screen.x, (int)screen.y);
- NtUserSendHardwareInput(hwnd, 0, &input, 0);
- NtUserSendHardwareInput(hwnd, waylanddrv_rawinput_flag, &input, 0);
Need to send two NtUserSendHardwareInput() calls. - First with SEND_HWMSG_NO_RAW with the normal accelerated relative motion. - Second with SEND_HWMSG_NO_MSG with the unaccelerated relative motion.
If you don't have those flags then wine will automatically create a rawinput (WM_INPUT) event from a normal (WM_MOUSEMOVE) event.
On Tue Jun 18 18:59:48 2024 +0000, Errno Ebadf wrote:
Need to send two NtUserSendHardwareInput() calls.
- First with SEND_HWMSG_NO_RAW with the normal accelerated relative motion.
- Second with SEND_HWMSG_NO_MSG with the unaccelerated relative motion
and a new input struct That way the normal accelerated mouse event still gets through with the accelerated data (WM_MOUSEMOVE) and it matches the desktop pointer which is just like windows. We only want the raw input (WM_INPUT) message to have unaccelerated pointer data, so we need to send that too. Also need both server patches from wine-staging user32-rawinput-mouse:
- [0001-server-Add-support-for-absolute-rawinput-mouse-messa.patch](https://gitlab.winehq.org/wine/wine-staging/-/blob/v9.11/patches/user32-rawi...)
- [0004-server-Add-send_hardware_message-flags-for-rawinput-.patch](https://gitlab.winehq.org/wine/wine-staging/-/blob/v9.11/patches/user32-rawi...)
Unfortunately the 0001 patch will break x11 raw input... maybe we need to change wayland and x11 at the same time ;-) Or you could adjust the 0001 patch to only use the raw `x` and `y` when the `SEND_HWMSG_NO_MSG` is set. That way the x11 driver will still synthesize raw inputs the exact same way it does currently.
@EBADF Proton only uses one flag, and my solution is based on proton's code. At least everything works as it should. As I understand it, Wine always generates one of the message types from the other, and there are no separate threads for updating both at once. Therefore, @rbernon suggested the option of using `lparam` in `NtUserSendHardwareInput`. I don't yet fully understand how this all works, and which solution is more correct from proton or wine-staging. https://github.com/ValveSoftware/wine/commit/7ecb696933b019dbb6b124ca1e18f87...
On Tue Jun 18 18:59:48 2024 +0000, Grigory Vasilyev wrote:
@EBADF Proton only uses one flag, and my solution is based on proton's code. At least everything works as it should. As I understand it, Wine always generates one of the message types from the other, and there are no separate threads for updating both at once. Therefore, @rbernon suggested the option of using `lparam` in `NtUserSendHardwareInput`. I don't yet fully understand how this all works, and which solution is more correct from proton or wine-staging. https://github.com/ValveSoftware/wine/commit/7ecb696933b019dbb6b124ca1e18f87...
You are right I made some wrong assumptions, sorry! I see your patch is different from the newer wine-staging ones (indeed it is like the old one that is in proton). Ultimately you need to give the server the accelerated data AND the unaccelerated data. From what I see your changes only give it the unaccelerated data which is not right (desktop mouse motion won't be correct because it is unaccelerated). The old send_hardware_message() accepted a RAWINPUT struct that you had to populate when you set the SEND_HWMSG_RAWINPUT flag. I am getting confused (sorry!) -- looks like wine has been refactored quite a bit since then. I can't figure out how you are supposed to get the rawinput data in separately from the regular mouse motion.
In my opinion using the latest wine-staging patches makes it very straightforward to implement as I described in my earlier comment.
On Tue Jun 18 18:43:49 2024 +0000, Grigory Vasilyev wrote:
@EBADF I know it. See my patches.
Again, apologies for my assumption earlier! Your changes do already take the x and y as specified.
My two cents is it doesn't matter if you keep the flags or not. Keeping the flags makes it easier for drivers to implement absolute/virtual rawinput mouse in the future, but would they? Maybe for a tablet. Note hardcoding 0 is the same as MOUSE_MOVE_RELATIVE.
Following along at https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawmo..., the special thing to know about absolute raw input is that x and y are out of 65535 (i.e. 16 bits of precision). I'm not really sure how MOUSE_VIRTUAL_DESKTOP would work out.
The input path goes like this: - NtUserSendHardwareInput fills `struct send_hardware_input_params` - dlls/win32u/window.c:NtUserCallHwndParam() takes data from `send_hardware_input_params` and calls send_hardware_message() - dlls/win32u/message.c:send_hardware_message() queues a message to wineserver of type 'struct send_hardware_message_request' - server/queue.c:DECL_HANDLER(send_hardware_message) wineserver receives the send_hardware_message request and processes it (sending input to relevant windows, etc...)
Just like @rbernon says it is possible to stuff data into lparam and get it all the way to wineserver. And it probably would be good to do it that way in order to avoid two server requests for every mouse move! But your changes right now do not put anything in lparam.
Current proton (and old-style wine-staging patches) puts a RAWINPUT struct in lparam but the x11drv seems to *try* to support rawinput but does it in a confusing way and does not actually work.
On Wed Jun 19 04:58:40 2024 +0000, Errno Ebadf wrote:
The input path goes like this:
- NtUserSendHardwareInput fills `struct send_hardware_input_params`
- dlls/win32u/window.c:NtUserCallHwndParam() takes data from
`send_hardware_input_params` and calls send_hardware_message()
- dlls/win32u/message.c:send_hardware_message() queues a message to
wineserver of type 'struct send_hardware_message_request'
- server/queue.c:DECL_HANDLER(send_hardware_message) wineserver receives
the send_hardware_message request and processes it (sending input to relevant windows, etc...) Just like @rbernon says it is possible to stuff data into lparam and get it all the way to wineserver. And it probably would be good to do it that way in order to avoid two server requests for every mouse move! But your changes right now do not put anything in lparam. Current proton (and old-style wine-staging patches) puts a RAWINPUT struct in lparam but the x11drv seems to *try* to support rawinput but does it in a confusing way and does not actually work.
Oops, I was wrong about lparam. It does not survive all the way to the server. The lparam in win32u/message.c:send_hardware_message() just adjusts the request to the server (which is defined in `struct send_hardware_message_request` (generated from `server/protocol.def`).
I think what @rbernon meant when they said "pass the raw values in a custom struct" would be giving extra data to win32u/message.c:send_hardware_message() via lparam in order to build the wineserver request to include unaccelerated values.
I like the idea of sending both accel and unaccel coordinates in one call to the server. All we really need extra is unaccel_x and unaccel_y (16 bits each). Is it okay to extend the hw_input_t.mouse struct? That would be simple.
(And dang, I am finding problems with my x11drv proton patches. Anyway, hopefully my braindumps help more than hurt. I would be happy to jump on IRC to chat about it if you want).
On Wed Jun 19 04:58:40 2024 +0000, Errno Ebadf wrote:
Oops, I was wrong about lparam. It does not survive all the way to the server. The lparam in win32u/message.c:send_hardware_message() just adjusts the request to the server (which is defined in `struct send_hardware_message_request` (generated from `server/protocol.def`). I think what @rbernon meant when they said "pass the raw values in a custom struct" would be giving extra data to win32u/message.c:send_hardware_message() via lparam in order to build the wineserver request to include unaccelerated values. I like the idea of sending both accel and unaccel coordinates in one call to the server. All we really need extra is unaccel_x and unaccel_y (16 bits each). Is it okay to extend the hw_input_t.mouse struct? That would be simple. (And dang, I am finding problems with my x11drv proton patches. Anyway, hopefully my braindumps help more than hurt. I would be happy to jump on IRC to chat about it if you want).
Yeah, instead of a struct you could even just pass the raw values with `lparam = MAKELONG(x_raw, y_raw)` and use the flag to indicate they should be read from it. It would still require an additional field in `hw_input_t::mouse`.
On Tue Jun 18 22:48:47 2024 +0000, Errno Ebadf wrote:
Again, apologies for my assumption earlier! Your changes do already take the x and y as specified. My two cents is it doesn't matter if you keep the flags or not. Keeping the flags makes it easier for drivers to implement absolute/virtual rawinput mouse in the future, but would they? Maybe for a tablet. Note hardcoding 0 is the same as MOUSE_MOVE_RELATIVE. Following along at https://learn.microsoft.com/en-us/windows/win32/api/winuser/ns-winuser-rawmo..., the special thing to know about absolute raw input is that x and y are out of 65535 (i.e. 16 bits of precision). I'm not really sure how MOUSE_VIRTUAL_DESKTOP would work out.
These changes are for absolute raw motion, which isn't available in wayland IIUC anyway. I'm not sure you need to worry about them.
Note that if I understand correctly this will also make the raw input messages change from accelerated to non-accelerated values back and forth when the cursor is clipped/unclipped. It might cause some issues and maybe it would be better to find a way to receive unaccelerated values all the time. I'm not completely sure how this can be done, but basically needs to have `zwp_relative_pointer_v1` all the time, while keeping absolute position to make sure Wine doesn't drift away.