From a845c7027e68ff1c75bf814819d8e6b22499d899 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 15 Apr 2024 13:46:32 -0400 Subject: [PATCH] x11: Fix pointer warp on XWayland XWayland seems to require that the pointer be hidden when it is warped, so hide and show the pointer when warping, if required. Note that XWayland still only allows warping within the window, so attempts to warp to global coordinates outside the window won't work. --- src/video/x11/SDL_x11mouse.c | 15 +++++++++++++++ src/video/x11/SDL_x11video.c | 4 +++- src/video/x11/SDL_x11video.h | 2 ++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/video/x11/SDL_x11mouse.c b/src/video/x11/SDL_x11mouse.c index 079332ad7..dc4735375 100644 --- a/src/video/x11/SDL_x11mouse.c +++ b/src/video/x11/SDL_x11mouse.c @@ -318,6 +318,17 @@ static void X11_WarpMouseInternal(Window xwindow, float x, float y) { SDL_VideoData *videodata = SDL_GetVideoDevice()->driverdata; Display *display = videodata->display; + SDL_Mouse *mouse = SDL_GetMouse(); + SDL_bool warp_hack = SDL_FALSE; + + /* XWayland will only warp the cursor if it is hidden, so this workaround is required. */ + if (videodata->is_xwayland && mouse && mouse->cursor_shown) { + warp_hack = SDL_TRUE; + } + + if (warp_hack) { + X11_ShowCursor(NULL); + } #ifdef SDL_VIDEO_DRIVER_X11_XINPUT2 int deviceid = 0; if (X11_Xinput2IsInitialized()) { @@ -336,6 +347,10 @@ static void X11_WarpMouseInternal(Window xwindow, float x, float y) { X11_XWarpPointer(display, None, xwindow, 0, 0, 0, 0, (int)x, (int)y); } + + if (warp_hack) { + X11_ShowCursor(SDL_GetCursor()); + } X11_XSync(display, False); videodata->global_mouse_changed = SDL_TRUE; } diff --git a/src/video/x11/SDL_x11video.c b/src/video/x11/SDL_x11video.c index 3aba22386..d1736ecf3 100644 --- a/src/video/x11/SDL_x11video.c +++ b/src/video/x11/SDL_x11video.c @@ -289,8 +289,10 @@ static SDL_VideoDevice *X11_CreateDevice(void) device->device_caps = VIDEO_DEVICE_CAPS_HAS_POPUP_WINDOW_SUPPORT | VIDEO_DEVICE_CAPS_SENDS_FULLSCREEN_DIMENSIONS; - if (X11_IsXWayland(x11_display)) + data->is_xwayland = X11_IsXWayland(x11_display); + if (data->is_xwayland) { device->device_caps |= VIDEO_DEVICE_CAPS_MODE_SWITCHING_EMULATED; + } return device; } diff --git a/src/video/x11/SDL_x11video.h b/src/video/x11/SDL_x11video.h index 71a2daf9d..cafa035a0 100644 --- a/src/video/x11/SDL_x11video.h +++ b/src/video/x11/SDL_x11video.h @@ -133,6 +133,8 @@ struct SDL_VideoData SDL_bool is_steam_deck; SDL_bool steam_keyboard_open; + SDL_bool is_xwayland; + }; extern SDL_bool X11_UseDirectColorVisuals(void);