From 78bd41716ae3b4cc1ca57e100ede337a5944a62b Mon Sep 17 00:00:00 2001 From: Quantum Date: Sun, 10 Jan 2021 00:53:02 -0500 Subject: [PATCH] [client] spice: use simple custom Wayland mouse logic The normal logic does not work due to Wayland not supporting mouse warp. We use a simple logic that works for the desktop with 1:1 mouse patch and require capture mode for all other cases. --- client/src/main.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/client/src/main.c b/client/src/main.c index fcbe750d..4aee2b98 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -913,6 +913,25 @@ static void guestCurToLocal(struct DoublePoint *local) local->y = (g_cursor.guest.y + g_cursor.guest.hy) / g_cursor.scale.y; } +// On Wayland, our normal cursor logic does not work due to the lack of cursor +// warp support. Instead, we attempt a best-effort emulation which works with a +// 1:1 mouse movement patch applied in the guest. For anything fancy, use +// capture mode. +static void handleMouseWayland() +{ + double ex = (g_cursor.pos.x - g_cursor.guest.x) / g_cursor.dpiScale; + double ey = (g_cursor.pos.y - g_cursor.guest.y) / g_cursor.dpiScale; + + int x, y; + cursorToInt(ex, ey, &x, &y); + + g_cursor.delta.x += x; + g_cursor.delta.y += y; + + if (!spice_mouse_motion(x, y)) + DEBUG_ERROR("failed to send mouse motion message"); +} + static void handleMouseNormal(double ex, double ey) { /* if we don't have the current cursor pos just send cursor movements */ @@ -923,6 +942,12 @@ static void handleMouseNormal(double ex, double ey) return; } + if (g_state.wminfo.subsystem == SDL_SYSWM_WAYLAND) + { + handleMouseWayland(); + return; + } + /* scale the movement to the guest */ if (g_cursor.useScale && params.scaleMouseInput) { @@ -1197,11 +1222,15 @@ int eventFilter(void * userdata, SDL_Event * event) switch(event->window.event) { case SDL_WINDOWEVENT_ENTER: + if (g_state.wminfo.subsystem == SDL_SYSWM_WAYLAND) + g_cursor.inView = true; if (g_state.wminfo.subsystem != SDL_SYSWM_X11) handleWindowEnter(); break; case SDL_WINDOWEVENT_LEAVE: + if (g_state.wminfo.subsystem == SDL_SYSWM_WAYLAND) + g_cursor.inView = false; if (g_state.wminfo.subsystem != SDL_SYSWM_X11) handleWindowLeave(); break;