@@ -662,6 +662,31 @@ void SDL_SendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouse
662662 SDL_PrivateSendMouseMotion (timestamp , window , mouseID , relative , x , y );
663663}
664664
665+ void SDL_SendMouseWarp (Uint64 timestamp , SDL_Window * window , SDL_MouseID mouseID , float x , float y )
666+ {
667+ SDL_Mouse * mouse = SDL_GetMouse ();
668+
669+ // Ignore the previous position when we warp, as warps don't generate relative motion.
670+ mouse -> last_x = x ;
671+ mouse -> last_y = y ;
672+ mouse -> has_position = false;
673+
674+ if (mouse -> relative_mode ) {
675+ /* Sending motion events when warping while relative mode is active can confuse
676+ * clients that don't expect it, so just update the absolute position and don't
677+ * generate a motion event unless SDL_HINT_MOUSE_RELATIVE_WARP_MOTION is set.
678+ */
679+ if (!mouse -> relative_mode_warp_motion ) {
680+ mouse -> x = x ;
681+ mouse -> y = y ;
682+ mouse -> has_position = true;
683+ return ;
684+ }
685+ }
686+
687+ SDL_SendMouseMotion (timestamp , window , mouseID , false, x , y );
688+ }
689+
665690static void ConstrainMousePosition (SDL_Mouse * mouse , SDL_Window * window , float * x , float * y )
666691{
667692 /* make sure that the pointers find themselves inside the windows,
@@ -1263,24 +1288,29 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, bool ign
12631288 return ;
12641289 }
12651290
1266- // Ignore the previous position when we warp
1267- mouse -> last_x = x ;
1268- mouse -> last_y = y ;
1269- mouse -> has_position = false;
1270-
1271- if (mouse -> relative_mode && !ignore_relative_mode ) {
1272- /* 2.0.22 made warping in relative mode actually functional, which
1273- * surprised many applications that weren't expecting the additional
1274- * mouse motion.
1275- *
1276- * So for now, warping in relative mode adjusts the absolution position
1277- * but doesn't generate motion events, unless SDL_HINT_MOUSE_RELATIVE_WARP_MOTION is set.
1278- */
1279- if (!mouse -> relative_mode_warp_motion ) {
1280- mouse -> x = x ;
1281- mouse -> y = y ;
1282- mouse -> has_position = true;
1283- return ;
1291+ /* If the backend sends explicit warp events, this will be taken care of if/when the pointer actually warps,
1292+ * Warps when in relative save the position to be applied when leaving relative mode.
1293+ */
1294+ if (!mouse -> have_explicit_warp_event || mouse -> relative_mode ) {
1295+ // Ignore the previous position when we warp, as warps don't generate relative motion.
1296+ mouse -> last_x = x ;
1297+ mouse -> last_y = y ;
1298+ mouse -> has_position = false;
1299+
1300+ if (mouse -> relative_mode && !ignore_relative_mode ) {
1301+ /* 2.0.22 made warping in relative mode actually functional, which
1302+ * surprised many applications that weren't expecting the additional
1303+ * mouse motion.
1304+ *
1305+ * So for now, warping in relative mode adjusts the absolute position, but
1306+ * doesn't generate motion events, unless SDL_HINT_MOUSE_RELATIVE_WARP_MOTION is set.
1307+ */
1308+ if (!mouse -> relative_mode_warp_motion ) {
1309+ mouse -> x = x ;
1310+ mouse -> y = y ;
1311+ mouse -> has_position = true;
1312+ return ;
1313+ }
12841314 }
12851315 }
12861316
0 commit comments