[Spice-devel,spice-gtk,3/4] spice-gtk: hookup automount inhibiting

Submitted by Hans de Goede on June 21, 2012, 8:09 p.m.

Details

Message ID 1340309356-28960-4-git-send-email-hdegoede@redhat.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Hans de Goede June 21, 2012, 8:09 p.m.
Inhibit automounting when usb-autoredirection is active.

Note:
1) While changing the prototype for the spice_gtk_session_update_keyboard_focus
function, this patch also renames it to spice_gtk_session_update_usb_autoredir
to better reflect its function.

2) This patch changes the "do we have focus?" tracking, to tracking a list of
toplevel window ids which have requested autoredirection to be enabled
(iow which have keyboard focus). The reason for this is that sometimes multiple
spice-widgets can have focus at the same time, yes really! Sometimes (rarely,
hard to reproduce) the focus in event for one window arrives before the
focus out of the other windows.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 gtk/spice-gtk-session-priv.h |    5 ++--
 gtk/spice-gtk-session.c      |   55 ++++++++++++++++++++++++++++++++++++++----
 gtk/spice-widget.c           |   23 +++++++++++++++---
 3 files changed, 72 insertions(+), 11 deletions(-)

Patch hide | download patch | download mbox

diff --git a/gtk/spice-gtk-session-priv.h b/gtk/spice-gtk-session-priv.h
index 21a4251..6e572b8 100644
--- a/gtk/spice-gtk-session-priv.h
+++ b/gtk/spice-gtk-session-priv.h
@@ -22,8 +22,9 @@ 
 
 G_BEGIN_DECLS
 
-void spice_gtk_session_update_keyboard_focus(SpiceGtkSession *self,
-                                             gboolean state);
+void spice_gtk_session_update_usb_autoredir(SpiceGtkSession *self,
+                                            guint toplevel_window_id,
+                                            gboolean state);
 gboolean spice_gtk_session_get_read_only(SpiceGtkSession *self);
 
 G_END_DECLS
diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
index 130cbc9..89fc724 100644
--- a/gtk/spice-gtk-session.c
+++ b/gtk/spice-gtk-session.c
@@ -18,6 +18,7 @@ 
 
 #include <gtk/gtk.h>
 #include <spice/vd_agent.h>
+#include "desktop-integration.h"
 #include "spice-common.h"
 #include "spice-gtk-session.h"
 #include "spice-gtk-session-priv.h"
@@ -39,7 +40,7 @@  struct _SpiceGtkSessionPrivate {
     gboolean                clipboard_by_guest[CLIPBOARD_LAST];
     /* auto-usbredir related */
     gboolean                auto_usbredir_enable;
-    gboolean                keyboard_focus;
+    GSList                  *auto_usbredir_toplevels;
 };
 
 /**
@@ -194,6 +195,20 @@  static void spice_gtk_session_finalize(GObject *gobject)
         G_OBJECT_CLASS(spice_gtk_session_parent_class)->finalize(gobject);
 }
 
+static void inhibit_automount(gpointer data, gpointer user_data)
+{
+    SpiceDesktopIntegration *di = SPICE_DESKTOP_INTEGRATION(user_data);
+
+    spice_desktop_integration_inhibit_automount(di, GPOINTER_TO_UINT(data));
+}
+
+static void uninhibit_automount(gpointer data, gpointer user_data)
+{
+    SpiceDesktopIntegration *di = SPICE_DESKTOP_INTEGRATION(user_data);
+
+    spice_desktop_integration_uninhibit_automount(di, GPOINTER_TO_UINT(data));
+}
+
 static void spice_gtk_session_get_property(GObject    *gobject,
                                            guint       prop_id,
                                            GValue     *value,
@@ -235,13 +250,23 @@  static void spice_gtk_session_set_property(GObject      *gobject,
         break;
     case PROP_AUTO_USBREDIR:
         s->auto_usbredir_enable = g_value_get_boolean(value);
-        if (s->keyboard_focus) {
+        if (s->auto_usbredir_toplevels) {
+            SpiceDesktopIntegration *desktop_int;
             SpiceUsbDeviceManager *manager =
                 spice_usb_device_manager_get(s->session, NULL);
 
             if (!manager)
                 break;
 
+            desktop_int = spice_desktop_integration_get(s->session);
+            if (s->auto_usbredir_enable) {
+                g_slist_foreach(s->auto_usbredir_toplevels,
+                                inhibit_automount, desktop_int);
+            } else {
+                g_slist_foreach(s->auto_usbredir_toplevels,
+                                uninhibit_automount, desktop_int);
+            }
+
             g_object_set(manager, "auto-connect", s->auto_usbredir_enable,
                          NULL);
         }
@@ -837,15 +862,28 @@  static gboolean read_only(SpiceGtkSession *self)
 /* ---------------------------------------------------------------- */
 /* private functions (usbredir related)                             */
 G_GNUC_INTERNAL
-void spice_gtk_session_update_keyboard_focus(SpiceGtkSession *self,
-                                             gboolean state)
+void spice_gtk_session_update_usb_autoredir(SpiceGtkSession *self,
+                                            guint toplevel,
+                                            gboolean state)
 {
     g_return_if_fail(SPICE_IS_GTK_SESSION(self));
 
     SpiceGtkSessionPrivate *s = self->priv;
+    SpiceDesktopIntegration *desktop_int;
     SpiceUsbDeviceManager *manager;
 
-    s->keyboard_focus = state;
+    if (state) {
+        if (!g_slist_find(s->auto_usbredir_toplevels,
+                          GUINT_TO_POINTER(toplevel))) {
+            s->auto_usbredir_toplevels =
+                g_slist_prepend(s->auto_usbredir_toplevels,
+                                GUINT_TO_POINTER(toplevel));
+        }
+    } else {
+        s->auto_usbredir_toplevels =
+            g_slist_remove(s->auto_usbredir_toplevels,
+                           GUINT_TO_POINTER(toplevel));
+    }
 
     if (!s->auto_usbredir_enable)
         return;
@@ -854,6 +892,13 @@  void spice_gtk_session_update_keyboard_focus(SpiceGtkSession *self,
     if (!manager)
         return;
 
+    desktop_int = spice_desktop_integration_get(s->session);
+    if (state)
+        spice_desktop_integration_inhibit_automount(desktop_int, toplevel);
+    else
+        spice_desktop_integration_uninhibit_automount(desktop_int, toplevel);
+
+    state = s->auto_usbredir_toplevels != NULL;
     g_object_set(manager, "auto-connect", state, NULL);
 }
 
diff --git a/gtk/spice-widget.c b/gtk/spice-widget.c
index d559273..9397750 100644
--- a/gtk/spice-widget.c
+++ b/gtk/spice-widget.c
@@ -209,6 +209,23 @@  static void update_size_request(SpiceDisplay *display)
     recalc_geometry(GTK_WIDGET(display));
 }
 
+static void update_usb_autoredir(SpiceDisplay *display)
+{
+    SpiceDisplayPrivate *d = SPICE_DISPLAY_GET_PRIVATE(display);
+    guint toplevel_window_id = 0;
+#ifdef GDK_WINDOWING_X11
+    {
+        GtkWidget *toplevel = gtk_widget_get_toplevel(GTK_WIDGET(display));
+        GdkWindow *w = GDK_WINDOW(gtk_widget_get_window(toplevel));
+
+        toplevel_window_id = GDK_WINDOW_XID(w);
+    }
+#endif
+    spice_gtk_session_update_usb_autoredir(d->gtk_session,
+                                           toplevel_window_id,
+                                           d->keyboard_have_focus);
+}
+
 static void spice_display_set_property(GObject      *object,
                                        guint         prop_id,
                                        const GValue *value,
@@ -1097,8 +1114,7 @@  static gboolean focus_in_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_UN
     sync_keyboard_lock_modifiers(display);
     d->keyboard_have_focus = true;
     try_keyboard_grab(display);
-    spice_gtk_session_update_keyboard_focus(d->gtk_session,
-                                            d->keyboard_have_focus);
+    update_usb_autoredir(display);
 #ifdef WIN32
     focus_window = GDK_WINDOW_HWND(gtk_widget_get_window(widget));
     g_return_val_if_fail(focus_window != NULL, true);
@@ -1122,8 +1138,7 @@  static gboolean focus_out_event(GtkWidget *widget, GdkEventFocus *focus G_GNUC_U
 
     release_keys(display);
     d->keyboard_have_focus = false;
-    spice_gtk_session_update_keyboard_focus(d->gtk_session,
-                                            d->keyboard_have_focus);
+    update_usb_autoredir(display);
     return true;
 }