[Spice-devel] [spice-gtk PATCH v2] Ability to release the cursor with a keyboard shortcut

Pavel Grunt pgrunt at redhat.com
Thu Oct 9 02:46:03 PDT 2014


The cursor is grabbed/ungrabbed automatically by spice-gtk,
this patch allows releasing the cursor in the client mouse mode
with a keyboard shortcut.
---
v2:
 - fix crash on vm shutdown

 gtk/spice-widget-priv.h |  1 +
 gtk/spice-widget.c      | 68 +++++++++++++++++++++++++++++--------------------
 2 files changed, 42 insertions(+), 27 deletions(-)

diff --git a/gtk/spice-widget-priv.h b/gtk/spice-widget-priv.h
index 597ce10..c5960bd 100644
--- a/gtk/spice-widget-priv.h
+++ b/gtk/spice-widget-priv.h
@@ -92,6 +92,7 @@ struct _SpiceDisplayPrivate {
     enum SpiceMouseMode     mouse_mode;
     int                     mouse_grab_active;
     bool                    mouse_have_pointer;
+    gboolean                cursor_released;
     GdkCursor               *mouse_cursor;
     GdkPixbuf               *mouse_pixbuf;
     GdkPoint                mouse_hotspot;
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index 1220030..5a14236 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -916,8 +916,11 @@ static void update_mouse_pointer(SpiceDisplay *display)
 
     switch (d->mouse_mode) {
     case SPICE_MOUSE_MODE_CLIENT:
-        if (gdk_window_get_cursor(window) != d->mouse_cursor)
+        if (d->cursor_released) {
+            gdk_window_set_cursor(window, NULL);
+        } else if (gdk_window_get_cursor(window) != d->mouse_cursor) {
             gdk_window_set_cursor(window, d->mouse_cursor);
+        }
         break;
     case SPICE_MOUSE_MODE_SERVER:
         if (gdk_window_get_cursor(window) != NULL)
@@ -940,19 +943,21 @@ static void try_mouse_grab(SpiceDisplay *display)
 
     if (!d->mouse_have_pointer)
         return;
-    if (!d->keyboard_have_focus)
-        return;
 
     if (!d->mouse_grab_enable)
         return;
-    if (d->mouse_mode != SPICE_MOUSE_MODE_SERVER)
-        return;
     if (d->mouse_grab_active)
         return;
 
-    if (do_pointer_grab(display) != GDK_GRAB_SUCCESS)
-        return;
-
+    if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) {
+        if (do_pointer_grab(display) != GDK_GRAB_SUCCESS)
+            return;
+    } else {
+        try_keyboard_grab(display);
+        d->mouse_grab_active = true;
+        g_signal_emit(display, signals[SPICE_DISPLAY_MOUSE_GRAB], 0, true);
+    }
+    d->cursor_released = false;
     d->mouse_last_x = -1;
     d->mouse_last_y = -1;
 }
@@ -996,13 +1001,14 @@ static void try_mouse_ungrab(SpiceDisplay *display)
     if (!d->mouse_grab_active)
         return;
 
-    gdk_pointer_ungrab(GDK_CURRENT_TIME);
     gtk_grab_remove(GTK_WIDGET(display));
+    if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER && gdk_pointer_is_grabbed()) {
+        gdk_pointer_ungrab(GDK_CURRENT_TIME);
 #ifdef G_OS_WIN32
-    ClipCursor(NULL);
+        ClipCursor(NULL);
 #endif
-    set_mouse_accel(display, TRUE);
-
+        set_mouse_accel(display, TRUE);
+    }
     d->mouse_grab_active = false;
 
     g_signal_emit(display, signals[SPICE_DISPLAY_MOUSE_GRAB], 0, false);
@@ -1308,11 +1314,11 @@ static gboolean key_event(GtkWidget *widget, GdkEventKey *key)
     if (check_for_grab_key(display, key->type, key->keyval)) {
         g_signal_emit(widget, signals[SPICE_DISPLAY_GRAB_KEY_PRESSED], 0);
 
-        if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) {
-            if (d->mouse_grab_active)
-                try_mouse_ungrab(display);
-            else
-                try_mouse_grab(display);
+        if (d->mouse_grab_active) {
+            spice_display_mouse_ungrab(display);
+            try_keyboard_ungrab(display);
+        } else {
+            try_mouse_grab(display);
         }
     }
 
@@ -1402,7 +1408,10 @@ static gboolean enter_event(GtkWidget *widget, GdkEventCrossing *crossing G_GNUC
     SPICE_DEBUG("%s", __FUNCTION__);
 
     d->mouse_have_pointer = true;
+    if (d->cursor_released)
+        return true;
     try_keyboard_grab(display);
+    try_mouse_grab(display);
     update_display(display);
 
     return true;
@@ -1415,11 +1424,9 @@ static gboolean leave_event(GtkWidget *widget, GdkEventCrossing *crossing G_GNUC
 
     SPICE_DEBUG("%s", __FUNCTION__);
 
-    if (d->mouse_grab_active)
-        return true;
-
     d->mouse_have_pointer = false;
     try_keyboard_ungrab(display);
+    try_mouse_ungrab(display);
 
     return true;
 }
@@ -1442,6 +1449,8 @@ static gboolean focus_in_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UN
     if (!d->disable_inputs)
         spice_gtk_session_sync_keyboard_modifiers(d->gtk_session);
     update_keyboard_focus(display, true);
+    if (d->cursor_released)
+        return true;
     try_keyboard_grab(display);
     update_display(display);
 
@@ -1550,7 +1559,8 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
 
     switch (d->mouse_mode) {
     case SPICE_MOUSE_MODE_CLIENT:
-        if (x >= 0 && x < d->area.width &&
+        if (d->mouse_grab_active &&
+            x >= 0 && x < d->area.width &&
             y >= 0 && y < d->area.height) {
             spice_inputs_position(d->inputs, x, y, get_display_id(display),
                                   button_mask_gdk_to_spice(motion->state));
@@ -1628,12 +1638,11 @@ static gboolean button_event(GtkWidget *widget, GdkEventButton *button)
     }
 
     gtk_widget_grab_focus(widget);
-    if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER) {
-        if (!d->mouse_grab_active) {
-            try_mouse_grab(display);
-            return true;
-        }
-    } else
+    if (!d->mouse_grab_active) {
+        try_mouse_grab(display);
+        return true;
+    }
+    if (d->mouse_mode == SPICE_MOUSE_MODE_CLIENT)
         /* allow to drag and drop between windows/displays:
 
            By default, X (and other window system) do a pointer grab
@@ -2491,9 +2500,14 @@ SpiceDisplay* spice_display_new_with_monitor(SpiceSession *session, gint channel
  **/
 void spice_display_mouse_ungrab(SpiceDisplay *display)
 {
+    SpiceDisplayPrivate *d;
+
     g_return_if_fail(SPICE_IS_DISPLAY(display));
 
+    d = display->priv;
+
     try_mouse_ungrab(display);
+    d->cursor_released = true;
 }
 
 /**
-- 
1.9.3



More information about the Spice-devel mailing list