diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 79fa091514..98ce50fef0 100644 --- a/include/SDL3/SDL_hints.h +++ b/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. diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 8de492058b..13ef1e9a93 100644 --- a/src/events/SDL_mouse.c +++ b/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); } diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 6d120ec3ec..2641107638 100644 --- a/src/events/SDL_mouse_c.h +++ b/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; diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c index b372e245eb..9cc060ac7c 100644 --- a/src/video/windows/SDL_windowsevents.c +++ b/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); } }