From 7ca0e9ede151aaa8ab2d3f835fbb3437181c82ff Mon Sep 17 00:00:00 2001 From: Frank Praznik 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 6e9b0122b7..3c35424a2b 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; }