wayland: Special-case relative warp mode to deliver accelerated relative motion

The Wayland backend lacks pointer warp functionality, so special-case the relative warp mode hint to deliver accelerated relative motion deltas, which is ultimately what the client wants by enabling this hint.

(cherry picked from commit 235e4870af)
This commit is contained in:
Frank Praznik
2025-10-09 09:48:22 -04:00
parent bc67702d8d
commit 735d8a2dc8
4 changed files with 27 additions and 9 deletions

View File

@@ -1121,6 +1121,15 @@ int SDL_WarpMouseGlobal(int x, int y)
static SDL_bool ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
{
#ifdef SDL_VIDEO_DRIVER_WAYLAND
SDL_VideoDevice *vid = SDL_GetVideoDevice();
/* Wayland can't warp the mouse, but uses this hint internally to deliver accelerated motion */
if (SDL_strcmp(vid->name, "wayland") == 0) {
return SDL_FALSE;
}
#endif
if (!mouse->WarpMouse) {
/* Need this functionality for relative mode warp implementation */
return SDL_FALSE;

View File

@@ -2681,23 +2681,28 @@ static void relative_pointer_handle_relative_motion(void *data,
struct SDL_WaylandInput *input = data;
SDL_VideoData *d = input->display;
SDL_WindowData *window = input->pointer_focus;
double dx_unaccel;
double dy_unaccel;
double dx;
double dy;
double dx_mod;
double dy_mod;
dx_unaccel = wl_fixed_to_double(dx_unaccel_w);
dy_unaccel = wl_fixed_to_double(dy_unaccel_w);
if (!d->relative_mode_accelerated) {
dx = wl_fixed_to_double(dx_unaccel_w);
dy = wl_fixed_to_double(dy_unaccel_w);
} else {
dx = wl_fixed_to_double(dx_w) * (window ? window->pointer_scale_x : 1.0);
dy = wl_fixed_to_double(dy_w) * (window ? window->pointer_scale_y : 1.0);
}
/* Add left over fraction from last event. */
dx_unaccel += input->dx_frac;
dy_unaccel += input->dy_frac;
dx += input->dx_frac;
dy += input->dy_frac;
input->dx_frac = modf(dx_unaccel, &dx);
input->dy_frac = modf(dy_unaccel, &dy);
input->dx_frac = modf(dx, &dx_mod);
input->dy_frac = modf(dy, &dy_mod);
if (input->pointer_focus && d->relative_mouse_mode) {
SDL_SendMouseMotion(window->sdlwindow, 0, 1, (int)dx, (int)dy);
SDL_SendMouseMotion(window->sdlwindow, 0, 1, (int)dx_mod, (int)dy_mod);
}
}

View File

@@ -537,6 +537,9 @@ static int Wayland_SetRelativeMouseMode(SDL_bool enabled)
SDL_VideoData *data = (SDL_VideoData *)vd->driverdata;
if (enabled) {
/* Clients use relative warp mode to get accelerated motion deltas, which Wayland delivers internally. */
data->relative_mode_accelerated = SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, SDL_FALSE);
/* Disable mouse warp emulation if it's enabled. */
if (data->input->relative_mode_override) {
data->input->relative_mode_override = SDL_FALSE;

View File

@@ -101,6 +101,7 @@ typedef struct
char *classname;
int relative_mouse_mode;
int relative_mode_accelerated;
SDL_bool egl_transparency_enabled;
} SDL_VideoData;