From 597bfe6b2708e218161bd22d2b30020167d5c32b Mon Sep 17 00:00:00 2001
From: Cameron Gutman <[EMAIL REDACTED]>
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.
---
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 e2ce07ffd6e59..c891fdd956fdb 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;
@@ -725,12 +735,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;
@@ -1003,6 +1023,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;
}
@@ -1113,6 +1139,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 ee3e814739c1d..b2518b8879eb4 100644
--- a/src/events/SDL_mouse_c.h
+++ b/src/events/SDL_mouse_c.h
@@ -102,8 +102,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;