Skip to content

Commit 40ed9f7

Browse files
committed
Workaround for Windows occasionally ignoring SetCursorPos() calls
Also, since we're flushing mouse motion before and including the warp, we don't need the isWin10FCUorNewer hack to simulate mouse warp motion. Fixes #4339 and #4165
1 parent 373216a commit 40ed9f7

File tree

3 files changed

+19
-26
lines changed

3 files changed

+19
-26
lines changed

src/video/windows/SDL_windowsevents.c

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -477,11 +477,6 @@ ShouldGenerateWindowCloseOnAltF4(void)
477477
return !SDL_GetHintBoolean(SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, SDL_FALSE);
478478
}
479479

480-
/* Win10 "Fall Creators Update" introduced the bug that SetCursorPos() (as used by SDL_WarpMouseInWindow())
481-
doesn't reliably generate WM_MOUSEMOVE events anymore (see #3931) which breaks relative mouse mode via warping.
482-
This is used to implement a workaround.. */
483-
static SDL_bool isWin10FCUorNewer = SDL_FALSE;
484-
485480
/* We want to generate mouse events from mouse and pen, and touch events from touchscreens */
486481
#define MI_WP_SIGNATURE 0xFF515700
487482
#define MI_WP_SIGNATURE_MASK 0xFFFFFF00
@@ -581,7 +576,7 @@ WarpWithinBoundsRect(int x, int y, RECT *bounds)
581576
} else {
582577
warpY = SDL_clamp(y, targetTop, targetBottom);
583578
}
584-
SetCursorPos(warpX, warpY);
579+
WIN_SetCursorPos(warpX, warpY);
585580
}
586581
}
587582
}
@@ -752,18 +747,6 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
752747
if (GetMouseMessageSource() != SDL_MOUSE_EVENT_SOURCE_TOUCH &&
753748
lParam != data->last_pointer_update) {
754749
SDL_SendMouseMotion(data->window, 0, 0, GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
755-
if (isWin10FCUorNewer && mouse->relative_mode_warp &&
756-
(data->window->flags & SDL_WINDOW_INPUT_FOCUS) != 0) {
757-
/* To work around #3931, Win10 bug introduced in Fall Creators Update, where
758-
SetCursorPos() (SDL_WarpMouseInWindow()) doesn't reliably generate mouse events anymore,
759-
after each windows mouse event generate a fake event for the middle of the window
760-
if relative_mode_warp is used */
761-
int center_x = 0, center_y = 0;
762-
SDL_GetWindowSize(data->window, &center_x, &center_y);
763-
center_x /= 2;
764-
center_y /= 2;
765-
SDL_SendMouseMotion(data->window, 0, 0, center_x, center_y);
766-
}
767750
}
768751
}
769752
}
@@ -1703,8 +1686,6 @@ SDL_RegisterApp(char *name, Uint32 style, void *hInst)
17031686
return SDL_SetError("Couldn't register application class");
17041687
}
17051688

1706-
isWin10FCUorNewer = IsWin10FCUorNewer();
1707-
17081689
app_registered = 1;
17091690
return 0;
17101691
}

src/video/windows/SDL_windowsmouse.c

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,21 @@ WIN_ShowCursor(SDL_Cursor * cursor)
236236
return 0;
237237
}
238238

239+
void
240+
WIN_SetCursorPos(int x, int y)
241+
{
242+
/* We need to jitter the value because otherwise Windows will occasionally inexplicably ignore the SetCursorPos() or SendInput() */
243+
SetCursorPos(x, y);
244+
SetCursorPos(x+1, y);
245+
SetCursorPos(x, y);
246+
247+
/* Flush any mouse motion prior to or associated with this warp */
248+
SDL_last_warp_time = GetTickCount();
249+
if (!SDL_last_warp_time) {
250+
SDL_last_warp_time = 1;
251+
}
252+
}
253+
239254
static void
240255
WIN_WarpMouse(SDL_Window * window, int x, int y)
241256
{
@@ -251,13 +266,9 @@ WIN_WarpMouse(SDL_Window * window, int x, int y)
251266
pt.x = x;
252267
pt.y = y;
253268
ClientToScreen(hwnd, &pt);
254-
SetCursorPos(pt.x, pt.y);
269+
WIN_SetCursorPos(pt.x, pt.y);
255270

256-
/* Flush any pending mouse motion and simulate motion for this warp */
257-
SDL_last_warp_time = GetTickCount();
258-
if (!SDL_last_warp_time) {
259-
SDL_last_warp_time = 1;
260-
}
271+
/* Send the exact mouse motion associated with this warp */
261272
SDL_SendMouseMotion(window, SDL_GetMouse()->mouseID, 0, x, y);
262273
}
263274

src/video/windows/SDL_windowsmouse.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ extern HCURSOR SDL_cursor;
2828

2929
extern void WIN_InitMouse(_THIS);
3030
extern void WIN_QuitMouse(_THIS);
31+
extern void WIN_SetCursorPos(int x, int y);
3132

3233
#endif /* SDL_windowsmouse_h_ */
3334

0 commit comments

Comments
 (0)