[glib: 1/2] gobject: Add g_signal_group_connect_closure
- From: Philip Withnall <pwithnall src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib: 1/2] gobject: Add g_signal_group_connect_closure
- Date: Tue, 5 Apr 2022 16:32:13 +0000 (UTC)
commit 2a842b1173eaca3423e955e110227df00fecde43
Author: Jason Francis <jafrancis999 gmail com>
Date: Tue Feb 22 14:51:37 2022 -0500
gobject: Add g_signal_group_connect_closure
docs/reference/gobject/gobject-sections.txt | 1 +
gobject/gsignalgroup.c | 81 ++++++++++++++++++++---------
gobject/gsignalgroup.h | 5 ++
gobject/tests/signalgroup.c | 21 ++++++--
4 files changed, 79 insertions(+), 29 deletions(-)
---
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt
index cbab92406a..278c756104 100644
--- a/docs/reference/gobject/gobject-sections.txt
+++ b/docs/reference/gobject/gobject-sections.txt
@@ -1034,6 +1034,7 @@ g_signal_group_connect_after
g_signal_group_connect_data
g_signal_group_connect_object
g_signal_group_connect_swapped
+g_signal_group_connect_closure
g_signal_group_dup_target
g_signal_group_get_type
g_signal_group_new
diff --git a/gobject/gsignalgroup.c b/gobject/gsignalgroup.c
index 8feba543c2..01a0a12c8b 100644
--- a/gobject/gsignalgroup.c
+++ b/gobject/gsignalgroup.c
@@ -705,18 +705,28 @@ g_signal_group_new (GType target_type)
NULL);
}
-static void
-g_signal_group_connect_full (GSignalGroup *self,
- const gchar *detailed_signal,
- GCallback c_handler,
- gpointer data,
- GClosureNotify notify,
- GConnectFlags flags,
- gboolean is_object)
+/**
+ * g_signal_group_connect_closure:
+ * @self: a #GSignalGroup
+ * @detailed_signal: a string of the form `signal-name` with optional `::signal-detail`
+ * @closure: (not nullable): the closure to connect.
+ * @after: whether the handler should be called before or after the
+ * default handler of the signal.
+ *
+ * Connects @closure to the signal @detailed_signal on #GSignalGroup:target.
+ *
+ * You cannot connect a signal handler after #GSignalGroup:target has been set.
+ *
+ * Since: 2.74
+ */
+void
+g_signal_group_connect_closure (GSignalGroup *self,
+ const gchar *detailed_signal,
+ GClosure *closure,
+ gboolean after)
{
GObject *target;
SignalHandler *handler;
- GClosure *closure;
guint signal_id;
GQuark signal_detail;
@@ -724,8 +734,7 @@ g_signal_group_connect_full (GSignalGroup *self,
g_return_if_fail (detailed_signal != NULL);
g_return_if_fail (g_signal_parse_name (detailed_signal, self->target_type,
&signal_id, &signal_detail, TRUE) != 0);
- g_return_if_fail (c_handler != NULL);
- g_return_if_fail (!is_object || G_IS_OBJECT (data));
+ g_return_if_fail (closure != NULL);
g_rec_mutex_lock (&self->mutex);
@@ -736,29 +745,15 @@ g_signal_group_connect_full (GSignalGroup *self,
return;
}
- if ((flags & G_CONNECT_SWAPPED) != 0)
- closure = g_cclosure_new_swap (c_handler, data, notify);
- else
- closure = g_cclosure_new (c_handler, data, notify);
-
handler = g_slice_new0 (SignalHandler);
handler->group = self;
handler->signal_id = signal_id;
handler->signal_detail = signal_detail;
handler->closure = g_closure_ref (closure);
- handler->connect_after = ((flags & G_CONNECT_AFTER) != 0);
+ handler->connect_after = after;
g_closure_sink (closure);
- if (is_object)
- {
- /* Set closure->is_invalid when data is disposed. We only track this to avoid
- * reconnecting in the future. However, we do a round of cleanup when ever we
- * connect a new object or the target changes to GC the old handlers.
- */
- g_object_watch_closure (data, closure);
- }
-
g_ptr_array_add (self->handlers, handler);
target = g_weak_ref_get (&self->target_ref);
@@ -775,6 +770,40 @@ g_signal_group_connect_full (GSignalGroup *self,
g_rec_mutex_unlock (&self->mutex);
}
+static void
+g_signal_group_connect_full (GSignalGroup *self,
+ const gchar *detailed_signal,
+ GCallback c_handler,
+ gpointer data,
+ GClosureNotify notify,
+ GConnectFlags flags,
+ gboolean is_object)
+{
+ GClosure *closure;
+
+ g_return_if_fail (c_handler != NULL);
+ g_return_if_fail (!is_object || G_IS_OBJECT (data));
+
+ if ((flags & G_CONNECT_SWAPPED) != 0)
+ closure = g_cclosure_new_swap (c_handler, data, notify);
+ else
+ closure = g_cclosure_new (c_handler, data, notify);
+
+ if (is_object)
+ {
+ /* Set closure->is_invalid when data is disposed. We only track this to avoid
+ * reconnecting in the future. However, we do a round of cleanup when ever we
+ * connect a new object or the target changes to GC the old handlers.
+ */
+ g_object_watch_closure (data, closure);
+ }
+
+ g_signal_group_connect_closure (self,
+ detailed_signal,
+ closure,
+ (flags & G_CONNECT_AFTER) != 0);
+}
+
/**
* g_signal_group_connect_object: (skip)
* @self: a #GSignalGroup
diff --git a/gobject/gsignalgroup.h b/gobject/gsignalgroup.h
index c82a5cd4fa..ec93bdd619 100644
--- a/gobject/gsignalgroup.h
+++ b/gobject/gsignalgroup.h
@@ -59,6 +59,11 @@ GLIB_AVAILABLE_IN_2_72
void g_signal_group_block (GSignalGroup *self);
GLIB_AVAILABLE_IN_2_72
void g_signal_group_unblock (GSignalGroup *self);
+GLIB_AVAILABLE_IN_2_74
+void g_signal_group_connect_closure (GSignalGroup *self,
+ const gchar *detailed_signal,
+ GClosure *closure,
+ gboolean after);
GLIB_AVAILABLE_IN_2_72
void g_signal_group_connect_object (GSignalGroup *self,
const gchar *detailed_signal,
diff --git a/gobject/tests/signalgroup.c b/gobject/tests/signalgroup.c
index 5d1f17a813..9b82dc45f3 100644
--- a/gobject/tests/signalgroup.c
+++ b/gobject/tests/signalgroup.c
@@ -107,7 +107,7 @@ connect_after_cb (SignalTarget *target,
g_assert_true (readback == target);
g_object_unref (readback);
- g_assert_cmpint (*signal_calls, ==, 4);
+ g_assert_cmpint (*signal_calls, ==, 5);
*signal_calls += 1;
}
@@ -194,7 +194,8 @@ connect_data_weak_notify_cb (gboolean *weak_notify_called,
static void
connect_all_signals (GSignalGroup *group)
{
- GObject *object;
+ GObject *object;
+ GClosure *closure;
/* Check that these are called in the right order */
g_signal_group_connect (group,
@@ -245,6 +246,20 @@ connect_all_signals (GSignalGroup *group)
g_object_weak_ref (G_OBJECT (group),
(GWeakNotify)connect_data_weak_notify_cb,
&global_weak_notify_called);
+
+
+ /* Check that this can be called as a GClosure */
+ closure = g_cclosure_new (G_CALLBACK (connect_before_cb),
+ &global_signal_calls,
+ NULL);
+ g_signal_group_connect_closure (group, "the-signal", closure, FALSE);
+
+ /* Check that invalidated GClosures don't get called */
+ closure = g_cclosure_new (G_CALLBACK (connect_before_cb),
+ &global_signal_calls,
+ NULL);
+ g_closure_invalidate (closure);
+ g_signal_group_connect_closure (group, "the-signal", closure, FALSE);
}
static void
@@ -258,7 +273,7 @@ assert_signals (SignalTarget *target,
global_signal_calls = 0;
g_signal_emit (target, signals[THE_SIGNAL],
signal_detail_quark (), group);
- g_assert_cmpint (global_signal_calls, ==, success ? 5 : 0);
+ g_assert_cmpint (global_signal_calls, ==, success ? 6 : 0);
}
static void
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]