SDL: Removed SDL_HINT_MOUSE_RELATIVE_MODE_WARP

From e08f34c3bed1a03b70c65773d172b2728bd3f379 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Wed, 18 Dec 2024 17:49:51 -0800
Subject: [PATCH] Removed SDL_HINT_MOUSE_RELATIVE_MODE_WARP

This complicated mouse handling and is a rarely tested path. Real relative mode is much better performance and higher precision.
---
 docs/README-migration.md              |  3 +-
 include/SDL3/SDL_hints.h              | 15 ------
 src/events/SDL_mouse.c                | 70 +++------------------------
 src/events/SDL_mouse_c.h              |  1 -
 src/video/SDL_video.c                 |  3 --
 src/video/cocoa/SDL_cocoawindow.m     |  2 +-
 src/video/windows/SDL_windowswindow.c |  2 +-
 src/video/x11/SDL_x11events.c         |  4 +-
 src/video/x11/SDL_x11xinput2.c        |  4 +-
 test/testautomation_hints.c           |  2 -
 10 files changed, 16 insertions(+), 90 deletions(-)

diff --git a/docs/README-migration.md b/docs/README-migration.md
index f961d4c098704..59f3914a32034 100644
--- a/docs/README-migration.md
+++ b/docs/README-migration.md
@@ -820,12 +820,14 @@ The following hints have been renamed:
 The following hints have been removed:
 * SDL_HINT_ACCELEROMETER_AS_JOYSTICK
 * SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO - the audio will be paused when the application is paused, and SDL_HINT_ANDROID_BLOCK_ON_PAUSE can be used to control that
+* SDL_HINT_AUDIO_DEVICE_APP_NAME - replaced by either using the appname param to SDL_SetAppMetadata() or setting SDL_PROP_APP_METADATA_NAME_STRING with SDL_SetAppMetadataProperty()
 * SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS - gamepad buttons are always positional
 * SDL_HINT_GRAB_KEYBOARD - use SDL_SetWindowKeyboardGrab() instead
 * SDL_HINT_IDLE_TIMER_DISABLED - use SDL_DisableScreenSaver() instead
 * SDL_HINT_IME_INTERNAL_EDITING - replaced with SDL_HINT_IME_IMPLEMENTED_UI
 * SDL_HINT_IME_SHOW_UI - replaced with SDL_HINT_IME_IMPLEMENTED_UI
 * SDL_HINT_IME_SUPPORT_EXTENDED_TEXT - the normal text editing event has extended text
+* SDL_HINT_MOUSE_RELATIVE_MODE_WARP - relative mode is always implemented at the hardware level or reported as unavailable
 * SDL_HINT_MOUSE_RELATIVE_SCALING - mouse coordinates are no longer automatically scaled by the SDL renderer
 * SDL_HINT_PS2_DYNAMIC_VSYNC - use SDL_SetRenderVSync(renderer, -1) instead
 * SDL_HINT_RENDER_BATCHING - Render batching is always enabled, apps should call SDL_FlushRenderer() before calling into a lower-level graphics API.
@@ -848,7 +850,6 @@ The following hints have been removed:
 * SDL_HINT_WINRT_PRIVACY_POLICY_LABEL - WinRT support was removed in SDL3.
 * SDL_HINT_WINRT_PRIVACY_POLICY_URL - WinRT support was removed in SDL3.
 * SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING
-* SDL_HINT_AUDIO_DEVICE_APP_NAME - replaced by either using the appname param to SDL_SetAppMetadata() or setting SDL_PROP_APP_METADATA_NAME_STRING with SDL_SetAppMetadataProperty()
 
 The following environment variables have been renamed:
 * SDL_AUDIODRIVER => SDL_AUDIO_DRIVER
diff --git a/include/SDL3/SDL_hints.h b/include/SDL3/SDL_hints.h
index 1be6d0a1e69f4..1fee3d95488c9 100644
--- a/include/SDL3/SDL_hints.h
+++ b/include/SDL3/SDL_hints.h
@@ -2532,21 +2532,6 @@ extern "C" {
  */
 #define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER"
 
-/**
- * A variable controlling whether relative mouse mode is implemented using
- * mouse warping.
- *
- * The variable can be set to the following values:
- *
- * - "0": Relative mouse mode uses raw input. (default)
- * - "1": Relative mouse mode uses mouse warping.
- *
- * This hint can be set anytime relative mode is not currently enabled.
- *
- * \since This hint is available since SDL 3.1.3.
- */
-#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP"
-
 /**
  * A variable setting the scale for mouse motion, in floating point, when the
  * mouse is in relative mode.
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index 543bacce70217..638f6d4e543dd 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -694,30 +694,6 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL
         return;
     }
 
-    if (mouseID != SDL_TOUCH_MOUSEID && mouse->relative_mode_warp) {
-        int w = 0, h = 0;
-        float center_x, center_y;
-        SDL_GetWindowSize(window, &w, &h);
-        center_x = (float)w / 2.0f;
-        center_y = (float)h / 2.0f;
-        if (x >= SDL_floorf(center_x) && x <= SDL_ceilf(center_x) &&
-            y >= SDL_floorf(center_y) && y <= SDL_ceilf(center_y)) {
-            mouse->last_x = center_x;
-            mouse->last_y = center_y;
-            if (!mouse->relative_mode_warp_motion) {
-                return;
-            }
-        } else {
-            if (window && (window->flags & SDL_WINDOW_INPUT_FOCUS)) {
-                if (mouse->WarpMouse) {
-                    mouse->WarpMouse(window, center_x, center_y);
-                } else {
-                    SDL_PrivateSendMouseMotion(timestamp, window, mouseID, false, center_x, center_y);
-                }
-            }
-        }
-    }
-
     if (relative) {
         if (mouse->relative_mode) {
             if (mouse->enable_relative_speed_scale) {
@@ -760,19 +736,14 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL
         yrel = 0.0f;
     }
 
-    // TODO: should rework overall so that relative bool arg conveys intent,
-    // and do this logic at the SDL_SendMouseMotion level instead of here.
-    bool cmd_is_meant_as_delta = relative || (mouse->relative_mode && mouse->relative_mode_warp);
-    bool cmd_is_hardware_delta = relative;
-
     // modify internal state
     {
-        if (cmd_is_meant_as_delta) {
+        if (relative) {
             mouse->x_accu += xrel;
             mouse->y_accu += yrel;
         }
 
-        if (cmd_is_meant_as_delta && mouse->has_position) {
+        if (relative && mouse->has_position) {
             mouse->x += xrel;
             mouse->y += yrel;
             ConstrainMousePosition(mouse, window, &mouse->x, &mouse->y);
@@ -783,8 +754,8 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL
         mouse->has_position = true;
 
         // Use unclamped values if we're getting events outside the window
-        mouse->last_x = cmd_is_hardware_delta ? mouse->x : x;
-        mouse->last_y = cmd_is_hardware_delta ? mouse->y : y;
+        mouse->last_x = relative ? mouse->x : x;
+        mouse->last_y = relative ? mouse->y : y;
     }
 
     // Move the mouse cursor, if needed
@@ -795,7 +766,7 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL
 
     // Post the event, if desired
     if (SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION)) {
-        if (!cmd_is_meant_as_delta && window_is_relative) {
+        if (!relative && window_is_relative) {
             if (!mouse->relative_mode_warp_motion) {
                 return;
             }
@@ -1195,8 +1166,7 @@ void SDL_PerformWarpMouseInWindow(SDL_Window *window, float x, float y, bool ign
         }
     }
 
-    if (mouse->WarpMouse &&
-        (!mouse->relative_mode || mouse->relative_mode_warp)) {
+    if (mouse->WarpMouse && !mouse->relative_mode) {
         mouse->WarpMouse(window, x, y);
     } else {
         SDL_PrivateSendMouseMotion(0, window, SDL_GLOBAL_MOUSE_ID, false, x, y);
@@ -1265,16 +1235,6 @@ bool SDL_WarpMouseGlobal(float x, float y)
     return SDL_Unsupported();
 }
 
-static bool SDL_ShouldUseRelativeModeWarp(SDL_Mouse *mouse)
-{
-    if (!mouse->WarpMouse) {
-        // Need this functionality for relative mode warp implementation
-        return false;
-    }
-
-    return SDL_GetHintBoolean(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, false);
-}
-
 bool SDL_SetRelativeMouseMode(bool enabled)
 {
     SDL_Mouse *mouse = SDL_GetMouse();
@@ -1290,17 +1250,9 @@ bool SDL_SetRelativeMouseMode(bool enabled)
     }
 
     // Set the relative mode
-    if (!enabled && mouse->relative_mode_warp) {
-        mouse->relative_mode_warp = false;
-    } else if (enabled && SDL_ShouldUseRelativeModeWarp(mouse)) {
-        mouse->relative_mode_warp = true;
-    } else if (!mouse->SetRelativeMouseMode || !mouse->SetRelativeMouseMode(enabled)) {
+    if (!mouse->SetRelativeMouseMode || !mouse->SetRelativeMouseMode(enabled)) {
         if (enabled) {
-            // Fall back to warp mode if native relative mode failed
-            if (!mouse->WarpMouse) {
-                return SDL_SetError("No relative mode implementation available");
-            }
-            mouse->relative_mode_warp = true;
+            return SDL_SetError("No relative mode implementation available");
         }
     }
     mouse->relative_mode = enabled;
@@ -1312,12 +1264,6 @@ bool SDL_SetRelativeMouseMode(bool enabled)
 
     if (enabled && focusWindow) {
         SDL_SetMouseFocus(focusWindow);
-
-        if (mouse->relative_mode_warp) {
-            float center_x = (float)focusWindow->w / 2.0f;
-            float center_y = (float)focusWindow->h / 2.0f;
-            SDL_PerformWarpMouseInWindow(focusWindow, center_x, center_y, true);
-        }
     }
 
     if (focusWindow) {
diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h
index a87efbe651d0e..558cb4944e4a9 100644
--- a/src/events/SDL_mouse_c.h
+++ b/src/events/SDL_mouse_c.h
@@ -95,7 +95,6 @@ typedef struct
     float last_x, last_y; // the last reported x and y coordinates
     bool has_position;
     bool relative_mode;
-    bool relative_mode_warp;
     bool relative_mode_warp_motion;
     bool relative_mode_cursor_visible;
     bool relative_mode_center;
diff --git a/src/video/SDL_video.c b/src/video/SDL_video.c
index 6db4777eccdeb..3b0f576f44748 100644
--- a/src/video/SDL_video.c
+++ b/src/video/SDL_video.c
@@ -4012,9 +4012,6 @@ void SDL_OnWindowFocusGained(SDL_Window *window)
 
     if (mouse && mouse->relative_mode) {
         SDL_SetMouseFocus(window);
-        if (mouse->relative_mode_warp) {
-            SDL_PerformWarpMouseInWindow(window, (float)window->w / 2.0f, (float)window->h / 2.0f, true);
-        }
     }
 
     SDL_UpdateWindowGrab(window);
diff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m
index 0401a04532859..55dfe2cb1be07 100644
--- a/src/video/cocoa/SDL_cocoawindow.m
+++ b/src/video/cocoa/SDL_cocoawindow.m
@@ -954,7 +954,7 @@ - (void)onMovingOrFocusClickPendingStateCleared
             mouse->WarpMouseGlobal(pendingWindowWarpX, pendingWindowWarpY);
             pendingWindowWarpX = pendingWindowWarpY = FLT_MAX;
         }
-        if (mouse->relative_mode && !mouse->relative_mode_warp && mouse->focus == _data.window) {
+        if (mouse->relative_mode && mouse->focus == _data.window) {
             // Move the cursor to the nearest point in the window
             {
                 float x, y;
diff --git a/src/video/windows/SDL_windowswindow.c b/src/video/windows/SDL_windowswindow.c
index b7a05f6c45b83..bf65fa8741894 100644
--- a/src/video/windows/SDL_windowswindow.c
+++ b/src/video/windows/SDL_windowswindow.c
@@ -1655,7 +1655,7 @@ void WIN_UpdateClipCursor(SDL_Window *window)
     // }
 
     SDL_Mouse *mouse = SDL_GetMouse();
-    bool lock_to_ctr = (mouse->relative_mode_center && mouse->relative_mode && !mouse->relative_mode_warp);
+    bool lock_to_ctr = (mouse->relative_mode && mouse->relative_mode_center);
 
     RECT client;
     if (!GetClientScreenRect(data->hwnd, &client)) {
diff --git a/src/video/x11/SDL_x11events.c b/src/video/x11/SDL_x11events.c
index 94285e429165c..4d7fbf3e2e0c1 100644
--- a/src/video/x11/SDL_x11events.c
+++ b/src/video/x11/SDL_x11events.c
@@ -905,7 +905,7 @@ void X11_HandleButtonPress(SDL_VideoDevice *_this, SDL_WindowData *windowdata, S
 #endif
 
     SDL_Mouse *mouse = SDL_GetMouse();
-    if ((!mouse->relative_mode || mouse->relative_mode_warp) && (x != mouse->x || y != mouse->y)) {
+    if (!mouse->relative_mode && (x != mouse->x || y != mouse->y)) {
         X11_ProcessHitTest(_this, windowdata, x, y, false);
         SDL_SendMouseMotion(0, window, mouseID, false, x, y);
     }
@@ -1556,7 +1556,7 @@ static void X11_DispatchEvent(SDL_VideoDevice *_this, XEvent *xevent)
         }
 
         SDL_Mouse *mouse = SDL_GetMouse();
-        if (!mouse->relative_mode || mouse->relative_mode_warp) {
+        if (!mouse->relative_mode) {
 #ifdef DEBUG_MOTION
             SDL_Log("window 0x%lx: X11 motion: %d,%d\n", xevent->xany.window, xevent->xmotion.x, xevent->xmotion.y);
 #endif
diff --git a/src/video/x11/SDL_x11xinput2.c b/src/video/x11/SDL_x11xinput2.c
index 5cccb220def6e..abc5efae48333 100644
--- a/src/video/x11/SDL_x11xinput2.c
+++ b/src/video/x11/SDL_x11xinput2.c
@@ -325,7 +325,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
             break; // Pens check for XI_Motion instead
         }
 
-        if (!mouse->relative_mode || mouse->relative_mode_warp) {
+        if (!mouse->relative_mode) {
             break;
         }
 
@@ -469,7 +469,7 @@ void X11_HandleXinput2Event(SDL_VideoDevice *_this, XGenericEventCookie *cookie)
         } else if (!pointer_emulated && xev->deviceid == videodata->xinput_master_pointer_device) {
             // Use the master device for non-relative motion, as the slave devices can seemingly lag behind.
             SDL_Mouse *mouse = SDL_GetMouse();
-            if (!mouse->relative_mode || mouse->relative_mode_warp) {
+            if (!mouse->relative_mode) {
                 SDL_Window *window = xinput2_get_sdlwindow(videodata, xev->event);
                 if (window) {
                     X11_ProcessHitTest(_this, window->internal, (float)xev->event_x, (float)xev->event_y, false);
diff --git a/test/testautomation_hints.c b/test/testautomation_hints.c
index e5b682fd4f13c..e2c158b48d850 100644
--- a/test/testautomation_hints.c
+++ b/test/testautomation_hints.c
@@ -11,7 +11,6 @@ static const char *HintsEnum[] = {
     SDL_HINT_GAMECONTROLLERCONFIG,
     SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS,
     SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK,
-    SDL_HINT_MOUSE_RELATIVE_MODE_WARP,
     SDL_HINT_ORIENTATIONS,
     SDL_HINT_RENDER_DIRECT3D_THREADSAFE,
     SDL_HINT_RENDER_VSYNC,
@@ -28,7 +27,6 @@ static const char *HintsVerbose[] = {
     "SDL_GAMECONTROLLERCONFIG",
     "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS",
     "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK",
-    "SDL_MOUSE_RELATIVE_MODE_WARP",
     "SDL_ORIENTATIONS",
     "SDL_RENDER_DIRECT3D_THREADSAFE",
     "SDL_RENDER_VSYNC",