From 4eda58ba6aacc5b2a86ab3e533c9c1938319d7b6 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Fri, 2 Dec 2016 21:01:13 -0800 Subject: [PATCH] Added SDL_HINT_MOUSE_NORMAL_SPEED_SCALE and SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE to scale the speed of the mouse. This currently doesn't affect absolute motion, which would need to be implemented on each windowing system so the cursor matches the reported mouse coordinates. --- include/SDL_hints.h | 10 ++++++++ src/events/SDL_mouse.c | 52 ++++++++++++++++++++++++++++++++++++++++ src/events/SDL_mouse_c.h | 4 ++++ 3 files changed, 66 insertions(+) diff --git a/include/SDL_hints.h b/include/SDL_hints.h index c2ec237224089..6120b04f4b859 100644 --- a/include/SDL_hints.h +++ b/include/SDL_hints.h @@ -232,6 +232,16 @@ extern "C" { */ #define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD" +/** + * \brief A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode + */ +#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE" + +/** + * \brief A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode + */ +#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE" + /** * \brief A variable controlling whether relative mouse mode is implemented using mouse warping * diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index fb4fae7472f42..f3cc6fc9f7556 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -40,12 +40,34 @@ static int SDL_double_click_radius = 1; static int SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y); +static void +SDL_MouseNormalSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = (SDL_Mouse *)userdata; + + mouse->normal_speed_scale = SDL_atof(hint); +} + +static void +SDL_MouseRelativeSpeedScaleChanged(void *userdata, const char *name, const char *oldValue, const char *hint) +{ + SDL_Mouse *mouse = (SDL_Mouse *)userdata; + + mouse->relative_speed_scale = SDL_atof(hint); +} + /* Public functions */ int SDL_MouseInit(void) { SDL_Mouse *mouse = SDL_GetMouse(); + SDL_AddHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE, + SDL_MouseNormalSpeedScaleChanged, mouse); + + SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, + SDL_MouseRelativeSpeedScaleChanged, mouse); + mouse->cursor_shown = SDL_TRUE; return (0); @@ -199,6 +221,21 @@ SDL_SendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int return SDL_PrivateSendMouseMotion(window, mouseID, relative, x, y); } +static int +GetScaledMouseDelta(float scale, int value, float *accum) +{ + if (scale != 1.0f) { + *accum += scale * value; + if (*accum >= 0.0f) { + value = (int)SDL_floor(*accum); + } else { + value = (int)SDL_ceil(*accum); + } + *accum -= value; + } + return value; +} + static int SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relative, int x, int y) { @@ -221,6 +258,13 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ } if (relative) { + if (mouse->relative_mode) { + x = GetScaledMouseDelta(mouse->relative_speed_scale, x, &mouse->scale_accum_x); + y = GetScaledMouseDelta(mouse->relative_speed_scale, y, &mouse->scale_accum_y); + } else { + x = GetScaledMouseDelta(mouse->normal_speed_scale, x, &mouse->scale_accum_x); + y = GetScaledMouseDelta(mouse->normal_speed_scale, y, &mouse->scale_accum_y); + } xrel = x; yrel = y; x = (mouse->last_x + xrel); @@ -475,6 +519,12 @@ SDL_MouseQuit(void) } SDL_zerop(mouse); + + SDL_DelHintCallback(SDL_HINT_MOUSE_NORMAL_SPEED_SCALE, + SDL_MouseNormalSpeedScaleChanged, mouse); + + SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE, + SDL_MouseRelativeSpeedScaleChanged, mouse); } Uint32 @@ -603,6 +653,8 @@ SDL_SetRelativeMouseMode(SDL_bool enabled) } } mouse->relative_mode = enabled; + mouse->scale_accum_x = 0.0f; + mouse->scale_accum_y = 0.0f; if (mouse->focus) { SDL_UpdateWindowGrab(mouse->focus); diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 2bc07822a2417..cddb7e11d22c6 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -83,6 +83,10 @@ typedef struct Uint32 buttonstate; SDL_bool relative_mode; SDL_bool relative_mode_warp; + float normal_speed_scale; + float relative_speed_scale; + float scale_accum_x; + float scale_accum_y; /* Data for double-click tracking */ int num_clickstates;