From 9a6f8a2512bc3e3cbd363ed4cd901b72881272f9 Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Sat, 8 Mar 2025 20:23:21 -0600 Subject: [PATCH] mouse: Add internal integer mouse mode hint for sdl2-compat Performing this inside SDL3 dramatically simplifies sdl2-compat. See https://github.com/libsdl-org/sdl2-compat/issues/372. (cherry picked from commit 597bfe6b2708e218161bd22d2b30020167d5c32b) --- src/events/SDL_mouse.c | 29 +++++++++++++++++++++++++++++ src/events/SDL_mouse_c.h | 5 +++++ 2 files changed, 34 insertions(+) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 2ea5995dcc..bbcaa9290d 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_SetCursor(NULL); // Update cursor visibility } +static void SDLCALL SDL_MouseIntegerModeChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = (SDL_Mouse *)userdata; + + mouse->integer_mode = SDL_GetStringBoolean(hint, false); +} + // Public functions bool SDL_PreInitMouse(void) { @@ -288,6 +295,9 @@ bool SDL_PreInitMouse(void) SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, SDL_MouseRelativeCursorVisibleChanged, mouse); + SDL_AddHintCallback("SDL_MOUSE_INTEGER_MODE", + SDL_MouseIntegerModeChanged, mouse); + mouse->was_touch_mouse_events = false; // no touch to mouse movement event pending mouse->cursor_shown = true; @@ -720,12 +730,22 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL y *= mouse->normal_speed_scale; } } + if (mouse->integer_mode) { + // Accumulate the fractional relative motion and only process the integer portion + mouse->xrel_frac = SDL_modff(mouse->xrel_frac + x, &x); + mouse->yrel_frac = SDL_modff(mouse->yrel_frac + y, &y); + } xrel = x; yrel = y; x = (mouse->last_x + xrel); y = (mouse->last_y + yrel); ConstrainMousePosition(mouse, window, &x, &y); } else { + if (mouse->integer_mode) { + // Discard the fractional component from absolute coordinates + x = SDL_truncf(x); + y = SDL_truncf(y); + } ConstrainMousePosition(mouse, window, &x, &y); if (mouse->has_position) { xrel = x - mouse->last_x; @@ -998,6 +1018,12 @@ void SDL_SendMouseWheel(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseI SDL_SetMouseFocus(window); } + // Accumulate fractional wheel motion if integer mode is enabled + if (mouse->integer_mode) { + mouse->wheel_x_frac = SDL_modff(mouse->wheel_x_frac + x, &x); + mouse->wheel_y_frac = SDL_modff(mouse->wheel_y_frac + y, &y); + } + if (x == 0.0f && y == 0.0f) { return; } @@ -1108,6 +1134,9 @@ void SDL_QuitMouse(void) SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_CURSOR_VISIBLE, SDL_MouseRelativeCursorVisibleChanged, mouse); + SDL_RemoveHintCallback("SDL_MOUSE_INTEGER_MODE", + SDL_MouseIntegerModeChanged, mouse); + for (int i = SDL_mouse_count; i--; ) { SDL_RemoveMouse(SDL_mice[i].instance_id, false); } diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 43cc5207da..dc8c78b51a 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -98,8 +98,13 @@ typedef struct float x_accu; float y_accu; float last_x, last_y; // the last reported x and y coordinates + float xrel_frac; + float yrel_frac; + float wheel_x_frac; + float wheel_y_frac; double click_motion_x; double click_motion_y; + bool integer_mode; bool has_position; bool relative_mode; bool relative_mode_warp_motion;