소스 검색

wayland: Scale custom cursors with the pointer scale

When emulating display modes or using display scaling, custom cursors need to be scaled, or they can appear too large or small relative to the window size.
Frank Praznik 3 달 전
부모
커밋
3d21b3bc68
3개의 변경된 파일45개의 추가작업 그리고 6개의 파일을 삭제
  1. 36 6
      src/video/wayland/SDL_waylandmouse.c
  2. 1 0
      src/video/wayland/SDL_waylandmouse.h
  3. 8 0
      src/video/wayland/SDL_waylandwindow.c

+ 36 - 6
src/video/wayland/SDL_waylandmouse.c

@@ -1103,12 +1103,14 @@ static void Wayland_CursorStateSetCursor(SDL_WaylandCursorState *state, const Wa
 
 
             dst_height = dst_width;
             dst_height = dst_width;
         } else {
         } else {
-            // If viewports aren't available, the scale is always 1.0.
-            state->scale = viddata->viewporter && focus ? focus->scale_factor : 1.0;
-            dst_width = cursor_data->cursor_data.custom.width;
-            dst_height = cursor_data->cursor_data.custom.height;
-            hot_x = cursor_data->cursor_data.custom.hot_x;
-            hot_y = cursor_data->cursor_data.custom.hot_y;
+            /* If viewports aren't available, the scale is always 1.0.
+             * The dimensions are scaled by the pointer scale, so custom cursors will be scaled relative to the window size.
+             */
+            state->scale = viddata->viewporter && focus ? SDL_min(focus->pointer_scale.x, focus->pointer_scale.y) : 1.0;
+            dst_width = SDL_max((int)SDL_lround((double)cursor_data->cursor_data.custom.width / state->scale), 1);
+            dst_height = SDL_max((int)SDL_lround((double)cursor_data->cursor_data.custom.height / state->scale), 1);
+            hot_x = (int)SDL_lround((double)cursor_data->cursor_data.custom.hot_x / state->scale);
+            hot_y = (int)SDL_lround((double)cursor_data->cursor_data.custom.hot_y / state->scale);
         }
         }
 
 
         state->current_cursor = cursor_data;
         state->current_cursor = cursor_data;
@@ -1180,6 +1182,34 @@ static void Wayland_CursorStateResetCursor(SDL_WaylandCursorState *state)
     state->current_frame = -1;
     state->current_frame = -1;
 }
 }
 
 
+void Wayland_DisplayUpdatePointerFocusedScale(SDL_WindowData *updated_window)
+{
+    SDL_VideoData *viddata = updated_window->waylandData;
+    SDL_WaylandSeat *seat;
+    const double new_scale = SDL_min(updated_window->pointer_scale.x, updated_window->pointer_scale.y);
+
+    wl_list_for_each (seat, &viddata->seat_list, link) {
+        if (seat->pointer.focus == updated_window) {
+            SDL_WaylandCursorState *state = &seat->pointer.cursor_state;
+            if (state->current_cursor && !state->current_cursor->is_system_cursor && state->scale != new_scale) {
+                Wayland_CursorStateResetCursor(state);
+                Wayland_SeatUpdatePointerCursor(seat);
+            }
+        }
+
+        SDL_WaylandPenTool *tool;
+        wl_list_for_each (tool, &seat->tablet.tool_list, link) {
+            if (tool->focus == updated_window) {
+                SDL_WaylandCursorState *state = &tool->cursor_state;
+                if (state->current_cursor && !state->current_cursor->is_system_cursor && state->scale != new_scale) {
+                    Wayland_CursorStateResetCursor(&tool->cursor_state);
+                    Wayland_TabletToolUpdateCursor(tool);
+                }
+            }
+        }
+    }
+}
+
 static bool Wayland_ShowCursor(SDL_Cursor *cursor)
 static bool Wayland_ShowCursor(SDL_Cursor *cursor)
 {
 {
     SDL_VideoDevice *vd = SDL_GetVideoDevice();
     SDL_VideoDevice *vd = SDL_GetVideoDevice();

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

@@ -29,6 +29,7 @@ extern void Wayland_FiniMouse(SDL_VideoData *data);
 extern void Wayland_SeatUpdatePointerCursor(SDL_WaylandSeat *seat);
 extern void Wayland_SeatUpdatePointerCursor(SDL_WaylandSeat *seat);
 extern void Wayland_SeatSetDefaultCursor(SDL_WaylandSeat *seat);
 extern void Wayland_SeatSetDefaultCursor(SDL_WaylandSeat *seat);
 extern void Wayland_SeatResetCursor(SDL_WaylandSeat *seat);
 extern void Wayland_SeatResetCursor(SDL_WaylandSeat *seat);
+extern void Wayland_DisplayUpdatePointerFocusedScale(SDL_WindowData *updated_window);
 extern void Wayland_TabletToolUpdateCursor(SDL_WaylandPenTool *tool);
 extern void Wayland_TabletToolUpdateCursor(SDL_WaylandPenTool *tool);
 extern void Wayland_SeatWarpMouse(SDL_WaylandSeat *seat, SDL_WindowData *window, float x, float y);
 extern void Wayland_SeatWarpMouse(SDL_WaylandSeat *seat, SDL_WindowData *window, float x, float y);
 extern void Wayland_CursorStateSetFrameCallback(SDL_WaylandCursorState *state, void *userdata);
 extern void Wayland_CursorStateSetFrameCallback(SDL_WaylandCursorState *state, void *userdata);

+ 8 - 0
src/video/wayland/SDL_waylandwindow.c

@@ -30,6 +30,7 @@
 #include "../../core/unix/SDL_appid.h"
 #include "../../core/unix/SDL_appid.h"
 #include "../SDL_egl_c.h"
 #include "../SDL_egl_c.h"
 #include "SDL_waylandevents_c.h"
 #include "SDL_waylandevents_c.h"
+#include "SDL_waylandmouse.h"
 #include "SDL_waylandwindow.h"
 #include "SDL_waylandwindow.h"
 #include "SDL_waylandvideo.h"
 #include "SDL_waylandvideo.h"
 #include "../../SDL_hints_c.h"
 #include "../../SDL_hints_c.h"
@@ -287,6 +288,8 @@ static void ConfigureWindowGeometry(SDL_Window *window)
 {
 {
     SDL_WindowData *data = window->internal;
     SDL_WindowData *data = window->internal;
     const double scale_factor = GetWindowScale(window);
     const double scale_factor = GetWindowScale(window);
+    const double prev_pointer_scale_x = data->pointer_scale.x;
+    const double prev_pointer_scale_y = data->pointer_scale.y;
     const int old_pixel_width = data->current.pixel_width;
     const int old_pixel_width = data->current.pixel_width;
     const int old_pixel_height = data->current.pixel_height;
     const int old_pixel_height = data->current.pixel_height;
     int window_width = 0;
     int window_width = 0;
@@ -566,6 +569,11 @@ static void ConfigureWindowGeometry(SDL_Window *window)
         }
         }
     }
     }
 
 
+    // Update the scale for any focused cursors.
+    if (prev_pointer_scale_x != data->pointer_scale.x || prev_pointer_scale_y != data->pointer_scale.y) {
+        Wayland_DisplayUpdatePointerFocusedScale(data);
+    }
+
     /* Update the min/max dimensions, primarily if the state was changed, and for non-resizable
     /* Update the min/max dimensions, primarily if the state was changed, and for non-resizable
      * xdg-toplevel windows where the limits should match the window size.
      * xdg-toplevel windows where the limits should match the window size.
      */
      */