From ef678bab1d3c6e146ab01b4205250901eaf8ad85 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Sat, 16 Jan 2021 20:17:19 +1100 Subject: [PATCH] [client] wayland: move wayland specific mouse code out of main.c --- client/displayservers/SDL/sdl.c | 6 ++ client/displayservers/Wayland/wayland.c | 13 +++ client/include/app.h | 1 + client/src/main.c | 108 ++++++++++-------------- 4 files changed, 66 insertions(+), 62 deletions(-) diff --git a/client/displayservers/SDL/sdl.c b/client/displayservers/SDL/sdl.c index d935ca7e..91fac034 100644 --- a/client/displayservers/SDL/sdl.c +++ b/client/displayservers/SDL/sdl.c @@ -63,6 +63,12 @@ static bool sdlEventFilter(SDL_Event * event) // stop motion events during the warp out of the window if (sdl.exiting) return true; + + app_updateCursorPos(event->motion.x, event->motion.y); + if (app_cursorIsGrabbed()) + app_handleMouseGrabbed(event->motion.xrel, event->motion.yrel); + else + app_handleMouseNormal(event->motion.xrel, event->motion.yrel); break; case SDL_WINDOWEVENT: diff --git a/client/displayservers/Wayland/wayland.c b/client/displayservers/Wayland/wayland.c index fe5f37d7..2cfa8247 100644 --- a/client/displayservers/Wayland/wayland.c +++ b/client/displayservers/Wayland/wayland.c @@ -356,6 +356,19 @@ static void waylandFree(void) static bool waylandEventFilter(SDL_Event * event) { + /* prevent the default processing for the following events */ + switch(event->type) + { + case SDL_MOUSEMOTION: + { + app_updateCursorPos(event->motion.x, event->motion.y); + + // we must use the basic handler as Wayland has no warp support + app_handleMouseBasic(event->motion.x, event->motion.y); + return true; + } + } + return false; } diff --git a/client/include/app.h b/client/include/app.h index f60b4a0e..e6b4ae6f 100644 --- a/client/include/app.h +++ b/client/include/app.h @@ -34,6 +34,7 @@ void app_updateWindowPos(int x, int y); void app_handleResizeEvent(int w, int h); void app_handleMouseGrabbed(double ex, double ey); void app_handleMouseNormal(double ex, double ey); +void app_handleMouseBasic(double ex, double ey); void app_handleWindowEnter(); void app_handleWindowLeave(); diff --git a/client/src/main.c b/client/src/main.c index 914d6ac0..f22bcfc9 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -950,43 +950,6 @@ 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 app_handleMouseWayland(void) -{ - const bool inView = - g_cursor.pos.x >= g_state.dstRect.x && - g_cursor.pos.x < g_state.dstRect.x + g_state.dstRect.w && - g_cursor.pos.y >= g_state.dstRect.y && - g_cursor.pos.y < g_state.dstRect.y + g_state.dstRect.h; - - if (params.hideMouse && inView != g_cursor.inView) - SDL_ShowCursor(inView ? SDL_DISABLE : SDL_ENABLE); - - g_cursor.inView = inView; - - if (g_cursor.guest.dpiScale == 0) - return; - - /* translate the guests position to our coordinate space */ - struct DoublePoint local; - guestCurToLocal(&local); - - double ex = (g_cursor.pos.x - local.x) / g_cursor.dpiScale; - double ey = (g_cursor.pos.y - local.y) / g_cursor.dpiScale; - - int x, y; - cursorToInt(ex, ey, &x, &y); - - g_cursor.guest.x += x; - g_cursor.guest.y += y; - - if (!spice_mouse_motion(x, y)) - DEBUG_ERROR("failed to send mouse motion message"); -} - void app_handleMouseNormal(double ex, double ey) { /* if we don't have the current cursor pos just send cursor movements */ @@ -997,12 +960,6 @@ void app_handleMouseNormal(double ex, double ey) return; } - if (g_state.wminfo.subsystem == SDL_SYSWM_WAYLAND) - { - app_handleMouseWayland(); - return; - } - /* scale the movement to the guest */ if (g_cursor.useScale && params.scaleMouseInput) { @@ -1135,6 +1092,52 @@ void app_handleMouseNormal(double ex, double ey) DEBUG_ERROR("failed to send mouse motion message"); } + +// On some display servers 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. +void app_handleMouseBasic(double ex, double ey) +{ + /* if we don't have the current cursor pos just send cursor movements */ + if (!g_cursor.guest.valid) + { + if (g_cursor.grab) + app_handleMouseGrabbed(ex, ey); + return; + } + + const bool inView = + g_cursor.pos.x >= g_state.dstRect.x && + g_cursor.pos.x < g_state.dstRect.x + g_state.dstRect.w && + g_cursor.pos.y >= g_state.dstRect.y && + g_cursor.pos.y < g_state.dstRect.y + g_state.dstRect.h; + + if (params.hideMouse && inView != g_cursor.inView) + SDL_ShowCursor(inView ? SDL_DISABLE : SDL_ENABLE); + + g_cursor.inView = inView; + + if (g_cursor.guest.dpiScale == 0) + return; + + /* translate the guests position to our coordinate space */ + struct DoublePoint local; + guestCurToLocal(&local); + + double lx = (g_cursor.pos.x - local.x) / g_cursor.dpiScale; + double ly = (g_cursor.pos.y - local.y) / g_cursor.dpiScale; + + int x, y; + cursorToInt(lx, ly, &x, &y); + + g_cursor.guest.x += x; + g_cursor.guest.y += y; + + if (!spice_mouse_motion(x, y)) + DEBUG_ERROR("failed to send mouse motion message"); +} + void app_updateWindowPos(int x, int y) { g_state.windowPos.x = x; @@ -1320,25 +1323,6 @@ int eventFilter(void * userdata, SDL_Event * event) return 0; } - case SDL_MOUSEMOTION: - { - g_cursor.pos.x = event->motion.x; - g_cursor.pos.y = event->motion.y; - - if (g_state.wminfo.subsystem != SDL_SYSWM_WAYLAND) - { - // On Wayland, wm.c calls these functions, bypassing the SDL event loop. - if (g_cursor.grab) - { - if (g_state.wminfo.subsystem != SDL_SYSWM_WAYLAND) - app_handleMouseGrabbed(event->motion.xrel, event->motion.yrel); - } - else - app_handleMouseNormal(event->motion.xrel, event->motion.yrel); - } - break; - } - case SDL_KEYDOWN: { SDL_Scancode sc = event->key.keysym.scancode;