+ node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id);
+
+ g_assert (node != NULL); /* paranoid */
+
+ /* we should probably do the same parameter checks as g_signal_emit() here.
+ */
+ if (emission->chain_type != G_TYPE_NONE)
+ {
+ ClassClosure *cc = signal_find_class_closure (node, emission->chain_type);
+
+ g_assert (cc != NULL); /* closure currently in call stack */
+
+ n_params = node->n_params;
+ restore_type = cc->instance_type;
+ cc = signal_find_class_closure (node, g_type_parent (cc->instance_type));
+ if (cc && cc->instance_type != restore_type)
+ {
+ closure = cc->closure;
+ chain_type = cc->instance_type;
+ }
+ }
+ else
+ g_warning ("%s: signal id '%u' cannot be chained from current emission stage for instance '%p'", G_STRLOC, node->signal_id, instance);
+ }
+ else
+ g_warning ("%s: no signal is currently being emitted for instance '%p'", G_STRLOC, instance);
+
+ if (closure)
+ {
+ GValue *instance_and_params;
+ GType signal_return_type;
+ GValue *param_values;
+ va_list var_args;
+ guint i;
+
+ va_start (var_args, instance);
+
+ signal_return_type = node->return_type;
+ instance_and_params = g_alloca (sizeof (GValue) * (n_params + 1));
+ memset (instance_and_params, 0, sizeof (GValue) * (n_params + 1));
+ param_values = instance_and_params + 1;
+
+ for (i = 0; i < node->n_params; i++)
+ {
+ gchar *error;
+ GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE;
+ gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE;
+
+ SIGNAL_UNLOCK ();
+ G_VALUE_COLLECT_INIT (param_values + i, ptype,
+ var_args,
+ static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
+ &error);
+ if (error)
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* we purposely leak the value here, it might not be
+ * in a sane state if an error condition occoured
+ */
+ while (i--)
+ g_value_unset (param_values + i);
+
+ va_end (var_args);
+ return;
+ }
+ SIGNAL_LOCK ();
+ }
+
+ SIGNAL_UNLOCK ();
+ instance_and_params->g_type = 0;
+ g_value_init_from_instance (instance_and_params, instance);
+ SIGNAL_LOCK ();
+
+ emission->chain_type = chain_type;
+ SIGNAL_UNLOCK ();
+
+ if (signal_return_type == G_TYPE_NONE)
+ {
+ g_closure_invoke (closure,
+ NULL,
+ n_params + 1,
+ instance_and_params,
+ &emission->ihint);
+ }
+ else
+ {
+ GValue return_value = G_VALUE_INIT;
+ gchar *error = NULL;
+ GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE;
+ gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE;
+
+ g_value_init (&return_value, rtype);
+
+ g_closure_invoke (closure,
+ &return_value,
+ n_params + 1,
+ instance_and_params,
+ &emission->ihint);
+
+ G_VALUE_LCOPY (&return_value,
+ var_args,
+ static_scope ? G_VALUE_NOCOPY_CONTENTS : 0,
+ &error);
+ if (!error)
+ {
+ g_value_unset (&return_value);
+ }
+ else
+ {
+ g_warning ("%s: %s", G_STRLOC, error);
+ g_free (error);
+
+ /* we purposely leak the value here, it might not be
+ * in a sane state if an error condition occurred
+ */
+ }
+ }
+
+ for (i = 0; i < n_params; i++)
+ g_value_unset (param_values + i);
+ g_value_unset (instance_and_params);
+
+ va_end (var_args);
+
+ SIGNAL_LOCK ();
+ emission->chain_type = restore_type;
+ }
+ SIGNAL_UNLOCK ();
+}
+
+/**
+ * g_signal_get_invocation_hint:
+ * @instance: (type GObject.Object): the instance to query
+ *
+ * Returns the invocation hint of the innermost signal emission of instance.
+ *
+ * Returns: (transfer none): the invocation hint of the innermost signal emission.
+ */
+GSignalInvocationHint*
+g_signal_get_invocation_hint (gpointer instance)
+{
+ Emission *emission = NULL;
+
+ g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL);
+
+ SIGNAL_LOCK ();
+ emission = emission_find_innermost (instance);
+ SIGNAL_UNLOCK ();
+
+ return emission ? &emission->ihint : NULL;
+}
+
+/**
+ * g_signal_connect_closure_by_id:
+ * @instance: (type GObject.Object): the instance to connect to.
+ * @signal_id: the id of the signal.
+ * @detail: the detail.
+ * @closure: the closure to connect.
+ * @after: whether the handler should be called before or after the
+ * default handler of the signal.
+ *
+ * Connects a closure to a signal for a particular object.
+ *
+ * Returns: the handler id (always greater than 0 for successful connections)
+ */
+gulong
+g_signal_connect_closure_by_id (gpointer instance,
+ guint signal_id,
+ GQuark detail,
+ GClosure *closure,
+ gboolean after)
+{
+ SignalNode *node;
+ gulong handler_seq_no = 0;
+
+ g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0);
+ g_return_val_if_fail (signal_id > 0, 0);
+ g_return_val_if_fail (closure != NULL, 0);
+
+ SIGNAL_LOCK ();
+ node = LOOKUP_SIGNAL_NODE (signal_id);
+ if (node)
+ {
+ if (detail && !(node->flags & G_SIGNAL_DETAILED))
+ g_warning ("%s: signal id '%u' does not support detail (%u)", G_STRLOC, signal_id, detail);
+ else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype))
+ g_warning ("%s: signal id '%u' is invalid for instance '%p'", G_STRLOC, signal_id, instance);
+ else
+ {
+ Handler *handler = handler_new (after);