From 8b12d09fd6906dcbd4b7f0c1fb18357af5d7c5c3 Mon Sep 17 00:00:00 2001 From: expikr <77922942+expikr@users.noreply.github.com> Date: Wed, 13 Nov 2024 23:58:27 +0800 Subject: [PATCH] fix errenous delta when warping The following changes do not alter any logic: - rename x/ydelta fields to x/y_accu to better reflect what it actually is about - coalesce the logic for modifying internal state to one spot, branch based on whether the input was a move or a warp The following changes alter the logic: - put the x/y_accu addition under the relative branch only, warps should not add to the accumulation buffer by any definition - (MAIN FIX) set the pushed event's x/yrel value to zero if relative. This is the only way a developer can differentiate between a move and a warp. --- src/events/SDL_mouse.c | 53 ++++++++++++++++++++-------------------- src/events/SDL_mouse_c.h | 4 +-- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index 1d9fc8a4102c1..48e6267492f91 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -794,7 +794,6 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL 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; @@ -814,25 +813,30 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL yrel = 0.0f; } - if (mouse->has_position) { - // Update internal mouse coordinates - if (!mouse->relative_mode) { + { // modify internal state + if (relative) { + if (mouse->has_position) { + mouse->x += xrel; + mouse->y += yrel; + ConstrainMousePosition(mouse, window, &mouse->x, &mouse->y); + } else { + mouse->x = x; + mouse->y = y; + } + mouse->last_x = mouse->x; + mouse->last_y = mouse->y; + mouse->x_accu += xrel; + mouse->y_accu += yrel; + } else { + // Use unclamped values if we're getting events outside the window mouse->x = x; mouse->y = y; - } else { - mouse->x += xrel; - mouse->y += yrel; - ConstrainMousePosition(mouse, window, &mouse->x, &mouse->y); + mouse->last_x = x; + mouse->last_y = y; } - } else { - mouse->x = x; - mouse->y = y; mouse->has_position = true; } - mouse->xdelta += xrel; - mouse->ydelta += yrel; - // Move the mouse cursor, if needed if (mouse->cursor_shown && !mouse->relative_mode && mouse->MoveCursor && mouse->cur_cursor) { @@ -841,6 +845,11 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL // Post the event, if desired if (SDL_EventEnabled(SDL_EVENT_MOUSE_MOTION)) { + if (!relative) { + // if (window->flags & SDL_WINDOW_MOUSE_RELATIVE_MODE) return; + xrel = 0.0f; + yrel = 0.0f; + } SDL_Event event; event.type = SDL_EVENT_MOUSE_MOTION; event.common.timestamp = timestamp; @@ -855,14 +864,6 @@ static void SDL_PrivateSendMouseMotion(Uint64 timestamp, SDL_Window *window, SDL event.motion.yrel = yrel; SDL_PushEvent(&event); } - if (relative) { - mouse->last_x = mouse->x; - mouse->last_y = mouse->y; - } else { - // Use unclamped values if we're getting events outside the window - mouse->last_x = x; - mouse->last_y = y; - } } static SDL_MouseInputSource *GetMouseInputSource(SDL_Mouse *mouse, SDL_MouseID mouseID, bool down, Uint8 button) @@ -1178,13 +1179,13 @@ SDL_MouseButtonFlags SDL_GetRelativeMouseState(float *x, float *y) SDL_Mouse *mouse = SDL_GetMouse(); if (x) { - *x = mouse->xdelta; + *x = mouse->x_accu; } if (y) { - *y = mouse->ydelta; + *y = mouse->y_accu; } - mouse->xdelta = 0.0f; - mouse->ydelta = 0.0f; + mouse->x_accu = 0.0f; + mouse->y_accu = 0.0f; return SDL_GetMouseButtonState(mouse, SDL_GLOBAL_MOUSE_ID, true); } diff --git a/src/events/SDL_mouse_c.h b/src/events/SDL_mouse_c.h index 993e2ae160bfa..9c324b4e74490 100644 --- a/src/events/SDL_mouse_c.h +++ b/src/events/SDL_mouse_c.h @@ -86,8 +86,8 @@ typedef struct SDL_Window *focus; float x; float y; - float xdelta; - float ydelta; + float x_accu; + float y_accu; float last_x, last_y; // the last reported x and y coordinates bool has_position; bool relative_mode;