diff --git a/client/displayservers/Wayland/wayland.c b/client/displayservers/Wayland/wayland.c index da651a81..279924f9 100644 --- a/client/displayservers/Wayland/wayland.c +++ b/client/displayservers/Wayland/wayland.c @@ -230,13 +230,11 @@ static const struct wl_registry_listener registryListener = { static void pointerMotionHandler(void * data, struct wl_pointer * pointer, uint32_t serial, wl_fixed_t sxW, wl_fixed_t syW) { - if (wm.relativePointer) - return; - int sx = wl_fixed_to_int(sxW); int sy = wl_fixed_to_int(syW); app_updateCursorPos(sx, sy); - app_handleMouseBasic(); + if (!wm.relativePointer) + app_handleMouseBasic(); } static void pointerEnterHandler(void * data, struct wl_pointer * pointer, @@ -253,8 +251,10 @@ static void pointerEnterHandler(void * data, struct wl_pointer * pointer, int sx = wl_fixed_to_int(sxW); int sy = wl_fixed_to_int(syW); + app_resyncMouseBasic(); app_updateCursorPos(sx, sy); - app_handleMouseBasic(); + if (!wm.relativePointer) + app_handleMouseBasic(); } static void pointerLeaveHandler(void * data, struct wl_pointer * pointer, @@ -810,6 +810,9 @@ static void waylandUngrabPointer(void) zwp_confined_pointer_v1_destroy(wm.confinedPointer); wm.confinedPointer = NULL; } + + app_resyncMouseBasic(); + app_handleMouseBasic(); } static void waylandGrabKeyboard(void) @@ -837,7 +840,7 @@ static void waylandWarpPointer(int x, int y, bool exiting) static void waylandRealignPointer(void) { - app_handleMouseBasic(); + app_resyncMouseBasic(); } static bool waylandIsValidPointerPos(int x, int y) diff --git a/client/include/app.h b/client/include/app.h index e3d49190..920b48b3 100644 --- a/client/include/app.h +++ b/client/include/app.h @@ -46,6 +46,7 @@ void app_handleResizeEvent(int w, int h, const struct Border border); void app_handleMouseGrabbed(double ex, double ey); void app_handleMouseNormal(double ex, double ey); void app_handleMouseBasic(void); +void app_resyncMouseBasic(void); void app_handleButtonPress(int button); void app_handleButtonRelease(int button); void app_handleKeyPress(int scancode); diff --git a/client/src/app.c b/client/src/app.c index 94a89143..de732128 100644 --- a/client/src/app.c +++ b/client/src/app.c @@ -456,6 +456,12 @@ void app_handleMouseNormal(double ex, double ey) DEBUG_ERROR("failed to send mouse motion message"); } +static inline double clamp(double x, double min, double max) +{ + if (x < min) return min; + if (x > max) return max; + return x; +} // 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 @@ -464,7 +470,7 @@ void app_handleMouseNormal(double ex, double ey) void app_handleMouseBasic() { /* do not pass mouse events to the guest if we do not have focus */ - if (!g_state.focused) + if (!g_cursor.guest.valid || !g_state.haveSrcSize || !g_state.focused) return; if (!app_inputEnabled()) @@ -478,39 +484,31 @@ void app_handleMouseBasic() core_setCursorInView(inView); - if (g_cursor.guest.dpiScale == 0) - return; + /* translate the current position to guest coordinate space */ + struct DoublePoint guest; + util_localCurToGuest(&guest); - double px = g_cursor.pos.x; - double py = g_cursor.pos.y; - - if (px < g_state.dstRect.x) - px = g_state.dstRect.x; - else if (px > g_state.dstRect.x + g_state.dstRect.w) - px = g_state.dstRect.x + g_state.dstRect.w; - - if (py < g_state.dstRect.y) - py = g_state.dstRect.y; - else if (py > g_state.dstRect.y + g_state.dstRect.h) - py = g_state.dstRect.y + g_state.dstRect.h; - - /* translate the guests position to our coordinate space */ - struct DoublePoint local; - util_guestCurToLocal(&local); - - int x = (int) round((px - local.x) / g_cursor.dpiScale); - int y = (int) round((py - local.y) / g_cursor.dpiScale); + int x = (int) round(clamp(guest.x, 0, g_state.srcSize.x) - g_cursor.projected.x); + int y = (int) round(clamp(guest.y, 0, g_state.srcSize.y) - g_cursor.projected.y); if (!x && !y) return; - g_cursor.guest.x += x; - g_cursor.guest.y += y; + g_cursor.projected.x += x; + g_cursor.projected.y += y; if (!spice_mouse_motion(x, y)) DEBUG_ERROR("failed to send mouse motion message"); } +void app_resyncMouseBasic() +{ + if (!g_cursor.guest.valid) + return; + g_cursor.projected.x = g_cursor.guest.x + g_cursor.guest.hx; + g_cursor.projected.y = g_cursor.guest.y + g_cursor.guest.hy; +} + void app_updateWindowPos(int x, int y) { g_state.windowPos.x = x; diff --git a/client/src/main.c b/client/src/main.c index 9e3eff88..5ced665c 100644 --- a/client/src/main.c +++ b/client/src/main.c @@ -297,7 +297,10 @@ static int cursorThread(void * unused) // if the state just became valid if (valid != true && app_inputEnabled()) + { core_alignToGuest(); + app_resyncMouseBasic(); + } } lgmpClientMessageDone(queue); diff --git a/client/src/main.h b/client/src/main.h index 1ad28e3c..06e1a373 100644 --- a/client/src/main.h +++ b/client/src/main.h @@ -234,6 +234,9 @@ struct CursorState /* the guest's cursor position */ struct CursorInfo guest; + + /* the projected position after move, for app_handleMouseBasic only */ + struct Point projected; }; // forwards