From 3ee3f8dc027fe4e2d21ef144df4c29acbd709ee7 Mon Sep 17 00:00:00 2001 From: Romain Vimont Date: Thu, 17 Feb 2022 21:46:13 +0100 Subject: [PATCH] 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 PR #3031 --- app/src/screen.c | 19 +++++++++++++++++++ app/src/usb/screen_otg.c | 19 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/app/src/screen.c b/app/src/screen.c index 7ca9bfb7..ae28e6e6 100644 --- a/app/src/screen.c +++ b/app/src/screen.c @@ -164,7 +164,26 @@ sc_screen_is_relative_mode(struct sc_screen *screen) { static void sc_screen_set_mouse_capture(struct sc_screen *screen, bool capture) { +#ifdef __APPLE__ + // Workaround for SDL bug on macOS: + // + 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; +#endif if (SDL_SetRelativeMouseMode(capture)) { LOGE("Could not set relative mouse mode to %s: %s", capture ? "true" : "false", SDL_GetError()); diff --git a/app/src/usb/screen_otg.c b/app/src/usb/screen_otg.c index 96d7eaff..561a84ca 100644 --- a/app/src/usb/screen_otg.c +++ b/app/src/usb/screen_otg.c @@ -6,7 +6,26 @@ static void sc_screen_otg_set_mouse_capture(struct sc_screen_otg *screen, bool capture) { +#ifdef __APPLE__ + // Workaround for SDL bug on macOS: + // + 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; +#endif if (SDL_SetRelativeMouseMode(capture)) { LOGE("Could not set relative mouse mode to %s: %s", capture ? "true" : "false", SDL_GetError());