[Spice-devel] [PATCH spice-gtk 2/2] gtk-session: weak reference the session for clipboard cb

Marc-André Lureau marcandre.lureau at gmail.com
Wed Jan 18 06:12:54 PST 2012


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
---
 gtk/spice-gtk-session.c |   56 ++++++++++++++++++++++++++++++++++++++++------
 1 files changed, 48 insertions(+), 8 deletions(-)

diff --git a/gtk/spice-gtk-session.c b/gtk/spice-gtk-session.c
index a7357f8..f527368 100644
--- a/gtk/spice-gtk-session.c
+++ b/gtk/spice-gtk-session.c
@@ -386,23 +386,56 @@ 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)
+{
+    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 +513,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 +676,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 +748,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 +900,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)));
     }
 }
 
-- 
1.7.7.5



More information about the Spice-devel mailing list