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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
diff --git a/WhatsNew.txt b/WhatsNew.txt
index 2b780d0..198ae78 100644
--- a/WhatsNew.txt
+++ b/WhatsNew.txt
@@ -21,6 +21,7 @@ General:
* 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_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
* 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.
diff --git a/include/SDL_hints.h b/include/SDL_hints.h
index 32f65c3..e7cddba 100644
--- a/include/SDL_hints.h
+++ b/include/SDL_hints.h
@@ -1065,6 +1065,17 @@ extern "C" {
#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
*
* This variable can be set to the following values:
diff --git a/include/SDL_mouse.h b/include/SDL_mouse.h
index 4683e25..a9a00bd 100644
--- a/include/SDL_mouse.h
+++ b/include/SDL_mouse.h
@@ -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.
*
- * 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
* mouse when used over Microsoft Remote Desktop.
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 45dffc7..ba486ee 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -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 */
int
SDL_MouseInit(void)
@@ -195,6 +203,9 @@ SDL_MouseInit(void)
SDL_AddHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
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->cursor_shown = SDL_TRUE;
@@ -377,13 +388,16 @@ SDL_PrivateSendMouseMotion(SDL_Window * window, SDL_MouseID mouseID, int relativ
if (x == center_x && y == center_y) {
mouse->last_x = center_x;
mouse->last_y = center_y;
- return 0;
- }
- if (window && (window->flags & SDL_WINDOW_INPUT_FOCUS) != 0) {
- if (mouse->WarpMouse) {
- mouse->WarpMouse(window, center_x, center_y);
- } else {
- SDL_PrivateSendMouseMotion(window, mouseID, 0, center_x, center_y);
+ if (!mouse->relative_mode_warp_motion) {
+ return 0;
+ }
+ } else {
+ if (window && (window->flags & SDL_WINDOW_INPUT_FOCUS) != 0) {
+ if (mouse->WarpMouse) {
+ mouse->WarpMouse(window, center_x, center_y);
+ } else {
+ SDL_PrivateSendMouseMotion(window, mouseID, 0, center_x, center_y);
+ }
}
}
}
@@ -810,6 +824,9 @@ SDL_MouseQuit(void)
SDL_DelHintCallback(SDL_HINT_MOUSE_AUTO_CAPTURE,
SDL_MouseAutoCaptureChanged, mouse);
+
+ SDL_DelHintCallback(SDL_HINT_MOUSE_RELATIVE_WARP_MOTION,
+ SDL_MouseRelativeWarpMotionChanged, mouse);
}
Uint32
@@ -883,23 +900,27 @@ SDL_PerformWarpMouseInWindow(SDL_Window *window, int x, int y, SDL_bool ignore_r
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) {
/* 2.0.22 made warping in relative mode actually functional, which
* surprised many applications that weren't expecting the additional
* mouse motion.
*
* 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.
*/
- mouse->x = x;
- mouse->y = y;
- mouse->has_position = SDL_TRUE;
- return;
+ if (!mouse->relative_mode_warp_motion) {
+ mouse->x = x;
+ mouse->y = y;
+ mouse->has_position = SDL_TRUE;
+ return;
+ }
}
- /* Ignore the previous position when we warp */
- mouse->has_position = SDL_FALSE;
-
if (mouse->WarpMouse &&
(!mouse->relative_mode || mouse->relative_mode_warp)) {
mouse->WarpMouse(window, x, y);
diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h
index 70c3208..6b937b5 100644
--- a/src/events/SDL_mouse_c.h
+++ b/src/events/SDL_mouse_c.h
@@ -91,6 +91,7 @@ typedef struct
SDL_bool has_position;
SDL_bool relative_mode;
SDL_bool relative_mode_warp;
+ SDL_bool relative_mode_warp_motion;
float normal_speed_scale;
float relative_speed_scale;
float scale_accum_x;