From 43711828ce9c1c93a44f90341d4125d14564345b Mon Sep 17 00:00:00 2001
From: George Kiagiadakis <george.kiagiadakis@collabora.com>
Date: Fri, 8 May 2020 19:23:23 +0300
Subject: [PATCH] transition: add the ability to use a GClosure instead of a
 GAsyncReadyCallback

---
 lib/wp/transition.c | 56 +++++++++++++++++++++++++++++++++++++--------
 lib/wp/transition.h |  4 ++++
 2 files changed, 51 insertions(+), 9 deletions(-)

diff --git a/lib/wp/transition.c b/lib/wp/transition.c
index 71b55895..9187e349 100644
--- a/lib/wp/transition.c
+++ b/lib/wp/transition.c
@@ -42,8 +42,7 @@ struct _WpTransitionPrivate
   /* source obj & callback */
   GObject *source_object;
   GCancellable *cancellable;
-  GAsyncReadyCallback callback;
-  gpointer callback_data;
+  GClosure *closure;
 
   /* GAsyncResult tag */
   gpointer tag;
@@ -83,6 +82,7 @@ wp_transition_finalize (GObject * object)
     priv->data_destroy (priv->data);
 
   g_clear_error (&priv->error);
+  g_clear_pointer (&priv->closure, g_closure_unref);
   g_clear_object (&priv->cancellable);
   g_clear_object (&priv->source_object);
 
@@ -175,6 +175,35 @@ wp_transition_new (GType type,
     gpointer source_object, GCancellable * cancellable,
     GAsyncReadyCallback callback, gpointer callback_data)
 {
+  return wp_transition_new_closure (type, source_object, cancellable,
+      g_cclosure_new (G_CALLBACK (callback), callback_data, NULL));
+}
+
+/**
+ * wp_transition_new_closure:
+ * @type: the #GType of the #WpTransition subclass to instantiate
+ * @source_object: (nullable) (type GObject): the #GObject that owns this task,
+ *   or %NULL
+ * @cancellable: (nullable): optional #GCancellable
+ * @closure: (nullable): a #GAsyncReadyCallback wrapped in a #GClosure
+ *
+ * Creates a #WpTransition acting on @source_object. When the transition is
+ * done, @closure will be invoked.
+ *
+ * The transition does not automatically start executing steps. You must
+ * call wp_transition_advance() after creating it in order to start it.
+ *
+ * Note that the transition is automatically unref'ed after the @closure
+ * has been executed. If you wish to keep an additional reference on it,
+ * you need to ref it explicitly.
+ *
+ * Returns: (transfer none): the new transition
+ */
+WpTransition *
+wp_transition_new_closure (GType type, gpointer source_object,
+    GCancellable * cancellable, GClosure * closure)
+{
+  g_return_val_if_fail (g_type_is_a (type, WP_TYPE_TRANSITION), NULL);
   g_return_val_if_fail (G_IS_OBJECT (source_object), NULL);
 
   WpTransition *self = g_object_new (type, NULL);
@@ -182,8 +211,13 @@ wp_transition_new (GType type,
 
   priv->source_object = source_object ? g_object_ref (source_object) : NULL;
   priv->cancellable = cancellable ? g_object_ref (cancellable) : NULL;
-  priv->callback = callback;
-  priv->callback_data = callback_data;
+
+  if (closure) {
+    priv->closure = g_closure_ref (closure);
+    g_closure_sink (closure);
+    if (G_CLOSURE_NEEDS_MARSHAL (closure))
+      g_closure_set_marshal (closure, g_cclosure_marshal_VOID__OBJECT);
+  }
 
   return self;
 }
@@ -336,11 +370,15 @@ wp_transition_had_error (WpTransition * self)
 static void
 wp_transition_return (WpTransition * self, WpTransitionPrivate *priv)
 {
-  if (priv->callback) {
-      priv->callback (
-          priv->source_object ? G_OBJECT (priv->source_object) : NULL,
-          G_ASYNC_RESULT (self),
-          priv->callback_data);
+  if (priv->closure) {
+    GValue values[2] = { G_VALUE_INIT, G_VALUE_INIT };
+    g_value_init (&values[0], G_TYPE_OBJECT);
+    g_value_init (&values[1], G_TYPE_OBJECT);
+    g_value_set_object (&values[0], priv->source_object);
+    g_value_set_object (&values[1], self);
+    g_closure_invoke (priv->closure, NULL, 2, values, NULL);
+    g_value_unset (&values[0]);
+    g_value_unset (&values[1]);
   }
 
   g_object_notify (G_OBJECT (self), "completed");
diff --git a/lib/wp/transition.h b/lib/wp/transition.h
index 3f2191d1..840879da 100644
--- a/lib/wp/transition.h
+++ b/lib/wp/transition.h
@@ -55,6 +55,10 @@ WpTransition * wp_transition_new (GType type,
     gpointer source_object, GCancellable * cancellable,
     GAsyncReadyCallback callback, gpointer callback_data);
 
+WP_API
+WpTransition * wp_transition_new_closure (GType type,
+    gpointer source_object, GCancellable * cancellable, GClosure * closure);
+
 /* source object */
 
 WP_API
-- 
GitLab