Added the hint SDL_HINT_MOUSE_RELATIVE_WARP_MOTION

This hint controls whether mouse warping generates motion events in relative mode, and defaults off.

Fixes https://github.com/libsdl-org/SDL/issues/6034
Fixes https://github.com/libsdl-org/SDL/issues/5741
This commit is contained in:
Sam Lantinga 2022-08-11 13:58:39 -07:00
parent c2db429f93
commit 3861c557da
5 changed files with 50 additions and 16 deletions

View File

@ -21,6 +21,7 @@ General:
* Added SDL_bsearch(), SDL_crc16(), and SDL_utf8strnlen() to the stdlib routines * Added SDL_bsearch(), SDL_crc16(), and SDL_utf8strnlen() to the stdlib routines
* Added SDL_size_mul_overflow() and SDL_size_add_overflow() for better size overflow protection * Added SDL_size_mul_overflow() and SDL_size_add_overflow() for better size overflow protection
* Added SDL_ResetHint() to reset a hint to the default value * Added SDL_ResetHint() to reset a hint to the default value
* Added the hint SDL_HINT_MOUSE_RELATIVE_WARP_MOTION to control whether mouse warping generates motion events in relative mode. This hint defaults off.
* The hint SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS now defaults on * The hint SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS now defaults on
* Added support for mini-gamepad mode for Nintendo Joy-Con controllers using the HIDAPI driver * Added support for mini-gamepad mode for Nintendo Joy-Con controllers using the HIDAPI driver
* Added the hint SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS to control whether Joy-Con controllers are automatically merged into a unified gamepad when using the HIDAPI driver. This hint defaults on. * Added the hint SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS to control whether Joy-Con controllers are automatically merged into a unified gamepad when using the HIDAPI driver. This hint defaults on.

View File

@ -1064,6 +1064,17 @@ extern "C" {
*/ */
#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE" #define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE"
/**
* \brief A variable controlling whether a motion event should be generated for mouse warping in relative mode.
*
* This variable can be set to the following values:
* "0" - Warping the mouse will not generate a motion event in relative mode
* "1" - Warping the mouse will generate a motion event in relative mode
*
* By default warping the mouse will not generate motion events in relative mode. This avoids the application having to filter out large relative motion due to warping.
*/
#define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION "SDL_MOUSE_RELATIVE_WARP_MOTION"
/** /**
* \brief A variable controlling whether mouse events should generate synthetic touch events * \brief A variable controlling whether mouse events should generate synthetic touch events
* *

View File

@ -154,7 +154,7 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetRelativeMouseState(int *x, int *y);
/** /**
* Move the mouse cursor to the given position within the window. * Move the mouse cursor to the given position within the window.
* *
* This function generates a mouse motion event. * This function generates a mouse motion event if relative mode is not enabled. If relative mode is enabled, you can force mouse events for the warp by setting the SDL_HINT_MOUSE_RELATIVE_WARP_MOTION hint.
* *
* Note that this function will appear to succeed, but not actually move the * Note that this function will appear to succeed, but not actually move the
* mouse when used over Microsoft Remote Desktop. * mouse when used over Microsoft Remote Desktop.

View File

@ -161,6 +161,14 @@ SDL_MouseAutoCaptureChanged(void *userdata, const char *name, const char *oldVal
} }
} }
static void SDLCALL
SDL_MouseRelativeWarpMotionChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
SDL_Mouse *mouse = (SDL_Mouse *)userdata;
mouse->relative_mode_warp_motion = SDL_GetStringBoolean(hint, SDL_FALSE);
}
/* Public functions */ /* Public functions */
int int
SDL_MouseInit(void) SDL_MouseInit(void)
@ -195,6 +203,9 @@ SDL_MouseInit(void)
SDL_AddHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE, SDL_AddHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
SDL_MouseAutoCaptureChanged, mouse); SDL_MouseAutoCaptureChanged, mouse);
SDL_AddHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION,
SDL_MouseRelativeWarpMotionChanged, mouse);
mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */ mouse->was_touch_mouse_events = SDL_FALSE; /* no touch to mouse movement event pending */
mouse->cursor_shown = SDL_TRUE; mouse->cursor_shown = SDL_TRUE;
@ -377,8 +388,10 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
if (x == center_x && y == center_y) { if (x == center_x && y == center_y) {
mouse->last_x = center_x; mouse->last_x = center_x;
mouse->last_y = center_y; mouse->last_y = center_y;
if (!mouse->relative_mode_warp_motion) {
return 0; return 0;
} }
} else {
if (window && (window->flags & SDL_WINDOW_INPUT_FOCUS) != 0) { if (window && (window->flags & SDL_WINDOW_INPUT_FOCUS) != 0) {
if (mouse->WarpMouse) { if (mouse->WarpMouse) {
mouse->WarpMouse(window, center_x, center_y); mouse->WarpMouse(window, center_x, center_y);
@ -387,6 +400,7 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
} }
} }
} }
}
if (relative) { if (relative) {
if (mouse->relative_mode) { if (mouse->relative_mode) {
@ -810,6 +824,9 @@ SDL_MouseQuit(void)
SDL_DelHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE, SDL_DelHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
SDL_MouseAutoCaptureChanged, mouse); SDL_MouseAutoCaptureChanged, mouse);
SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION,
SDL_MouseRelativeWarpMotionChanged, mouse);
} }
Uint32 Uint32
@ -883,22 +900,26 @@ SDL_PerformWarpMouseInWindow(SDL_Window *window, int x, int y, SDL_bool ignore_r
return; return;
} }
/* Ignore the previous position when we warp */
mouse->last_x = x;
mouse->last_y = y;
mouse->has_position = SDL_FALSE;
if (mouse->relative_mode && !ignore_relative_mode) { if (mouse->relative_mode && !ignore_relative_mode) {
/* 2.0.22 made warping in relative mode actually functional, which /* 2.0.22 made warping in relative mode actually functional, which
* surprised many applications that weren't expecting the additional * surprised many applications that weren't expecting the additional
* mouse motion. * mouse motion.
* *
* So for now, warping in relative mode adjusts the absolution position * So for now, warping in relative mode adjusts the absolution position
* but doesn't generate motion events. * but doesn't generate motion events, unless SDL_HINT_MOUSE_RELATIVE_WARP_MOTION is set.
*/ */
if (!mouse->relative_mode_warp_motion) {
mouse->x = x; mouse->x = x;
mouse->y = y; mouse->y = y;
mouse->has_position = SDL_TRUE; mouse->has_position = SDL_TRUE;
return; return;
} }
}
/* Ignore the previous position when we warp */
mouse->has_position = SDL_FALSE;
if (mouse->WarpMouse && if (mouse->WarpMouse &&
(!mouse->relative_mode || mouse->relative_mode_warp)) { (!mouse->relative_mode || mouse->relative_mode_warp)) {

View File

@ -91,6 +91,7 @@ typedef struct
SDL_bool has_position; SDL_bool has_position;
SDL_bool relative_mode; SDL_bool relative_mode;
SDL_bool relative_mode_warp; SDL_bool relative_mode_warp;
SDL_bool relative_mode_warp_motion;
float normal_speed_scale; float normal_speed_scale;
float relative_speed_scale; float relative_speed_scale;
float scale_accum_x; float scale_accum_x;