The current code shows annoying behavior where the X pointer can move out of the window during the input grab in the absolute mode. Due to this, the pointer in qemu window looks as if frozen until the real (invisible) X pointer comes back to the window again.
For avoiding such an unexpected lag, this patch limits the pointer movement only within the qemu window during the input grab in the absolute mode. When the pointer goes out, it's moved back to the boundary again. Signed-off-by: Takashi Iwai <ti...@suse.de> --- ui/gtk.c | 51 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/ui/gtk.c b/ui/gtk.c index 00fbbccb34b9..f87434093946 100644 --- a/ui/gtk.c +++ b/ui/gtk.c @@ -341,19 +341,13 @@ static void gd_refresh(DisplayChangeListener *dcl) graphic_hw_update(dcl->con); } -#if GTK_CHECK_VERSION(3, 0, 0) -static void gd_mouse_set(DisplayChangeListener *dcl, - int x, int y, int visible) +static void gd_warp_pointer(GtkDisplayState *s, int x, int y) { - GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); +#if GTK_CHECK_VERSION(3, 0, 0) GdkDisplay *dpy; GdkDeviceManager *mgr; gint x_root, y_root; - if (qemu_input_is_absolute()) { - return; - } - dpy = gtk_widget_get_display(s->drawing_area); mgr = gdk_display_get_device_manager(dpy); gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area), @@ -361,25 +355,27 @@ static void gd_mouse_set(DisplayChangeListener *dcl, gdk_device_warp(gdk_device_manager_get_client_pointer(mgr), gtk_widget_get_screen(s->drawing_area), x_root, y_root); -} #else + gint x_root, y_root; + + gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area), + x, y, &x_root, &y_root); + gdk_display_warp_pointer(gtk_widget_get_display(s->drawing_area), + gtk_widget_get_screen(s->drawing_area), + x_root, y_root); +#endif +} + static void gd_mouse_set(DisplayChangeListener *dcl, int x, int y, int visible) { GtkDisplayState *s = container_of(dcl, GtkDisplayState, dcl); - gint x_root, y_root; if (qemu_input_is_absolute()) { return; } - - gdk_window_get_root_coords(gtk_widget_get_window(s->drawing_area), - x, y, &x_root, &y_root); - gdk_display_warp_pointer(gtk_widget_get_display(s->drawing_area), - gtk_widget_get_screen(s->drawing_area), - x_root, y_root); + gd_warp_pointer(s, x, y); } -#endif static void gd_cursor_define(DisplayChangeListener *dcl, QEMUCursor *c) @@ -627,10 +623,23 @@ static gboolean gd_motion_event(GtkWidget *widget, GdkEventMotion *motion, y = (motion->y - my) / s->scale_y; if (qemu_input_is_absolute()) { - if (x < 0 || y < 0 || - x >= surface_width(s->ds) || - y >= surface_height(s->ds)) { - return TRUE; + int ox = x, oy = y; + if (x < 0) { + x = 0; + } else if (x >= surface_width(s->ds)) { + x = surface_width(s->ds) - 1; + } + if (y < 0) { + y = 0; + } else if (y >= surface_height(s->ds)) { + y = surface_height(s->ds) - 1; + } + if (ox != x || oy != y) { + if (!gd_is_grab_active(s)) { + return TRUE; + } + /* keep the pointer within the drawing area during input grab */ + gd_warp_pointer(s, x * s->scale_x + mx, y * s->scale_y + my); } qemu_input_queue_abs(s->dcl.con, INPUT_AXIS_X, x, surface_width(s->ds)); -- 1.9.1