SDL: wayland: Scale the pointer destination size relative to the theme size

From 7ca0e9ede151aaa8ab2d3f835fbb3437181c82ff Mon Sep 17 00:00:00 2001
From: Frank Praznik <[EMAIL REDACTED]>
Date: Sat, 28 Sep 2024 14:29:24 -0400
Subject: [PATCH] wayland: Scale the pointer destination size relative to the
 theme size

This better matches compositor behavior and avoids slight size jumps when the cursor enters and leaves the window.
---
 src/video/wayland/SDL_waylandmouse.c | 30 +++++++++++++---------------
 1 file changed, 14 insertions(+), 16 deletions(-)

diff --git a/src/video/wayland/SDL_waylandmouse.c b/src/video/wayland/SDL_waylandmouse.c
index 6e9b0122b7b24..3c35424a2b35d 100644
--- a/src/video/wayland/SDL_waylandmouse.c
+++ b/src/video/wayland/SDL_waylandmouse.c
@@ -423,34 +423,32 @@ static bool Wayland_GetSystemCursor(SDL_VideoData *vdata, SDL_CursorData *cdata,
     }
 
     *scale = SDL_ceil(scale_factor) == scale_factor ? (int)scale_factor : 0;
-    *dst_size = theme_size;
 
-    // Calculate the hotspot offset if the cursor is being scaled.
-    if (scaled_size == cursor->images[0]->width) {
-        // If the theme has an exact size match, just divide by the scale.
-        *hot_x = (int)SDL_lround(cursor->images[0]->hotspot_x / scale_factor);
-        *hot_y = (int)SDL_lround(cursor->images[0]->hotspot_y / scale_factor);
-    } else {
+    if (scaled_size != cursor->images[0]->width) {
+        /* If the cursor size isn't an exact match for the target size, use a viewport
+         * to avoid a possible "Buffer size is not divisible by scale" protocol error.
+         *
+         * If viewports are unavailable, find an integer scale that works.
+         */
         if (vdata->viewporter) {
-            // Use a viewport if no exact size match is found to avoid a potential "buffer size is not divisible by scale" protocol error.
+            // A scale of 0 indicates that a viewport set to the destination size should be used.
             *scale = 0;
-
-            // Map the hotspot coordinates from the source to destination sizes.
-            const double hotspot_scale = (double)theme_size / (double)cursor->images[0]->width;
-            *hot_x = (int)SDL_lround(hotspot_scale * cursor->images[0]->hotspot_x);
-            *hot_y = (int)SDL_lround(hotspot_scale * cursor->images[0]->hotspot_y);
         } else {
-            // No exact match, and viewports are unsupported. Find a safe integer scale.
             for (; *scale > 1; --*scale) {
                 if (cursor->images[0]->width % *scale == 0) {
                     break;
                 }
             }
-            *hot_x = cursor->images[0]->hotspot_x / *scale;
-            *hot_y = cursor->images[0]->hotspot_y / *scale;
+            // Set the scale factor to the new value for the hotspot calculations.
+            scale_factor = *scale;
         }
     }
 
+    *dst_size = (int)SDL_lround(cursor->images[0]->width / scale_factor);
+
+    *hot_x = (int)SDL_lround(cursor->images[0]->hotspot_x / scale_factor);
+    *hot_y = (int)SDL_lround(cursor->images[0]->hotspot_y / scale_factor);
+
     return true;
 }