From b55bb027239cd14558e806df60c9f77152fc281a Mon Sep 17 00:00:00 2001 From: Sam Lantinga 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 a438640de..1151feb43 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;