qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] gtk: Keep the pointer within window during input gr


From: Takashi Iwai
Subject: [Qemu-devel] [PATCH] gtk: Keep the pointer within window during input grab
Date: Tue, 8 Apr 2014 14:46:49 +0200

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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]