Work around mouse capture SDL bug on macOS

On macOS, SDL relative mouse mode does not work correctly when the
cursor is outside the window.

As a workaround, move the cursor inside the window before setting the
relative mouse mode.

Refs SDL/#5340 <https://github.com/libsdl-org/SDL/issues/5340>
PR #3031 <https://github.com/Genymobile/scrcpy/pull/3031>
This commit is contained in:
Romain Vimont 2022-02-17 21:46:13 +01:00
parent 9db42341e4
commit 3ee3f8dc02
2 changed files with 38 additions and 0 deletions

View file

@ -164,7 +164,26 @@ sc_screen_is_relative_mode(struct sc_screen *screen) {
static void static void
sc_screen_set_mouse_capture(struct sc_screen *screen, bool capture) { sc_screen_set_mouse_capture(struct sc_screen *screen, bool capture) {
#ifdef __APPLE__
// Workaround for SDL bug on macOS:
// <https://github.com/libsdl-org/SDL/issues/5340>
if (capture) {
int mouse_x, mouse_y;
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
int x, y, w, h;
SDL_GetWindowPosition(screen->window, &x, &y);
SDL_GetWindowSize(screen->window, &w, &h);
bool outside_window = mouse_x < x || mouse_x >= x + w
|| mouse_y < y || mouse_y >= y + h;
if (outside_window) {
SDL_WarpMouseInWindow(screen->window, w / 2, h / 2);
}
}
#else
(void) screen; (void) screen;
#endif
if (SDL_SetRelativeMouseMode(capture)) { if (SDL_SetRelativeMouseMode(capture)) {
LOGE("Could not set relative mouse mode to %s: %s", LOGE("Could not set relative mouse mode to %s: %s",
capture ? "true" : "false", SDL_GetError()); capture ? "true" : "false", SDL_GetError());

View file

@ -6,7 +6,26 @@
static void static void
sc_screen_otg_set_mouse_capture(struct sc_screen_otg *screen, bool capture) { sc_screen_otg_set_mouse_capture(struct sc_screen_otg *screen, bool capture) {
#ifdef __APPLE__
// Workaround for SDL bug on macOS:
// <https://github.com/libsdl-org/SDL/issues/5340>
if (capture) {
int mouse_x, mouse_y;
SDL_GetGlobalMouseState(&mouse_x, &mouse_y);
int x, y, w, h;
SDL_GetWindowPosition(screen->window, &x, &y);
SDL_GetWindowSize(screen->window, &w, &h);
bool outside_window = mouse_x < x || mouse_x >= x + w
|| mouse_y < y || mouse_y >= y + h;
if (outside_window) {
SDL_WarpMouseInWindow(screen->window, w / 2, h / 2);
}
}
#else
(void) screen; (void) screen;
#endif
if (SDL_SetRelativeMouseMode(capture)) { if (SDL_SetRelativeMouseMode(capture)) {
LOGE("Could not set relative mouse mode to %s: %s", LOGE("Could not set relative mouse mode to %s: %s",
capture ? "true" : "false", SDL_GetError()); capture ? "true" : "false", SDL_GetError());