Adds an env variable WINE_WAYLAND_UNACCELERATED_POINTER which allows 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.
-- v3: winewayland.drv: Add unaccelerated pointer support
From: Grigory Vasilyev h0tc0d3@gmail.com
Adds an env variable WINE_WAYLAND_UNACCELERATED_POINTER which allows 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/wayland_pointer.c | 20 ++++++++++++++++---- dlls/winewayland.drv/waylanddrv_main.c | 9 +++++++++ 2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c index ccd477b3c91..45320b6c52e 100644 --- a/dlls/winewayland.drv/wayland_pointer.c +++ b/dlls/winewayland.drv/wayland_pointer.c @@ -35,6 +35,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(waylanddrv);
+extern BOOL waylanddrv_unaccelerated_pointer; + static HWND wayland_pointer_get_focused_hwnd(void) { struct wayland_pointer *pointer = &process_wayland.pointer; @@ -250,15 +252,25 @@ 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_unaccelerated_pointer){ + 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); @@ -304,8 +316,8 @@ 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 unaccelerated_pointer=%d wayland_dxdy=%.2f,%.2f screen_dxdy=%d,%d\n", + hwnd, waylanddrv_unaccelerated_pointer, delta_x, delta_y, (int)screen.x, (int)screen.y);
__wine_send_input(hwnd, &input, NULL); diff --git a/dlls/winewayland.drv/waylanddrv_main.c b/dlls/winewayland.drv/waylanddrv_main.c index b60d282aacb..eb4de94cc62 100644 --- a/dlls/winewayland.drv/waylanddrv_main.c +++ b/dlls/winewayland.drv/waylanddrv_main.c @@ -29,6 +29,8 @@
#include "waylanddrv.h"
+#include <stdlib.h> + static const struct user_driver_funcs waylanddrv_funcs = { .pClipCursor = WAYLAND_ClipCursor, @@ -45,8 +47,15 @@ static const struct user_driver_funcs waylanddrv_funcs = .pwine_get_vulkan_driver = WAYLAND_wine_get_vulkan_driver, };
+BOOL waylanddrv_unaccelerated_pointer; + static NTSTATUS waylanddrv_unix_init(void *arg) { + + const char *env_str = getenv("WINE_WAYLAND_UNACCELERATED_POINTER"); + if (env_str) + waylanddrv_unaccelerated_pointer = !!atoi(env_str); + /* Set the user driver functions now so that they are available during * our initialization. We clear them on error. */ __wine_set_user_driver(&waylanddrv_funcs, WINE_GDI_DRIVER_VERSION);
Thanks for MR. Although having such an option could be potentially useful, the best way to implement it would be as a driver option in the registry (i.e., under `HKCU\Software\Wine\Wayland Driver` and the per-app variant). Implementing the infrastructure to read such options would make this change large enough to fall outside the scope of the freeze. I would prefer that we implement this properly after the freeze.
Most compositors offer some way to turn off pointer acceleration globally, so at least there is a way for users to get the behavior they want in the meantime.
Note that we should only translate accelerated mouse input to the Windows rawinput (WM_INPUT) messages. Other mouse messages (WM_MOUSEMOVE) should reflect the host pointer acceleration [*]. Currently the rawinput messages are automatically generated from the absolute mouse input -and are therefore always using accelerated values- and there's no mechanism to do it separately upstream yet. Wine staging has one, to implement rawinput on X11, but it's not completely clear to me whether it should be done that way.
[*] At least until we have a Wine-specific mouse acceleration support but that's also another topic, and it's not even clear that we need or want one.
@afrantzis Okay, I'll try to do this.
@rbernon I lied a little in the text to MR. This is not entirely raw input, it is input with sensitivity = 1.0, or zero point in libinput curve, libinput adds profile influence to this input, but with a flat profile we will have behavior and sensitivity identical to Windows with acceleration disabled, thereby easily transferring settings games. This input leaves the profile, but resets the sensitivity, i.e. we can avoid double input conversion.
Note that we should only translate accelerated mouse input to the Windows rawinput (WM_INPUT) messages.
Did you mean "unaccelerated" here?
I don't think we need to do like raw input in staging patches, I think X11 will be deprecated in a few years and staging patches cause regression, input doesn't work under wayland. My MR is enough to achieve the behavior of staging patches + xwayland.
Regardless of X11 and staging, if I understood @rbernon's comment correctly, the right approach would be to implement a proper upstream mechanism for the drivers to provide "raw" input events, and the Wayland driver can use the unaccelerated values in those events. Then games will behave properly because they will get the unaccelerated values in raw events (my understanding is that [3d] generally tend to use raw events, or can be configured to do so).
If we have proper raw events, the proposed option to make normal events unaccelerated would not be as compelling, correct?
On Fri Dec 15 14:32:08 2023 +0000, Alexandros Frantzis wrote:
Note that we should only translate accelerated mouse input to the
Windows rawinput (WM_INPUT) messages. Did you mean "unaccelerated" here?
Yes sorry.
On Fri Dec 15 14:32:09 2023 +0000, Alexandros Frantzis wrote:
I don't think we need to do like raw input in staging patches, I think
X11 will be deprecated in a few years and staging patches cause regression, input doesn't work under wayland. My MR is enough to achieve the behavior of staging patches + xwayland. Regardless of X11 and staging, if I understood @rbernon's comment correctly, the right approach would be to implement a proper upstream mechanism for the drivers to provide "raw" input events, and the Wayland driver can use the unaccelerated values in those events. Then games will behave properly because they will get the unaccelerated values in raw events (my understanding is that [3d] generally tend to use raw events, or can be configured to do so). If we have proper raw events, the proposed option to make normal events unaccelerated would not be as compelling, correct?
yes, that's more correct.
On Fri Dec 15 14:41:34 2023 +0000, Grigory Vasilyev wrote:
yes, that's more correct.
In that case, I would propose pausing effort on this MR for now, until some consensus on the best path forward is reached (as mentioned, it's not freeze material anyway). It could be the case that something along the lines of your proposal is best for staging or proton, until an upstream solution is implemented. Thanks!