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.

(cherry picked from commit a845c7027e)
This commit is contained in:
Frank Praznik
2024-04-15 13:46:32 -04:00
parent 59cc43ccbb
commit 863d4a0f2a
3 changed files with 26 additions and 1 deletions

View File

@@ -317,8 +317,19 @@ static void WarpMouseInternal(Window xwindow, const int x, const int y)
{
SDL_VideoData *videodata = (SDL_VideoData *)SDL_GetVideoDevice()->driverdata;
Display *display = videodata->display;
#ifdef SDL_VIDEO_DRIVER_X11_XINPUT2
SDL_Mouse *mouse = SDL_GetMouse();
int deviceid = 0;
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
if (X11_Xinput2IsInitialized()) {
/* It seems XIWarpPointer() doesn't work correctly on multi-head setups:
* https://developer.blender.org/rB165caafb99c6846e53d11c4e966990aaffc06cea
@@ -335,6 +346,10 @@ static void WarpMouseInternal(Window xwindow, const int x, const int y)
{
X11_XWarpPointer(display, None, xwindow, 0, 0, 0, 0, x, y);
}
if (warp_hack) {
X11_ShowCursor(SDL_GetCursor());
}
X11_XSync(display, False);
videodata->global_mouse_changed = SDL_TRUE;
}

View File

@@ -145,6 +145,12 @@ static int X11_SafetyNetErrHandler(Display *d, XErrorEvent *e)
return 0;
}
static SDL_bool X11_IsXWayland(Display *d)
{
int opcode, event, error;
return X11_XQueryExtension(d, "XWAYLAND", &opcode, &event, &error) == True;
}
static SDL_VideoDevice *X11_CreateDevice(void)
{
SDL_VideoDevice *device;
@@ -322,6 +328,8 @@ static SDL_VideoDevice *X11_CreateDevice(void)
device->Vulkan_CreateSurface = X11_Vulkan_CreateSurface;
#endif
data->is_xwayland = X11_IsXWayland(x11_display);
return device;
}

View File

@@ -156,6 +156,8 @@ typedef struct SDL_VideoData
SDL_bool is_steam_deck;
SDL_bool steam_keyboard_open;
SDL_bool is_xwayland;
} SDL_VideoData;
extern SDL_bool X11_UseDirectColorVisuals(void);