From bd8fea39a1017015dca2c22261918e1e4b76b9bf Mon Sep 17 00:00:00 2001 From: meag Date: Wed, 21 Jul 2021 20:13:08 +0100 Subject: [PATCH] INPUT: 'in_raw 0' ignores mouse motion events This has been fixed/broken/fixed/broken on different platforms for a while now. in_raw 0 relies on SDL_WarpMouseInWindow... on Windows the SDL_MOTION event is picked up in subsequent event pump, on Mac it is picked up immediately after (leading to immediately setting mx to 0 and in_raw 0 appearing to not work in-game). Now using state rather than motion events if using in_raw, which avoids our SDL_Warp() producing an event that we then have to try to ignore Might help with #489? --- release-notes-latest.md | 1 + release-notes.md | 1 + vid_sdl2.c | 58 +++++++++++++++++++++++++++-------------- 3 files changed, 40 insertions(+), 20 deletions(-) diff --git a/release-notes-latest.md b/release-notes-latest.md index 305bd7660..5d6d3c6ba 100644 --- a/release-notes-latest.md +++ b/release-notes-latest.md @@ -6,6 +6,7 @@ Leaving these here as bugs between dev versions of 3.6 aren't in the release not - Fixed bug causing off-by-one error when drawing rectangle outlines (3.5 bug, reported by Matrix, #536) - Detection of AMD drivers .13399 wasn't being working in classic renderer (#416) - Added `/gl_smoothmodels` back in, (requested by Repast via [quakeworld.nu](https://www.quakeworld.nu/forum/topic/7508/why-is-the-command-glsmoothmodels-r)) +- `/in_raw 0` behaviour changed to hopefully fix on MacOS and not break Windows ### Changes from alpha7=>alpha8 (Feb 9th => July 13th) diff --git a/release-notes.md b/release-notes.md index da52dec02..2a464d6f5 100644 --- a/release-notes.md +++ b/release-notes.md @@ -51,6 +51,7 @@ - Fixed bug causing "Unset entity number" message & program termination as entnum overwritten from local baselines after avoiding buffer overflow in previous frame (reported during sdCup2 on Discord) - Fixed bug causing `/cl_mvinsetcrosshair 1` crosshair to not move with the inset view (#462, 3.2 bug, reported by ptdev) - Fixed bug causing `/scr_cursor_iconoffset_x` & `/scr_cursor_iconoffset_y` to have no effect (3.x bug, fix by ciscon) +- Fixed bug causing `/in_raw 0` to produce no mouse input in-game on MacOS - Workaround applied to show players when playing back demos using FTE model extensions where player index >= 256 (3.1+ bug (no support in older clients), #551, reported by lordee) #### Bugs which affected 3.5 (typically related to renderer rewrite) diff --git a/vid_sdl2.c b/vid_sdl2.c index b826938d8..5e66fd665 100644 --- a/vid_sdl2.c +++ b/vid_sdl2.c @@ -245,6 +245,13 @@ qbool IN_QuakeMouseCursorRequired(void) return mouse_active && IN_MouseTrackingRequired() && !IN_OSMouseCursorRequired(); } +static void IN_SnapMouseBackToCentre(void) +{ + SDL_WarpMouseInWindow(sdl_window, glConfig.vidWidth / 2, glConfig.vidHeight / 2); + old_x = glConfig.vidWidth / 2; + old_y = glConfig.vidHeight / 2; +} + static void in_raw_callback(cvar_t *var, char *value, qbool *cancel) { if (var == &in_raw) @@ -260,20 +267,22 @@ static void in_grab_windowed_mouse_callback(cvar_t *val, char *value, qbool *can static void GrabMouse(qbool grab, qbool raw) { - if ((grab && mouse_active && raw == in_raw.integer) || (!grab && !mouse_active) || !mouseinitialized || !sdl_window) + if ((grab && mouse_active && raw == in_raw.integer) || (!grab && !mouse_active) || !mouseinitialized || !sdl_window) { return; + } - if (!r_fullscreen.integer && in_grab_windowed_mouse.integer == 0) - { - if (!mouse_active) + if (!r_fullscreen.integer && in_grab_windowed_mouse.integer == 0) { + if (!mouse_active) { return; + } grab = 0; } + // set initial position if (!raw && grab) { - SDL_WarpMouseInWindow(sdl_window, glConfig.vidWidth / 2, glConfig.vidHeight / 2); - old_x = glConfig.vidWidth / 2; - old_y = glConfig.vidHeight / 2; + // the first getState() will still return the old values so snapping back doesn't work... + // ... open problem, people will get a jump if releasing mouse when re-grabbing with in_raw 0 + IN_SnapMouseBackToCentre(); } SDL_SetWindowGrab(sdl_window, grab ? SDL_TRUE : SDL_FALSE); @@ -287,7 +296,8 @@ static void GrabMouse(qbool grab, qbool raw) SDL_ShowCursor(grab ? SDL_DISABLE : SDL_ENABLE); } - SDL_SetCursor(NULL); /* Force rewrite of it */ + // Force rewrite of it + SDL_SetCursor(NULL); mouse_active = grab; } @@ -309,6 +319,9 @@ void IN_StartupMouse(void) mouseinitialized = true; Com_Printf("%s mouse input initialized\n", in_raw.integer > 0 ? "RAW" : "SDL"); + if (in_raw.integer == 0) { + IN_SnapMouseBackToCentre(); + } } void IN_ActivateMouse(void) @@ -803,6 +816,7 @@ static void HandleWindowsKeyboardEvents(unsigned int flags, qbool down) static void HandleEvents(void) { SDL_Event event; + qbool track_movement_through_state = (mouse_active && !SDL_GetRelativeMouseMode()); #if defined(_WIN32) && !defined(WITHOUT_WINKEYHOOK) HandleWindowsKeyboardEvents(windows_keys_down, true); @@ -838,18 +852,7 @@ static void HandleEvents(void) Con_Printf("motion event, which=%d\n", event.motion.which); } #endif - if (mouse_active && !SDL_GetRelativeMouseMode()) { - float factor = (IN_MouseTrackingRequired() ? cursor_sensitivity.value : 1); - - mx = event.motion.x - old_x; - my = event.motion.y - old_y; - cursor_x = min(max(0, cursor_x + (event.motion.x - glConfig.vidWidth / 2) * factor), VID_RenderWidth2D()); - cursor_y = min(max(0, cursor_y + (event.motion.y - glConfig.vidHeight / 2) * factor), VID_RenderHeight2D()); - SDL_WarpMouseInWindow(sdl_window, glConfig.vidWidth / 2, glConfig.vidHeight / 2); - old_x = glConfig.vidWidth / 2; - old_y = glConfig.vidHeight / 2; - } - else { + if (!track_movement_through_state) { float factor = (IN_MouseTrackingRequired() ? cursor_sensitivity.value : 1); cursor_x += event.motion.xrel * factor; @@ -885,6 +888,21 @@ static void HandleEvents(void) break; } } + + if (track_movement_through_state) { + float factor = (IN_MouseTrackingRequired() ? cursor_sensitivity.value : 1); + int pos_x, pos_y; + + SDL_GetMouseState(&pos_x, &pos_y); + + mx = pos_x - old_x; + my = pos_y - old_y; + + cursor_x = min(max(0, cursor_x + (pos_x - glConfig.vidWidth / 2) * factor), VID_RenderWidth2D()); + cursor_y = min(max(0, cursor_y + (pos_y - glConfig.vidHeight / 2) * factor), VID_RenderHeight2D()); + + IN_SnapMouseBackToCentre(); + } } /*****************************************************************************/