[Spice-devel] [PATCH spice-gtk 5/8] Add disable-inputs on Spice widget

Marc-André Lureau marcandre.lureau at gmail.com
Wed Nov 23 04:23:41 PST 2011


---
 gtk/spice-widget-priv.h |    1 +
 gtk/spice-widget.c      |  111 +++++++++++++++++++++++++++++++++++-----------
 gtk/spicy.c             |    6 +++
 3 files changed, 91 insertions(+), 27 deletions(-)

diff --git a/gtk/spice-widget-priv.h b/gtk/spice-widget-priv.h
index a5791a4..5065f7c 100644
--- a/gtk/spice-widget-priv.h
+++ b/gtk/spice-widget-priv.h
@@ -61,6 +61,7 @@ struct _SpiceDisplayPrivate {
     bool                    convert;
     bool                    have_mitshm;
     gboolean                allow_scaling;
+    gboolean                disable_inputs;
 
     /* TODO: make a display object instead? */
 #ifdef WITH_X11
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index cec9aaa..fa347a1 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -34,6 +34,7 @@
 #include "spice-widget-priv.h"
 #include "spice-gtk-session-priv.h"
 #include "vncdisplaykeymap.h"
+#include "spice-util-priv.h"
 
 /* Some compatibility defines to let us build on both Gtk2 and Gtk3 */
 #if GTK_CHECK_VERSION (2, 91, 0)
@@ -86,6 +87,7 @@ enum {
     PROP_RESIZE_GUEST,
     PROP_AUTO_CLIPBOARD,
     PROP_SCALING,
+    PROP_DISABLE_INPUTS,
 };
 
 /* Signals */
@@ -102,10 +104,12 @@ static guint signals[SPICE_DISPLAY_LAST_SIGNAL];
 static HWND focus_window = NULL;
 #endif
 
+static void update_keyboard_grab(SpiceDisplay *display);
 static void try_keyboard_grab(SpiceDisplay *display);
 static void try_keyboard_ungrab(SpiceDisplay *display);
-static void try_mouse_grab(GtkWidget *widget);
-static void try_mouse_ungrab(GtkWidget *widget);
+static void update_mouse_grab(SpiceDisplay *display);
+static void try_mouse_grab(SpiceDisplay *display);
+static void try_mouse_ungrab(SpiceDisplay *display);
 static void recalc_geometry(GtkWidget *widget, gboolean set_display);
 static void disconnect_main(SpiceDisplay *display);
 static void disconnect_cursor(SpiceDisplay *display);
@@ -148,6 +152,9 @@ static void spice_display_get_property(GObject    *object,
     case PROP_SCALING:
         g_value_set_boolean(value, d->allow_scaling);
 	break;
+    case PROP_DISABLE_INPUTS:
+        g_value_set_boolean(value, d->disable_inputs);
+	break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -172,17 +179,11 @@ static void spice_display_set_property(GObject      *object,
         break;
     case PROP_KEYBOARD_GRAB:
         d->keyboard_grab_enable = g_value_get_boolean(value);
-        if (d->keyboard_grab_enable) {
-            try_keyboard_grab(display);
-        } else {
-            try_keyboard_ungrab(display);
-        }
+        update_keyboard_grab(display);
         break;
     case PROP_MOUSE_GRAB:
         d->mouse_grab_enable = g_value_get_boolean(value);
-        if (!d->mouse_grab_enable) {
-            try_mouse_ungrab(GTK_WIDGET(display));
-        }
+        update_mouse_grab(display);
         break;
     case PROP_RESIZE_GUEST:
         d->resize_guest_enable = g_value_get_boolean(value);
@@ -207,6 +208,12 @@ static void spice_display_set_property(GObject      *object,
         g_object_set(d->gtk_session, "auto-clipboard",
                      g_value_get_boolean(value), NULL);
         break;
+    case PROP_DISABLE_INPUTS:
+        d->disable_inputs = g_value_get_boolean(value);
+        gtk_widget_set_can_focus(GTK_WIDGET(display), !d->disable_inputs);
+        update_keyboard_grab(display);
+        update_mouse_grab(display);
+        break;
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
         break;
@@ -327,8 +334,8 @@ spice_display_constructor(GType                  gtype,
     }
     g_list_free(list);
 
-    g_signal_connect(d->gtk_session, "notify::auto-clipboard",
-                     G_CALLBACK(gtk_session_property_changed), display);
+    spice_g_signal_connect_object(d->gtk_session, "notify::auto-clipboard",
+                                  G_CALLBACK(gtk_session_property_changed), display, 0);
 
     return obj;
 }
@@ -410,12 +417,12 @@ static void try_keyboard_grab(SpiceDisplay *display)
 
     if (g_getenv("SPICE_NOGRAB"))
         return;
-
-    if (d->keyboard_grab_active)
+    if (d->disable_inputs)
         return;
-
     if (!d->keyboard_grab_enable)
         return;
+    if (d->keyboard_grab_active)
+        return;
     if (!d->keyboard_have_focus)
         return;
     if (!d->mouse_have_pointer)
@@ -441,7 +448,6 @@ static void try_keyboard_grab(SpiceDisplay *display)
     }
 }
 
-
 static void try_keyboard_ungrab(SpiceDisplay *display)
 {
     SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
@@ -460,6 +466,16 @@ static void try_keyboard_ungrab(SpiceDisplay *display)
     g_signal_emit(widget, signals[SPICE_DISPLAY_KEYBOARD_GRAB], 0, false);
 }
 
+static void update_keyboard_grab(SpiceDisplay *display)
+{
+    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
+
+    if (d->keyboard_grab_enable && !d->disable_inputs)
+        try_keyboard_grab(display);
+    else
+        try_keyboard_ungrab(display);
+}
+
 static GdkGrabStatus do_pointer_grab(SpiceDisplay *display)
 {
     SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
@@ -514,8 +530,9 @@ static void update_mouse_pointer(SpiceDisplay *display)
         if (!d->mouse_grab_active) {
             gdk_window_set_cursor(window, NULL);
         } else {
+            // FIXME: should it be transparent instead?
             gdk_window_set_cursor(window, d->mouse_cursor);
-            try_mouse_grab(GTK_WIDGET(display));
+            try_mouse_grab(display);
         }
         break;
     default:
@@ -524,13 +541,14 @@ static void update_mouse_pointer(SpiceDisplay *display)
     }
 }
 
-static void try_mouse_grab(GtkWidget *widget)
+static void try_mouse_grab(SpiceDisplay *display)
 {
-    SpiceDisplay *display = SPICE_DISPLAY(widget);
     SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
 
     if (g_getenv("SPICE_NOGRAB"))
         return;
+    if (d->disable_inputs)
+        return;
 
     if (!d->mouse_grab_enable)
         return;
@@ -579,9 +597,8 @@ static void mouse_check_edges(GtkWidget *widget, GdkEventMotion *motion)
     }
 }
 
-static void try_mouse_ungrab(GtkWidget *widget)
+static void try_mouse_ungrab(SpiceDisplay *display)
 {
-    SpiceDisplay *display = SPICE_DISPLAY(widget);
     SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
 
     if (!d->mouse_grab_active)
@@ -590,7 +607,17 @@ static void try_mouse_ungrab(GtkWidget *widget)
     gdk_pointer_ungrab(GDK_CURRENT_TIME);
     d->mouse_grab_active = false;
     update_mouse_pointer(display);
-    g_signal_emit(widget, signals[SPICE_DISPLAY_MOUSE_GRAB], 0, false);
+    g_signal_emit(display, signals[SPICE_DISPLAY_MOUSE_GRAB], 0, false);
+}
+
+static void update_mouse_grab(SpiceDisplay *display)
+{
+    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
+
+    if (d->mouse_grab_enable && !d->disable_inputs)
+        update_mouse_pointer(display);
+    else
+        try_mouse_ungrab(display);
 }
 
 static void recalc_geometry(GtkWidget *widget, gboolean set_display)
@@ -725,6 +752,9 @@ static void send_key(SpiceDisplay *display, int scancode, int down)
     if (!d->inputs)
         return;
 
+    if (d->disable_inputs)
+        return;
+
     i = scancode / 32;
     b = scancode % 32;
     m = (1 << b);
@@ -814,11 +844,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_grab_active)
-            try_mouse_ungrab(widget);
+            try_mouse_ungrab(display);
         else
             /* TODO: gtk-vnc has a weird condition here
                if (!d->grab_keyboard || !d->absolute) */
-            try_mouse_grab(widget);
+            try_mouse_grab(display);
     }
 
 
@@ -970,6 +1000,8 @@ static gboolean motion_event(GtkWidget *widget, GdkEventMotion *motion)
 
     if (!d->inputs)
         return true;
+    if (d->disable_inputs)
+        return true;
 
     gdk_drawable_get_size(gtk_widget_get_window(widget), &ww, &wh);
     if (spicex_is_scaled(display)) {
@@ -1030,6 +1062,8 @@ static gboolean scroll_event(GtkWidget *widget, GdkEventScroll *scroll)
 
     if (!d->inputs)
         return true;
+    if (d->disable_inputs)
+        return true;
 
     if (scroll->direction == GDK_SCROLL_UP)
         button = SPICE_MOUSE_BUTTON_UP;
@@ -1056,6 +1090,9 @@ static gboolean button_event(GtkWidget *widget, GdkEventButton *button)
             button->type == GDK_BUTTON_PRESS ? "press" : "release",
             button->button, button->state);
 
+    if (d->disable_inputs)
+        return true;
+
     if (!spicex_is_scaled(display)) {
         gint x, y;
 
@@ -1069,7 +1106,7 @@ static gboolean button_event(GtkWidget *widget, GdkEventButton *button)
 
     gtk_widget_grab_focus(widget);
     if (d->mouse_mode == SPICE_MOUSE_MODE_SERVER)
-        try_mouse_grab(widget);
+        try_mouse_grab(display);
     else /* allow to drag and drop between windows/displays:
             FIXME: should be multiple widget grab, but how?
             or should now the position of the other widgets?..
@@ -1227,6 +1264,23 @@ static void spice_display_class_init(SpiceDisplayClass *klass)
                               G_PARAM_READWRITE |
                               G_PARAM_CONSTRUCT |
                               G_PARAM_STATIC_STRINGS));
+
+    /**
+     * SpiceDisplay:disable-inputs:
+     *
+     * Disable all keyboard & mouse inputs.
+     *
+     * Since: 0.8
+     **/
+    g_object_class_install_property
+        (gobject_class, PROP_DISABLE_INPUTS,
+         g_param_spec_boolean("disable-inputs", "Disable inputs",
+                              "Whether inputs should be disabled",
+                              FALSE,
+                              G_PARAM_READWRITE |
+                              G_PARAM_CONSTRUCT |
+                              G_PARAM_STATIC_STRINGS));
+
     /**
      * SpiceDisplay::mouse-grab:
      * @display: the #SpiceDisplay that emitted the signal
@@ -1295,7 +1349,7 @@ static void mouse_update(SpiceChannel *channel, gpointer data)
     d->mouse_guest_x = -1;
     d->mouse_guest_y = -1;
     if (d->mouse_mode == SPICE_MOUSE_MODE_CLIENT) {
-        try_mouse_ungrab(GTK_WIDGET(display));
+        try_mouse_ungrab(display);
     }
     update_mouse_pointer(display);
 }
@@ -1646,7 +1700,7 @@ SpiceDisplay *spice_display_new(SpiceSession *session, int id)
  **/
 void spice_display_mouse_ungrab(SpiceDisplay *display)
 {
-    try_mouse_ungrab(GTK_WIDGET(display));
+    try_mouse_ungrab(display);
 }
 
 /**
@@ -1753,6 +1807,9 @@ static void sync_keyboard_lock_modifiers(SpiceDisplay *display)
     guint32 modifiers;
     GdkWindow *w;
 
+    if (d->disable_inputs)
+        return;
+
     w = gtk_widget_get_parent_window(GTK_WIDGET(display));
     if (w == NULL) /* it can happen if the display is not yet shown */
         return;
diff --git a/gtk/spicy.c b/gtk/spicy.c
index 6c05b1e..427b8d1 100644
--- a/gtk/spicy.c
+++ b/gtk/spicy.c
@@ -721,6 +721,7 @@ static const char *spice_display_properties[] = {
     "grab-mouse",
     "resize-guest",
     "scaling",
+    "disable-inputs",
 };
 
 static const char *spice_gtk_session_properties[] = {
@@ -748,6 +749,10 @@ static const GtkToggleActionEntry tentries[] = {
         .label       = N_("Scale display"),
         .callback    = G_CALLBACK(menu_cb_bool_prop),
     },{
+        .name        = "disable-inputs",
+        .label       = N_("Disable inputs"),
+        .callback    = G_CALLBACK(menu_cb_bool_prop),
+    },{
         .name        = "auto-clipboard",
         .label       = N_("Automagic clipboard sharing between host and guest"),
         .callback    = G_CALLBACK(menu_cb_bool_prop),
@@ -798,6 +803,7 @@ static char ui_xml[] =
 "      <menuitem action='grab-mouse'/>\n"
 "      <menuitem action='resize-guest'/>\n"
 "      <menuitem action='scaling'/>\n"
+"      <menuitem action='disable-inputs'/>\n"
 "      <menuitem action='auto-clipboard'/>\n"
 #ifdef USE_USBREDIR
 "      <menuitem action='auto-usbredir'/>\n"
-- 
1.7.7



More information about the Spice-devel mailing list