[Spice-commits] 2 commits - gtk/spice-gtk-session.c

Marc-André Lureau elmarco at kemper.freedesktop.org
Wed Jan 18 11:40:46 PST 2012


 gtk/spice-gtk-session.c |   61 ++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 52 insertions(+), 9 deletions(-)

New commits:
commit 9baba9fd89433833cb45badfa2aa0e46a436ee8a
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Jan 18 15:09:06 2012 +0100

    gtk-session: weak reference the session for clipboard cb
    
    It seems Gtk is lacking a way to cancel a gtk_clipboard_request_*().
    
    Although it seems like gtk_selection_remove_all() would solve that
    problem, it will have nasty effect of destroying other pending
    requests from others..
    
    Let's make use of an extra weak reference object that will be nulled
    when the session is destroyed.
    
    This should help solving the follwing bug:
    https://bugzilla.redhat.com/show_bug.cgi?id=743773

diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
index a7357f8..e4a36d1 100644
--- a/gtk/spice-gtk-session.c
+++ b/gtk/spice-gtk-session.c
@@ -386,23 +386,58 @@ static const struct {
     }
 };
 
+typedef struct _WeakRef {
+    GObject *object;
+} WeakRef;
+
+static void weak_notify_cb(WeakRef *weakref, GObject *object)
+{
+    weakref->object = NULL;
+}
+
+static WeakRef* weak_ref(GObject *object)
+{
+    WeakRef *weakref = g_new(WeakRef, 1);
+
+    g_object_weak_ref(object, (GWeakNotify)weak_notify_cb, weakref);
+    weakref->object = object;
+
+    return weakref;
+}
+
+static void weak_unref(WeakRef* weakref)
+{
+    if (weakref->object)
+        g_object_weak_unref(weakref->object, (GWeakNotify)weak_notify_cb, weakref);
+
+    g_free(weakref);
+}
+
 static void clipboard_get_targets(GtkClipboard *clipboard,
                                   GdkAtom *atoms,
                                   gint n_atoms,
                                   gpointer user_data)
 {
-    g_return_if_fail(SPICE_IS_GTK_SESSION(user_data));
+    WeakRef *weakref = user_data;
+    SpiceGtkSession *self = (SpiceGtkSession*)weakref->object;
+    weak_unref(weakref);
+
+    if (self == NULL)
+        return;
+
+    g_return_if_fail(SPICE_IS_GTK_SESSION(self));
 
-    SpiceGtkSession *self = user_data;
     SpiceGtkSessionPrivate *s = self->priv;
     guint32 types[SPICE_N_ELEMENTS(atom2agent)];
     char *name;
     int a, m, t;
     int selection;
 
+    if (s->main == NULL)
+        return;
+
     selection = get_selection_from_clipboard(s, clipboard);
     g_return_if_fail(selection != -1);
-    g_return_if_fail(s->main != NULL);
 
     SPICE_DEBUG("%s:", __FUNCTION__);
     if (spice_util_get_debug()) {
@@ -480,7 +515,7 @@ static void clipboard_owner_change(GtkClipboard        *clipboard,
         s->clip_hasdata[selection] = TRUE;
         if (s->auto_clipboard_enable && !read_only(self))
             gtk_clipboard_request_targets(clipboard, clipboard_get_targets,
-                                          self);
+                                          weak_ref(G_OBJECT(self)));
         break;
     default:
         s->clip_hasdata[selection] = FALSE;
@@ -643,9 +678,15 @@ static void clipboard_received_cb(GtkClipboard *clipboard,
                                   GtkSelectionData *selection_data,
                                   gpointer user_data)
 {
-    g_return_if_fail(SPICE_IS_GTK_SESSION(user_data));
+    WeakRef *weakref = user_data;
+    SpiceGtkSession *self = (SpiceGtkSession*)weakref->object;
+    weak_unref(weakref);
+
+    if (self == NULL)
+        return;
+
+    g_return_if_fail(SPICE_IS_GTK_SESSION(self));
 
-    SpiceGtkSession *self = user_data;
     SpiceGtkSessionPrivate *s = self->priv;
     gint len = 0, m;
     guint32 type = VD_AGENT_CLIPBOARD_NONE;
@@ -709,7 +750,8 @@ static gboolean clipboard_request(SpiceMainChannel *main, guint selection,
     g_return_val_if_fail(m < SPICE_N_ELEMENTS(atom2agent), FALSE);
 
     atom = gdk_atom_intern_static_string(atom2agent[m].xatom);
-    gtk_clipboard_request_contents(cb, atom, clipboard_received_cb, self);
+    gtk_clipboard_request_contents(cb, atom, clipboard_received_cb,
+                                   weak_ref(G_OBJECT(self)));
 
     return TRUE;
 }
@@ -860,7 +902,7 @@ void spice_gtk_session_copy_to_guest(SpiceGtkSession *self)
 
     if (s->clip_hasdata[selection] && !s->clip_grabbed[selection]) {
         gtk_clipboard_request_targets(s->clipboard, clipboard_get_targets,
-                                      self);
+                                      weak_ref(G_OBJECT(self)));
     }
 }
 
commit 7986c81e98efed09c883061bc31c5f0e51bd4620
Author: Marc-André Lureau <marcandre.lureau at redhat.com>
Date:   Wed Jan 18 15:06:37 2012 +0100

    gtk-session: ignore destroy of outdated main channel
    
    This solves clipboard sharing not working with a password protected
    server, since new main channel are created for each connection
    attempt.

diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
index 32848fa..a7357f8 100644
--- a/gtk/spice-gtk-session.c
+++ b/gtk/spice-gtk-session.c
@@ -743,6 +743,7 @@ static void channel_new(SpiceSession *session, SpiceChannel *channel,
     SpiceGtkSessionPrivate *s = self->priv;
 
     if (SPICE_IS_MAIN_CHANNEL(channel)) {
+        SPICE_DEBUG("Changing main channel from %p to %p", s->main, channel);
         s->main = SPICE_MAIN_CHANNEL(channel);
         g_signal_connect(channel, "main-clipboard-selection-grab",
                          G_CALLBACK(clipboard_grab), self);
@@ -762,7 +763,7 @@ static void channel_destroy(SpiceSession *session, SpiceChannel *channel,
     SpiceGtkSessionPrivate *s = self->priv;
     guint i;
 
-    if (SPICE_IS_MAIN_CHANNEL(channel)) {
+    if (SPICE_IS_MAIN_CHANNEL(channel) && SPICE_MAIN_CHANNEL(channel) == s->main) {
         s->main = NULL;
         for (i = 0; i < CLIPBOARD_LAST; ++i) {
             if (s->clipboard_by_guest[i]) {


More information about the Spice-commits mailing list