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
From: Grigory Vasilyev h0tc0d3@gmail.com
--- dlls/win32u/message.c | 2 ++ include/wine/server_protocol.h | 3 ++- server/protocol.def | 1 + server/queue.c | 18 +++++++++++------- 4 files changed, 16 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..cf086ec729b 100644 --- a/server/queue.c +++ b/server/queue.c @@ -1839,8 +1839,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 +1980,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 +2043,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); + 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);
dispatch_rawinput_message( desktop, &raw_msg ); release_object( foreground ); @@ -2222,7 +2227,6 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c desktop->key_repeat.timeout = add_timeout_user( timeout, key_repeat_timeout, desktop ); } } - if (!unicode && (foreground = get_foreground_thread( desktop, win ))) { struct rawinput_message raw_msg = {0}; @@ -2981,7 +2985,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 DPI and do not depend on the compositor or OS.
For example, you want to set the sensitivity to half as much, and sensitivity curves in libinput are more difficult to calculate than in the games themselves. --- 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);