From c8bd0e7605304d5c932678e4cb987b54818d8626 Mon Sep 17 00:00:00 2001 From: expikr <77922942+expikr@users.noreply.github.com> Date: Mon, 28 Apr 2025 12:47:15 +0800 Subject: [PATCH] add SDL_HINT_MOUSE_CURSOR_SUSPEND_REDRAW --- include/SDL3/SDL_hints.h | 15 +++++++++++++++ src/events/SDL_mouse.c | 35 ++++++++++++++++++++++++++++++++++- src/events/SDL_mouse_c.h | 1 + 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 9f1685de76993..00ae81075fed7 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -2652,6 +2652,21 @@ extern "C" { */ #define SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE "SDL_MOUSE_RELATIVE_CURSOR_VISIBLE" +/** + * A variable controlling whether SDL should leave cursor redraws to be manually + * issued by usercode instead of automatically refreshing on state changes. + * + * This variable can be set to the following values: + * + * - "0": SDL will issue redraws automatically when focus changes (default) + * - "1": The usercode is responsible for updating the cursor on focus change. + * + * This hint can be set anytime. + * + * \since This hint is available since SDL 3.4.0. + */ +#define SDL_HINT_MOUSE_CURSOR_SUSPEND_REDRAW "SDL_MOUSE_CURSOR_SUSPEND_REDRAW" + /** * 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 e2e9e4abc64d9..44b77869b2937 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -234,6 +234,13 @@ static void SDLCALL SDL_MouseRelativeCursorVisibleChanged(void *userdata, const SDL_RedrawCursor(); // Update cursor visibility } +static void SDLCALL SDL_MouseCursorSuspendRedrawChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = (SDL_Mouse *)userdata; + + mouse->cursor_auto_redraw = !(SDL_GetStringBoolean(hint, false)); +} + static void SDLCALL SDL_MouseIntegerModeChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_Mouse *mouse = (SDL_Mouse *)userdata; @@ -299,6 +306,9 @@ bool SDL_PreInitMouse(void) SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, SDL_MouseRelativeCursorVisibleChanged, mouse); + SDL_AddHintCallback(SDL_HINT_MOUSE_CURSOR_SUSPEND_REDRAW, + SDL_MouseCursorSuspendRedrawChanged, mouse); + SDL_AddHintCallback("SDL_MOUSE_INTEGER_MODE", SDL_MouseIntegerModeChanged, mouse); @@ -1158,6 +1168,9 @@ void SDL_QuitMouse(void) SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, SDL_MouseRelativeCursorVisibleChanged, mouse); + SDL_RemoveHintCallback(SDL_HINT_MOUSE_CURSOR_SUSPEND_REDRAW, + SDL_MouseCursorSuspendRedrawChanged, mouse); + SDL_RemoveHintCallback("SDL_MOUSE_INTEGER_MODE", SDL_MouseIntegerModeChanged, mouse); @@ -1599,11 +1612,17 @@ SDL_Cursor *SDL_CreateSystemCursor(SDL_SystemCursor id) return cursor; } +// Cursor redraw command used by SDL internally +// which checks whether or not to auto-redraw. void SDL_RedrawCursor(void) { SDL_Mouse *mouse = SDL_GetMouse(); SDL_Cursor *cursor; + if (!mouse->cursor_auto_redraw) { + return; + } + if (mouse->focus) { cursor = mouse->cur_cursor; } else { @@ -1649,7 +1668,21 @@ bool SDL_SetCursor(SDL_Cursor *cursor) mouse->cur_cursor = cursor; } - SDL_RedrawCursor(); + // user-called SDL_SetCursor(NULL) are manually issued redraws, + // so code for SDL_RedrawCursor should be mirrored here. + if (mouse->focus) { + cursor = mouse->cur_cursor; + } else { + cursor = mouse->def_cursor; + } + + if (mouse->focus && (!mouse->cursor_visible || (mouse->relative_mode && mouse->relative_mode_hide_cursor))) { + cursor = NULL; + } + + if (mouse->ShowCursor) { + mouse->ShowCursor(cursor); + } return true; } diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 07a761b79789c..dfd58b3770af0 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -149,6 +149,7 @@ typedef struct SDL_Cursor *def_cursor; SDL_Cursor *cur_cursor; bool cursor_visible; + bool cursor_auto_redraw; // Driver-dependent data. void *internal;