diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h index 97b85962661e1..b6995a60dc884 100644 --- a/include/SDL3/SDL_hints.h +++ b/include/SDL3/SDL_hints.h @@ -2505,35 +2505,6 @@ extern "C" { */ #define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP" -/** - * A variable setting the scale for mouse motion, in floating point, when the - * mouse is in relative mode. - * - * This hint can be set anytime. - * - * \since This hint is available since SDL 3.1.3. - */ -#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE" - -/** - * A variable controlling whether the system mouse acceleration curve is used - * for relative mouse motion. - * - * The variable can be set to the following values: - * - * - "0": Relative mouse motion will be unscaled. (default) - * - "1": Relative mouse motion will be scaled using the system mouse - * acceleration curve. - * - * If SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE is set, that will override the - * system speed scale. - * - * This hint can be set anytime. - * - * \since This hint is available since SDL 3.1.3. - */ -#define SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE "SDL_MOUSE_RELATIVE_SYSTEM_SCALE" - /** * A variable controlling whether a motion event should be generated for mouse * warping in relative mode. diff --git a/include/SDL3/SDL_mouse.h b/include/SDL3/SDL_mouse.h index 9068b3fab3b34..3374e9e6133fe 100644 --- a/include/SDL3/SDL_mouse.h +++ b/include/SDL3/SDL_mouse.h @@ -190,6 +190,37 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetMouseNameForID(SDL_MouseID insta */ extern SDL_DECLSPEC SDL_Window * SDLCALL SDL_GetMouseFocus(void); +/** + * Retieve an implementation of the function by which the platform + * transforms raw mouse inputs into cursor motion. + * + * This returns a function pointer to the implmentation if one exists, + * or NULL if not. This pointer can be passed to SDL_SetInputTransform + * if one wishes to scale relative mouse motion using the implementation, + * in which case the userdata argument is ignored and platform-specific + * data will be used instead. + * + * \returns a pointer to an input transform function. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_SetInputTransform + */ +extern SDL_DECLSPEC const void * SDLCALL SDL_GetSystemInputTransform(void); + +/** + * Set a user-defined function by which to transform relative mouse inputs, + * and its associated internal data which will be passed to the function. + * + * \param transform a pointer to an input transform function, or NULL to disable. + * \param userdata an optional pointer to the associated internal data. + * + * \since This function is available since SDL 3.1.3. + * + * \sa SDL_GetSystemInputTransform + */ +extern SDL_DECLSPEC void SDLCALL SDL_SetInputTransform(const void *transform, void *userdata); + /** * Query SDL's cache for the synchronous mouse button state and the * window-relative SDL-cursor position. diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 657bad9a6c237..c696f8dec3632 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -100,26 +100,6 @@ static void SDLCALL SDL_MouseNormalSpeedScaleChanged(void *userdata, const char } } -static void SDLCALL SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_Mouse *mouse = (SDL_Mouse *)userdata; - - if (hint && *hint) { - mouse->enable_relative_speed_scale = true; - mouse->relative_speed_scale = (float)SDL_atof(hint); - } else { - mouse->enable_relative_speed_scale = false; - mouse->relative_speed_scale = 1.0f; - } -} - -static void SDLCALL SDL_MouseRelativeSystemScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint) -{ - SDL_Mouse *mouse = (SDL_Mouse *)userdata; - - mouse->enable_relative_system_scale = SDL_GetStringBoolean(hint, false); -} - static void SDLCALL SDL_MouseWarpEmulationChanged(void *userdata, const char *name, const char *oldValue, const char *hint) { SDL_Mouse *mouse = (SDL_Mouse *)userdata; @@ -220,12 +200,6 @@ bool SDL_PreInitMouse(void) SDL_AddHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE, SDL_MouseNormalSpeedScaleChanged, mouse); - SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, - SDL_MouseRelativeSpeedScaleChanged, mouse); - - SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE, - SDL_MouseRelativeSystemScaleChanged, mouse); - SDL_AddHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE, SDL_MouseWarpEmulationChanged, mouse); @@ -696,13 +670,12 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL if (relative) { if (mouse->relative_mode) { - if (mouse->enable_relative_speed_scale) { - x *= mouse->relative_speed_scale; - y *= mouse->relative_speed_scale; - } else if (mouse->enable_relative_system_scale) { - if (mouse->ApplySystemScale) { - mouse->ApplySystemScale(mouse->system_scale_data, timestamp, window, mouseID, &x, &y); + if (mouse->InputTransform) { + void *data = mouse->input_transform_data; + if (mouse->InputTransform == mouse->ApplySystemScale) { + data = mouse->system_scale_data; } + mouse->InputTransform(data, timestamp, window, mouseID, &x, &y); } } else { if (mouse->enable_normal_speed_scale) { @@ -1049,12 +1022,6 @@ void SDL_QuitMouse(void) SDL_RemoveHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE, SDL_MouseNormalSpeedScaleChanged, mouse); - SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, - SDL_MouseRelativeSpeedScaleChanged, mouse); - - SDL_RemoveHintCallback(SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE, - SDL_MouseRelativeSystemScaleChanged, mouse); - SDL_RemoveHintCallback(SDL_HINT_MOUSE_EMULATE_WARP_WITH_RELATIVE, SDL_MouseWarpEmulationChanged, mouse); @@ -1083,6 +1050,17 @@ void SDL_QuitMouse(void) SDL_mice = NULL; } +const void *SDL_GetSystemInputTransform(void) { + SDL_Mouse *mouse = SDL_GetMouse(); + return mouse->ApplySystemScale; +} + +void SDL_SetInputTransform(const void *transform, void *userdata) { + SDL_Mouse *mouse = SDL_GetMouse(); + mouse->InputTransform = (SDL_InputTransform)transform; + mouse->input_transform_data = userdata; +} + SDL_MouseButtonFlags SDL_GetMouseState(float *x, float *y) { SDL_Mouse *mouse = SDL_GetMouse(); diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index d77d0a7e10bf4..44d38fe12b18f 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -50,6 +50,8 @@ typedef struct Uint8 click_count; } SDL_MouseClickState; +typedef void (*SDL_InputTransform)(void *userdata, Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float *x, float *y); + typedef struct { // Create a cursor from a surface @@ -83,9 +85,13 @@ typedef struct SDL_MouseButtonFlags (*GetGlobalMouseState)(float *x, float *y); // Platform-specific system mouse transform - void (*ApplySystemScale)(void *internal, Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, float *x, float *y); + SDL_InputTransform ApplySystemScale; void *system_scale_data; + // User-defined mouse input transform + SDL_InputTransform InputTransform; + void *input_transform_data; + // Data common to all mice SDL_Window *focus; float x; @@ -105,9 +111,6 @@ typedef struct int relative_mode_clip_interval; bool enable_normal_speed_scale; float normal_speed_scale; - bool enable_relative_speed_scale; - float relative_speed_scale; - bool enable_relative_system_scale; Uint32 double_click_time; int double_click_radius; bool touch_mouse_events; diff --git a/src/video/windows/SDL_windowsmouse.c b/src/video/windows/SDL_windowsmouse.c index d53a1f20c544c..5b38d7e096ba7 100644 --- a/src/video/windows/SDL_windowsmouse.c +++ b/src/video/windows/SDL_windowsmouse.c @@ -694,9 +694,9 @@ void WIN_UpdateMouseSystemScale(void) { SDL_Mouse *mouse = SDL_GetMouse(); - if (mouse->ApplySystemScale == WIN_ApplySystemScale) { - mouse->system_scale_data = &WIN_system_scale_data; - } + // always set to platform impl to be safe, even though it's not exposed to user. + mouse->ApplySystemScale = WIN_ApplySystemScale; + mouse->system_scale_data = &WIN_system_scale_data; // always reinitialize to valid defaults, whether fetch was successful or not. WIN_MouseData *data = &WIN_system_scale_data;