From 2ce9f640ef432b2d955e97c3636e95eb0864f79e Mon Sep 17 00:00:00 2001 From: Patric Stout Date: Sat, 3 Jun 2023 23:08:37 +0200 Subject: [PATCH] Fix: [SDL] unify the way X11 and Wayland handle mouse events Basically, we drop RelativeMode completely, and use the same trick as used by the Windows driver: read all motion events till the last one, and use that as value. --- src/video/sdl2_v.cpp | 22 +++++++++++++++------- src/video/sdl_v.cpp | 17 +++++++++++++++-- 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/src/video/sdl2_v.cpp b/src/video/sdl2_v.cpp index 51c490d231..51271c2b30 100644 --- a/src/video/sdl2_v.cpp +++ b/src/video/sdl2_v.cpp @@ -371,12 +371,25 @@ bool VideoDriver_SDL_Base::PollEvent() if (!SDL_PollEvent(&ev)) return false; switch (ev.type) { - case SDL_MOUSEMOTION: - if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) { + case SDL_MOUSEMOTION: { + int32_t x = ev.motion.x; + int32_t y = ev.motion.y; + + if (_cursor.fix_at) { + /* Get all queued mouse events now in case we have to warp the cursor. In the + * end, we only care about the current mouse position and not bygone events. */ + while (SDL_PeepEvents(&ev, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION)) { + x = ev.motion.x; + y = ev.motion.y; + } + } + + if (_cursor.UpdateCursorPosition(x, y, false)) { SDL_WarpMouseInWindow(this->sdl_window, _cursor.pos.x, _cursor.pos.y); } HandleMouseEvents(); break; + } case SDL_MOUSEWHEEL: if (ev.wheel.y > 0) { @@ -478,10 +491,8 @@ bool VideoDriver_SDL_Base::PollEvent() } else if (ev.window.event == SDL_WINDOWEVENT_ENTER) { // mouse entered the window, enable cursor _cursor.in_window = true; -#ifdef __EMSCRIPTEN__ /* Ensure pointer lock will not occur. */ SDL_SetRelativeMouseMode(SDL_FALSE); -#endif } else if (ev.window.event == SDL_WINDOWEVENT_LEAVE) { // mouse left the window, undraw cursor UndrawMouseCursor(); @@ -500,9 +511,6 @@ static const char *InitializeSDL() * UpdateWindowSurface() to update the window's texture instead of * its surface. */ SDL_SetHint(SDL_HINT_FRAMEBUFFER_ACCELERATION, "0"); -#ifndef __EMSCRIPTEN__ - SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1"); -#endif /* Check if the video-driver is already initialized. */ if (SDL_WasInit(SDL_INIT_VIDEO) != 0) return nullptr; diff --git a/src/video/sdl_v.cpp b/src/video/sdl_v.cpp index 1b180d3b8b..d01b17e194 100644 --- a/src/video/sdl_v.cpp +++ b/src/video/sdl_v.cpp @@ -477,12 +477,25 @@ bool VideoDriver_SDL::PollEvent() if (!SDL_PollEvent(&ev)) return false; switch (ev.type) { - case SDL_MOUSEMOTION: - if (_cursor.UpdateCursorPosition(ev.motion.x, ev.motion.y, true)) { + case SDL_MOUSEMOTION: { + int32_t x = ev.motion.x; + int32_t y = ev.motion.y; + + if (_cursor.fix_at) { + /* Get all queued mouse events now in case we have to warp the cursor. In the + * end, we only care about the current mouse position and not bygone events. */ + while (SDL_PeepEvents(&ev, 1, SDL_GETEVENT, SDL_MOUSEMOTION)) { + x = ev.motion.x; + y = ev.motion.y; + } + } + + if (_cursor.UpdateCursorPosition(x, y, false)) { SDL_WarpMouse(_cursor.pos.x, _cursor.pos.y); } HandleMouseEvents(); break; + } case SDL_MOUSEBUTTONDOWN: if (_rightclick_emulate && SDL_GetModState() & KMOD_CTRL) {