Browse Source

Add SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL (#10085)

expikr 10 months ago
parent
commit
3b504c4a89

+ 13 - 0
include/SDL3/SDL_hints.h

@@ -2337,6 +2337,19 @@ extern "C" {
  */
 #define SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE  "SDL_MOUSE_RELATIVE_CURSOR_VISIBLE"
 
+/**
+ * Controls how often SDL issues cursor confinement commands to the operating
+ * system while relative mode is active, in case the desired confinement state 
+ * became out-of-sync due to interference from other running programs.
+ *
+ * The variable can be integers representing miliseconds between each refresh.
+ * A value of zero means SDL will not automatically refresh the confinement.
+ * The default value varies depending on the operating system, this variable
+ * might not have any effects on inapplicable platforms such as those without
+ * a cursor.
+ */
+#define SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL  "SDL_MOUSE_RELATIVE_CLIP_INTERVAL"
+
 /**
  * A variable controlling whether mouse events should generate synthetic touch
  * events.

+ 17 - 0
src/events/SDL_mouse.c

@@ -64,6 +64,17 @@ static void SDLCALL SDL_MouseDoubleClickTimeChanged(void *userdata, const char *
     }
 }
 
+static void SDLCALL SDL_MouseRelativeClipIntervalChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
+{
+    SDL_Mouse *mouse = (SDL_Mouse *)userdata;
+
+    if (hint && *hint) {
+        mouse->relative_mode_clip_interval = SDL_atoi(hint);
+    } else {
+        mouse->relative_mode_clip_interval = 3000;
+    }
+}
+
 static void SDLCALL SDL_MouseDoubleClickRadiusChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
 {
     SDL_Mouse *mouse = (SDL_Mouse *)userdata;
@@ -220,6 +231,9 @@ int SDL_PreInitMouse(void)
     SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
                         SDL_MouseRelativeCursorVisibleChanged, mouse);
 
+    SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL,
+                        SDL_MouseRelativeClipIntervalChanged, mouse);
+
     mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */
 
     mouse->cursor_shown = SDL_TRUE;
@@ -1133,6 +1147,9 @@ void SDL_QuitMouse(void)
     SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE,
                         SDL_MouseRelativeCursorVisibleChanged, mouse);
 
+    SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_CLIP_INTERVAL,
+                        SDL_MouseRelativeClipIntervalChanged, mouse);
+
     for (int i = SDL_mouse_count; i--; ) {
         SDL_RemoveMouse(SDL_mice[i].instance_id, SDL_FALSE);
     }

+ 1 - 0
src/events/SDL_mouse_c.h

@@ -92,6 +92,7 @@ typedef struct
     SDL_bool relative_mode_warp;
     SDL_bool relative_mode_warp_motion;
     SDL_bool relative_mode_cursor_visible;
+    int relative_mode_clip_interval;
     SDL_bool enable_normal_speed_scale;
     float normal_speed_scale;
     SDL_bool enable_relative_speed_scale;

+ 2 - 2
src/video/windows/SDL_windowsevents.c

@@ -2093,7 +2093,7 @@ static void WIN_UpdateClipCursorForWindows()
     SDL_VideoDevice *_this = SDL_GetVideoDevice();
     SDL_Window *window;
     Uint64 now = SDL_GetTicks();
-    const int CLIPCURSOR_UPDATE_INTERVAL_MS = 3000;
+    const int CLIPCURSOR_UPDATE_INTERVAL_MS = SDL_GetMouse()->relative_mode_clip_interval;
 
     if (_this) {
         for (window = _this->windows; window; window = window->next) {
@@ -2102,7 +2102,7 @@ static void WIN_UpdateClipCursorForWindows()
                 if (data->skip_update_clipcursor) {
                     data->skip_update_clipcursor = SDL_FALSE;
                     WIN_UpdateClipCursor(window);
-                } else if (now >= (data->last_updated_clipcursor + CLIPCURSOR_UPDATE_INTERVAL_MS)) {
+                } else if (CLIPCURSOR_UPDATE_INTERVAL_MS > 0 && now >= (data->last_updated_clipcursor + CLIPCURSOR_UPDATE_INTERVAL_MS)) {
                     WIN_UpdateClipCursor(window);
                 }
             }