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 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/spice-devel