瀏覽代碼

Added SDL_HINT_MOUSE_DPI_SCALE_CURSORS

We only want to change cursor display scale if the application or the user opts in by setting a hint. Otherwise cursors could change size unexpectedly when upgrading to SDL 3.4.0.
Sam Lantinga 3 天之前
父節點
當前提交
466ca58b04
共有 5 個文件被更改,包括 39 次插入8 次删除
  1. 1 0
      WhatsNew.txt
  2. 14 0
      include/SDL3/SDL_hints.h
  3. 1 1
      include/SDL3/SDL_mouse.h
  4. 17 4
      src/video/wayland/SDL_waylandmouse.c
  5. 6 3
      src/video/windows/SDL_windowsmouse.c

+ 1 - 0
WhatsNew.txt

@@ -7,6 +7,7 @@ This is a list of major changes in SDL's version history.
 
 General:
 * Added SDL_CreateAnimatedCursor() to create animated color cursors
+* Added SDL_HINT_MOUSE_DPI_SCALE_CURSORS to automatically scale cursors based on the display scale
 * Added SDL_SetWindowProgressState(), SDL_SetWindowProgressValue(), SDL_GetWindowProgressState(), and SDL_GetWindowProgressValue() to show progress in the window's taskbar icon on Windows and Linux
 * Added GPU device creation properties to enable the GPU API on older hardware if you're not using these features:
   - SDL_PROP_GPU_DEVICE_CREATE_FEATURE_CLIP_DISTANCE_BOOLEAN

+ 14 - 0
include/SDL3/SDL_hints.h

@@ -2692,6 +2692,20 @@ extern "C" {
  */
 #define SDL_HINT_MOUSE_DEFAULT_SYSTEM_CURSOR "SDL_MOUSE_DEFAULT_SYSTEM_CURSOR"
 
+/**
+ * A variable setting whether we should scale cursors by the current display scale.
+ *
+ * The variable can be set to the following values:
+ *
+ * - "0": Cursors will not change size based on the display content scale. (default)
+ * - "1": Cursors will automatically match the display content scale (e.g. a 2x sized cursor will be used when the window is on a monitor with 200% scale). This is currently implemented on Windows and Wayland.
+ *
+ * This hint needs to be set before creating cursors.
+ *
+ * \since This hint is available since SDL 3.4.0.
+ */
+#define SDL_HINT_MOUSE_DPI_SCALE_CURSORS "SDL_MOUSE_DPI_SCALE_CURSORS"
+
 /**
  * A variable controlling whether warping a hidden mouse cursor will activate
  * relative mouse mode.

+ 1 - 1
include/SDL3/SDL_mouse.h

@@ -593,7 +593,7 @@ extern SDL_DECLSPEC SDL_Cursor * SDLCALL SDL_CreateCursor(const Uint8 *data,
  * If this function is passed a surface with alternate representations added
  * with SDL_AddSurfaceAlternateImage(), the surface will be interpreted as the
  * content to be used for 100% display scale, and the alternate
- * representations will be used for high DPI situations. For example, if the
+ * representations will be used for high DPI situations if SDL_HINT_MOUSE_DPI_SCALE_CURSORS is enabled. For example, if the
  * original surface is 32x32, then on a 2x macOS display or 200% display scale
  * on Windows, a 64x64 version of the image will be used, if available. If a
  * matching version of the image isn't available, the closest larger size

+ 17 - 4
src/video/wayland/SDL_waylandmouse.c

@@ -1025,6 +1025,21 @@ typedef struct Wayland_PointerObject
     bool is_pointer;
 } Wayland_PointerObject;
 
+static float Wayland_GetCursorScale(SDL_WindowData *focus)
+{
+    SDL_VideoData *viddata = SDL_GetVideoDevice()->internal;
+
+    if (!SDL_GetHintBoolean(SDL_HINT_MOUSE_DPI_SCALE_CURSORS, false)) {
+        return 1.0f;
+    }
+
+    // If viewports aren't available, the scale is always 1.0.
+    if (viddata->viewporter && focus) {
+        return (float)focus->scale_factor;
+    }
+    return 1.0f;
+}
+
 static void Wayland_CursorStateSetCursor(SDL_WaylandCursorState *state, const Wayland_PointerObject *obj, SDL_WindowData *focus, Uint32 serial, SDL_Cursor *cursor)
 {
     SDL_VideoData *viddata = SDL_GetVideoDevice()->internal;
@@ -1079,16 +1094,14 @@ static void Wayland_CursorStateSetCursor(SDL_WaylandCursorState *state, const Wa
                 return;
             }
 
-            // If viewports aren't available, the scale is always 1.0.
-            state->scale = viddata->viewporter && focus ? focus->scale_factor : 1.0;
+            state->scale = Wayland_GetCursorScale(focus);
             if (!Wayland_GetSystemCursor(cursor_data, state, &dst_width, &hot_x, &hot_y)) {
                 return;
             }
 
             dst_height = dst_width;
         } else {
-            // If viewports aren't available, the scale is always 1.0.
-            state->scale = viddata->viewporter && focus ? focus->scale_factor : 1.0;
+            state->scale = Wayland_GetCursorScale(focus);
             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;

+ 6 - 3
src/video/windows/SDL_windowsmouse.c

@@ -566,9 +566,12 @@ static HCURSOR GetCachedCursor(SDL_Cursor *cursor)
 {
     SDL_CursorData *data = cursor->internal;
 
-    float scale = SDL_GetDisplayContentScale(SDL_GetDisplayForWindow(SDL_GetMouseFocus()));
-    if (scale == 0.0f) {
-        scale = 1.0f;
+    float scale = 1.0f;
+    if (SDL_GetHintBoolean(SDL_HINT_MOUSE_DPI_SCALE_CURSORS, false)) {
+        scale = SDL_GetDisplayContentScale(SDL_GetDisplayForWindow(SDL_GetMouseFocus()));
+        if (scale == 0.0f) {
+            scale = 1.0f;
+        }
     }
     for (CachedCursor *entry = data->cache; entry; entry = entry->next) {
         if (scale == entry->scale) {