From b55bb027239cd14558e806df60c9f77152fc281a Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Fri, 10 Feb 2023 09:08:12 -0800
Subject: [PATCH] Constrain the mouse position before it's used to generate
mouse deltas
Also clamp the mouse position to the maximum of *max and the last mouse position
Fixes https://github.com/libsdl-org/SDL/issues/7221#issuecomment-1426054481
---
src/events/SDL_mouse.c | 90 +++++++++++++++++++++++-------------------
1 file changed, 49 insertions(+), 41 deletions(-)
diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c
index a438640dee5b..1151feb439f7 100644
--- a/src/events/SDL_mouse.c
+++ b/src/events/SDL_mouse.c
@@ -443,6 +443,47 @@ static void GetScaledMouseDeltas(SDL_Mouse *mouse, float *x, float *y)
}
}
+static void ConstrainMousePosition(SDL_Mouse *mouse, SDL_Window *window, float *x, float *y)
+{
+ /* make sure that the pointers find themselves inside the windows,
+ unless we have the mouse captured. */
+ if (window && !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
+ int x_min = 0, x_max = window->w - 1;
+ int y_min = 0, y_max = window->h - 1;
+ const SDL_Rect *confine = SDL_GetWindowMouseRect(window);
+
+ if (confine) {
+ SDL_Rect window_rect;
+ SDL_Rect mouse_rect;
+
+ window_rect.x = 0;
+ window_rect.y = 0;
+ window_rect.w = x_max + 1;
+ window_rect.h = y_max + 1;
+ if (SDL_GetRectIntersection(confine, &window_rect, &mouse_rect)) {
+ x_min = mouse_rect.x;
+ y_min = mouse_rect.y;
+ x_max = x_min + mouse_rect.w - 1;
+ y_max = y_min + mouse_rect.h - 1;
+ }
+ }
+
+ if (*x >= (float)(x_max + 1)) {
+ *x = SDL_max((float)x_max, mouse->last_x);
+ }
+ if (*x < (float)x_min) {
+ *x = (float)x_min;
+ }
+
+ if (*y >= (float)(y_max + 1)) {
+ *y = SDL_max((float)y_max, mouse->last_y);
+ }
+ if (*y < (float)y_min) {
+ *y = (float)y_min;
+ }
+ }
+}
+
static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_MouseID mouseID, int relative, float x, float y)
{
SDL_Mouse *mouse = SDL_GetMouse();
@@ -498,9 +539,14 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_
yrel = y;
x = (mouse->last_x + xrel);
y = (mouse->last_y + yrel);
- } else if (mouse->has_position) {
- xrel = x - mouse->last_x;
- yrel = y - mouse->last_y;
+ ConstrainMousePosition(mouse, window, &x, &y);
+ } else {
+ ConstrainMousePosition(mouse, window, &x, &y);
+
+ if (mouse->has_position) {
+ xrel = x - mouse->last_x;
+ yrel = y - mouse->last_y;
+ }
}
/* Ignore relative motion when first positioning the mouse */
@@ -530,44 +576,6 @@ static int SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL_
mouse->y += yrel;
}
- /* make sure that the pointers find themselves inside the windows,
- unless we have the mouse captured. */
- if (window && !(window->flags & SDL_WINDOW_MOUSE_CAPTURE)) {
- int x_min = 0, x_max = window->w - 1;
- int y_min = 0, y_max = window->h - 1;
- const SDL_Rect *confine = SDL_GetWindowMouseRect(window);
-
- if (confine) {
- SDL_Rect window_rect;
- SDL_Rect mouse_rect;
-
- window_rect.x = 0;
- window_rect.y = 0;
- window_rect.w = x_max + 1;
- window_rect.h = y_max + 1;
- if (SDL_GetRectIntersection(confine, &window_rect, &mouse_rect)) {
- x_min = mouse_rect.x;
- y_min = mouse_rect.y;
- x_max = x_min + mouse_rect.w - 1;
- y_max = y_min + mouse_rect.h - 1;
- }
- }
-
- if (mouse->x >= (float)(x_max + 1)) {
- mouse->x = (float)x_max;
- }
- if (mouse->x < (float)x_min) {
- mouse->x = (float)x_min;
- }
-
- if (mouse->y >= (float)(y_max + 1)) {
- mouse->y = (float)y_max;
- }
- if (mouse->y < (float)y_min) {
- mouse->y = (float)y_min;
- }
- }
-
mouse->xdelta += xrel;
mouse->ydelta += yrel;