File winewayland-no-enter-move-if-relative.patch of Package wine
Stop sending a mouse move on surface enter if the last move was relative.
This reduces sudden movement jumps if a surface is in relative pointer mode and loses then regains focus.
Preventing them entirely would require some more rework..
diff --git a/dlls/winewayland.drv/wayland_pointer.c b/dlls/winewayland.drv/wayland_pointer.c
index b5126e2..3cdddfd 100644
--- a/dlls/winewayland.drv/wayland_pointer.c
+++ b/dlls/winewayland.drv/wayland_pointer.c
@@ -121,7 +121,7 @@ static HWND wayland_pointer_get_focused_hwnd(void)
return hwnd;
}
-static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy)
+static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy, BOOL is_enter)
{
INPUT input = {0};
RECT *window_rect;
@@ -132,7 +132,7 @@ static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy)
if (!(hwnd = wayland_pointer_get_focused_hwnd())) return;
if (!(data = wayland_win_data_get(hwnd))) return;
- if (!(surface = data->wayland_surface))
+ if (!(surface = data->wayland_surface) || (is_enter && data->last_mouse_move_was_relative))
{
wayland_win_data_release(data);
return;
@@ -152,6 +152,7 @@ static void pointer_handle_motion_internal(wl_fixed_t sx, wl_fixed_t sy)
else if (screen.x < window_rect->left) screen.x = window_rect->left;
if (screen.y >= window_rect->bottom) screen.y = window_rect->bottom - 1;
else if (screen.y < window_rect->top) screen.y = window_rect->top;
+ data->last_mouse_move_was_relative = FALSE;
wayland_win_data_release(data);
@@ -175,7 +176,7 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
/* Ignore absolute motion events if in relative mode. */
if (pointer->zwp_relative_pointer_v1) return;
- pointer_handle_motion_internal(sx, sy);
+ pointer_handle_motion_internal(sx, sy, FALSE);
}
static void wayland_set_cursor(HWND hwnd, HCURSOR hcursor, BOOL use_hcursor);
@@ -208,7 +209,7 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
/* Handle the enter as a motion, to account for cases where the
* window first appears beneath the pointer and won't get a separate
* motion event. */
- pointer_handle_motion_internal(sx, sy);
+ pointer_handle_motion_internal(sx, sy, TRUE);
}
static void pointer_handle_leave(void *data, struct wl_pointer *wl_pointer,
@@ -364,6 +365,7 @@ static void relative_pointer_v1_relative_motion(void *private,
wl_fixed_to_double(dx),
wl_fixed_to_double(dy),
&screen_x, &screen_y);
+ data->last_mouse_move_was_relative = TRUE;
wayland_win_data_release(data);
pthread_mutex_lock(&pointer->mutex);
diff --git a/dlls/winewayland.drv/waylanddrv.h b/dlls/winewayland.drv/waylanddrv.h
index cb331df..5336fe2 100644
--- a/dlls/winewayland.drv/waylanddrv.h
+++ b/dlls/winewayland.drv/waylanddrv.h
@@ -371,6 +371,7 @@ struct wayland_win_data
BOOL is_fullscreen;
BOOL managed;
BOOL layered_attribs_set;
+ BOOL last_mouse_move_was_relative;
};
struct wayland_win_data *wayland_win_data_get(HWND hwnd);