Skip to content

Commit

Permalink
INPUT: 'in_raw 0' ignores mouse motion events
Browse files Browse the repository at this point in the history
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 QW-Group#489?
  • Loading branch information
meag committed Jul 21, 2021
1 parent 32f263e commit bd8fea3
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 20 deletions.
1 change: 1 addition & 0 deletions release-notes-latest.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
1 change: 1 addition & 0 deletions release-notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
58 changes: 38 additions & 20 deletions vid_sdl2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
Expand All @@ -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;
}
Expand All @@ -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)
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}
}

/*****************************************************************************/
Expand Down

0 comments on commit bd8fea3

Please sign in to comment.