aboutsummaryrefslogtreecommitdiffstats
path: root/libempathy/empathy-utils.c
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2009-10-14 22:20:20 +0800
committerGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2009-10-15 00:01:28 +0800
commitc8d648fff1a1f130baab6838a4aab2c6f2162d66 (patch)
tree3d85405f1ba3e6c7759f4ee243a0794e71bb8ab2 /libempathy/empathy-utils.c
parenta99138d9d745e0269f9a9a8182f8df92dcb61bda (diff)
downloadgsoc2013-empathy-c8d648fff1a1f130baab6838a4aab2c6f2162d66.tar.gz
gsoc2013-empathy-c8d648fff1a1f130baab6838a4aab2c6f2162d66.tar.zst
gsoc2013-empathy-c8d648fff1a1f130baab6838a4aab2c6f2162d66.zip
copy empathy_signal_connect_weak from telepathy-gabble
Diffstat (limited to 'libempathy/empathy-utils.c')
-rw-r--r--libempathy/empathy-utils.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/libempathy/empathy-utils.c b/libempathy/empathy-utils.c
index 243b4b040..3b14b0028 100644
--- a/libempathy/empathy-utils.c
+++ b/libempathy/empathy-utils.c
@@ -403,3 +403,88 @@ empathy_protocol_name_to_display_name (const gchar *proto_name)
return NULL;
}
+typedef struct {
+ GObject *instance;
+ GObject *user_data;
+ gulong handler_id;
+} WeakHandlerCtx;
+
+static WeakHandlerCtx *
+whc_new (GObject *instance,
+ GObject *user_data)
+{
+ WeakHandlerCtx *ctx = g_slice_new0 (WeakHandlerCtx);
+
+ ctx->instance = instance;
+ ctx->user_data = user_data;
+
+ return ctx;
+}
+
+static void
+whc_free (WeakHandlerCtx *ctx)
+{
+ g_slice_free (WeakHandlerCtx, ctx);
+}
+
+static void user_data_destroyed_cb (gpointer, GObject *);
+
+static void
+instance_destroyed_cb (gpointer ctx_,
+ GObject *where_the_instance_was)
+{
+ WeakHandlerCtx *ctx = ctx_;
+
+ DEBUG ("instance for %p destroyed; cleaning up", ctx);
+
+ /* No need to disconnect the signal here, the instance has gone away. */
+ g_object_weak_unref (ctx->user_data, user_data_destroyed_cb, ctx);
+ whc_free (ctx);
+}
+
+static void
+user_data_destroyed_cb (gpointer ctx_,
+ GObject *where_the_user_data_was)
+{
+ WeakHandlerCtx *ctx = ctx_;
+
+ DEBUG ("user_data for %p destroyed; disconnecting", ctx);
+
+ g_signal_handler_disconnect (ctx->instance, ctx->handler_id);
+ g_object_weak_unref (ctx->instance, instance_destroyed_cb, ctx);
+ whc_free (ctx);
+}
+
+/* This function is copied from telepathy-gabble: util.c */
+/**
+ * empathy_signal_connect_weak:
+ * @instance: the instance to connect to.
+ * @detailed_signal: a string of the form "signal-name::detail".
+ * @c_handler: the GCallback to connect.
+ * @user_data: an object to pass as data to c_handler calls.
+ *
+ * Connects a #GCallback function to a signal for a particular object, as if
+ * with g_signal_connect(). Additionally, arranges for the signal handler to be
+ * disconnected if @user_data is destroyed.
+ *
+ * This is intended to be a convenient way for objects to use themselves as
+ * user_data for callbacks without having to explicitly disconnect all the
+ * handlers in their finalizers.
+ */
+void
+empathy_signal_connect_weak (gpointer instance,
+ const gchar *detailed_signal,
+ GCallback c_handler,
+ GObject *user_data)
+{
+ GObject *instance_obj = G_OBJECT (instance);
+ WeakHandlerCtx *ctx = whc_new (instance_obj, user_data);
+
+ DEBUG ("connecting to %p:%s with context %p", instance, detailed_signal, ctx);
+
+ ctx->handler_id = g_signal_connect (instance, detailed_signal, c_handler,
+ user_data);
+
+ g_object_weak_ref (instance_obj, instance_destroyed_cb, ctx);
+ g_object_weak_ref (user_data, user_data_destroyed_cb, ctx);
+}