SDL: Don't send mouse events when warping in relative mode (b7187)

From b718753ebf9e9113d8bee97ccd659cd7d61f8233 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 18 May 2022 08:50:59 -0700
Subject: [PATCH] Don't send mouse events when warping in relative mode

This fixes games which set relative mode and then did mouse warping at the same time

Reference https://github.com/libsdl-org/SDL/issues/5609
---
 src/events/SDL_mouse.c | 31 ++++++++++++++++++++++++++-----
 1 file changed, 26 insertions(+), 5 deletions(-)

diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 254182cc5ac..e6ad53065cf 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -866,8 +866,8 @@ SDL_GetGlobalMouseState(int *x, int *y)
     }
 }
 
-void
-SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
+static void
+SDL_PerformWarpMouseInWindow(SDL_Window *window, int x, int y, SDL_bool ignore_relative_mode)
 {
     SDL_Mouse *mouse = SDL_GetMouse();
 
@@ -883,6 +883,20 @@ SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
         return;
     }
 
+    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.
+         */
+        mouse->x = x;
+        mouse->y = y;
+        mouse->has_position = SDL_TRUE;
+        return;
+    }
+
     /* Ignore the previous position when we warp */
     mouse->has_position = SDL_FALSE;
 
@@ -894,6 +908,12 @@ SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
     }
 }
 
+void
+SDL_WarpMouseInWindow(SDL_Window * window, int x, int y)
+{
+    SDL_PerformWarpMouseInWindow(window, x, y, SDL_FALSE);
+}
+
 int
 SDL_WarpMouseGlobal(int x, int y)
 {
@@ -953,8 +973,9 @@ SDL_SetRelativeMouseMode(SDL_bool enabled)
     if (enabled && focusWindow) {
         SDL_SetMouseFocus(focusWindow);
 
-        if (mouse->relative_mode_warp)
-            SDL_WarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2);
+        if (mouse->relative_mode_warp) {
+            SDL_PerformWarpMouseInWindow(focusWindow, focusWindow->w/2, focusWindow->h/2, SDL_TRUE);
+        }
     }
 
     if (focusWindow) {
@@ -962,7 +983,7 @@ SDL_SetRelativeMouseMode(SDL_bool enabled)
 
         /* Put the cursor back to where the application expects it */
         if (!enabled) {
-            SDL_WarpMouseInWindow(focusWindow, mouse->x, mouse->y);
+            SDL_PerformWarpMouseInWindow(focusWindow, mouse->x, mouse->y, SDL_TRUE);
         }
 
         SDL_UpdateMouseCapture(SDL_FALSE);