Sfoglia il codice sorgente

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.
Frank Praznik 2 settimane fa
parent
commit
235e4870af

+ 9 - 0
src/events/SDL_mouse.c

@@ -1121,6 +1121,15 @@ int SDL_WarpMouseGlobal(int x, int y)
 
 
 static SDL_bool ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
 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) {
     if (!mouse->WarpMouse) {
         /* Need this functionality for relative mode warp implementation */
         /* Need this functionality for relative mode warp implementation */
         return SDL_FALSE;
         return SDL_FALSE;

+ 14 - 9
src/video/wayland/SDL_waylandevents.c

@@ -2681,23 +2681,28 @@ static void relative_pointer_handle_relative_motion(void *data,
     struct SDL_WaylandInput *input = data;
     struct SDL_WaylandInput *input = data;
     SDL_VideoData *d = input->display;
     SDL_VideoData *d = input->display;
     SDL_WindowData *window = input->pointer_focus;
     SDL_WindowData *window = input->pointer_focus;
-    double dx_unaccel;
-    double dy_unaccel;
     double dx;
     double dx;
     double dy;
     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. */
     /* 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) {
     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);
     }
     }
 }
 }
 
 

+ 3 - 0
src/video/wayland/SDL_waylandmouse.c

@@ -537,6 +537,9 @@ static int Wayland_SetRelativeMouseMode(SDL_bool enabled)
     SDL_VideoData *data = (SDL_VideoData *)vd->driverdata;
     SDL_VideoData *data = (SDL_VideoData *)vd->driverdata;
 
 
     if (enabled) {
     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. */
         /* Disable mouse warp emulation if it's enabled. */
         if (data->input->relative_mode_override) {
         if (data->input->relative_mode_override) {
             data->input->relative_mode_override = SDL_FALSE;
             data->input->relative_mode_override = SDL_FALSE;

+ 1 - 0
src/video/wayland/SDL_waylandvideo.h

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