gsignal.c revision 622f01012030fcba31ee2a68920873ac06bb62e4
1ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* GObject - GLib Type, Object, Parameter and Signal Library 237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik * Copyright (C) 2000-2001 Red Hat, Inc. 3ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 4ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * This library is free software; you can redistribute it and/or 5ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * modify it under the terms of the GNU Lesser General Public 6ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * License as published by the Free Software Foundation; either 7ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * version 2 of the License, or (at your option) any later version. 8ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 9ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * This library is distributed in the hope that it will be useful, 10ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * but WITHOUT ANY WARRANTY; without even the implied warranty of 11ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Lesser General Public License for more details. 13ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 14ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * You should have received a copy of the GNU Lesser General 15ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Public License along with this library; if not, write to the 16ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Free Software Foundation, Inc., 59 Temple Place, Suite 330, 17ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Boston, MA 02111-1307, USA. 18ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 19ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * this code is based on the original GtkSignal implementation 20ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu> 21ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 225602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer 235602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer/* 245602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * MT safe 255602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer */ 265602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer 275602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "config.h" 285602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer 295602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include <string.h> 305602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include <signal.h> 315602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer 325602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "gsignal.h" 335602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "gbsearcharray.h" 345602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "gvaluecollector.h" 355602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "gvaluetypes.h" 365602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "gboxed.h" 375602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "gobject.h" 385602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "genums.h" 395602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer#include "gobjectalias.h" 405602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer 415602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer 42356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost/** 43356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * SECTION:signals 44d6d221911d8a8515bf91c9d0721025669717d6f8Matthias Clasen * @short_description: A means for customization of object behaviour 45d6d221911d8a8515bf91c9d0721025669717d6f8Matthias Clasen * and a general purpose notification mechanism 46d6d221911d8a8515bf91c9d0721025669717d6f8Matthias Clasen * @title: Signals 475602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * 485602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * The basic concept of the signal system is that of the 495602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * <emphasis>emission</emphasis> of a signal. Signals are introduced 505602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * per-type and are identified through strings. Signals introduced 515602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * for a parent type are available in derived types as well, so 525602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * basically they are a per-type facility that is inherited. A signal 535602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * emission mainly involves invocation of a certain set of callbacks 545602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * in precisely defined manner. There are two main categories of such 55d6d221911d8a8515bf91c9d0721025669717d6f8Matthias Clasen * callbacks, per-object 56d6d221911d8a8515bf91c9d0721025669717d6f8Matthias Clasen * <footnote><para>Although signals can deal with any kind of instantiatable 57d6d221911d8a8515bf91c9d0721025669717d6f8Matthias Clasen * type, i'm referring to those types as "object types" in the following, 58d6d221911d8a8515bf91c9d0721025669717d6f8Matthias Clasen * simply because that is the context most users will encounter signals in. 59d6d221911d8a8515bf91c9d0721025669717d6f8Matthias Clasen * </para></footnote> 60356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * ones and user provided ones. 61356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * The per-object callbacks are most often referred to as "object method 62356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * handler" or "default (signal) handler", while user provided callbacks are 63356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * usually just called "signal handler". 64356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * The object method handler is provided at signal creation time (this most 65356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * frequently happens at the end of an object class' creation), while user 66356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * provided handlers are frequently connected and disconnected to/from a certain 67356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * signal on certain object instances. 685602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer * 69356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * A signal emission consists of five stages, unless prematurely stopped: 70356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * <variablelist> 71356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * <varlistentry><term></term><listitem><para> 72356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 1 - Invocation of the object method handler for %G_SIGNAL_RUN_FIRST signals 73356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * </para></listitem></varlistentry> 74356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * <varlistentry><term></term><listitem><para> 75356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 2 - Invocation of normal user-provided signal handlers (<emphasis>after</emphasis> flag %FALSE) 76356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * </para></listitem></varlistentry> 77356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * <varlistentry><term></term><listitem><para> 78356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 3 - Invocation of the object method handler for %G_SIGNAL_RUN_LAST signals 79356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * </para></listitem></varlistentry> 80356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * <varlistentry><term></term><listitem><para> 81356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 4 - Invocation of user provided signal handlers, connected with an <emphasis>after</emphasis> flag of %TRUE 82356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * </para></listitem></varlistentry> 83356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * <varlistentry><term></term><listitem><para> 84356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 5 - Invocation of the object method handler for %G_SIGNAL_RUN_CLEANUP signals 85356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * </para></listitem></varlistentry> 86356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * </variablelist> 87356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * The user-provided signal handlers are called in the order they were 88356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * connected in. 89356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * All handlers may prematurely stop a signal emission, and any number of 90356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * handlers may be connected, disconnected, blocked or unblocked during 91356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * a signal emission. 92356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * There are certain criteria for skipping user handlers in stages 2 and 4 93356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * of a signal emission. 94356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * First, user handlers may be <emphasis>blocked</emphasis>, blocked handlers are omitted 95356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * during callback invocation, to return from the "blocked" state, a 96356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * handler has to get unblocked exactly the same amount of times 97356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * it has been blocked before. 98356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Second, upon emission of a %G_SIGNAL_DETAILED signal, an additional 99356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * "detail" argument passed in to g_signal_emit() has to match the detail 100356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * argument of the signal handler currently subject to invocation. 101356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Specification of no detail argument for signal handlers (omission of the 102356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * detail part of the signal specification upon connection) serves as a 103356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * wildcard and matches any detail argument passed in to emission. 104356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost */ 105ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 106ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 107160cd96ae26a571e76af717c27ae29b8125a54a5Matthias Clasen#define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org" 10822357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#ifdef G_ENABLE_DEBUG 10922357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#define IF_DEBUG(debug_type, cond) if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond) 110115366f6630596afc6f9c858ea9ea61464e92d18Tim Janikstatic volatile gpointer g_trace_instance_signals = NULL; 111115366f6630596afc6f9c858ea9ea61464e92d18Tim Janikstatic volatile gpointer g_trap_instance_signals = NULL; 11222357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik#endif /* G_ENABLE_DEBUG */ 113ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 114ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 115ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- typedefs --- */ 11683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalNode SignalNode; 11783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _SignalKey SignalKey; 11883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Emission Emission; 11983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _Handler Handler; 12083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerList HandlerList; 12183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janiktypedef struct _HandlerMatch HandlerMatch; 122ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiktypedef enum 123ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 124ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_STOP, 125ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_RUN, 126ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_HOOK, 127ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik EMISSION_RESTART 128ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} EmissionState; 129ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 130ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 131ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- prototypes --- */ 13283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline guint signal_id_lookup (GQuark quark, 13383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GType itype); 13483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic void signal_destroy_R (SignalNode *signal_node); 13583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList* handler_list_ensure (guint signal_id, 13683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance); 13783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerList* handler_list_lookup (guint signal_id, 13883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance); 13983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Handler* handler_new (gboolean after); 14083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic void handler_insert (guint signal_id, 14183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance, 14283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler); 14383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic Handler* handler_lookup (gpointer instance, 144abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik gulong handler_id, 14583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint *signal_id_p); 14683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch* handler_match_prepend (HandlerMatch *list, 14783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler, 14883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id); 14983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch* handler_match_free1_R (HandlerMatch *node, 15083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance); 15183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic HandlerMatch* handlers_find (gpointer instance, 15283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GSignalMatchType mask, 15383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id, 15483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 15583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GClosure *closure, 15683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer func, 15783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer data, 15883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gboolean one_and_only); 15983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void handler_ref (Handler *handler); 16083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void handler_unref_R (guint signal_id, 16183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance, 16283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler); 163a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic gint handler_lists_cmp (gconstpointer node1, 164a05a4b766073561baea10ba697fc7042c308719cTim Janik gconstpointer node2); 16583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void emission_push (Emission **emission_list_p, 166a05a4b766073561baea10ba697fc7042c308719cTim Janik Emission *emission); 16783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline void emission_pop (Emission **emission_list_p, 168a05a4b766073561baea10ba697fc7042c308719cTim Janik Emission *emission); 16983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline Emission* emission_find (Emission *emission_list, 17083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id, 17183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 17283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance); 173a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic gint class_closures_cmp (gconstpointer node1, 174a05a4b766073561baea10ba697fc7042c308719cTim Janik gconstpointer node2); 17545fb71949a0c0e27fe8d0948b345334f61a5c924Tim Janikstatic gint signal_key_cmp (gconstpointer node1, 17645fb71949a0c0e27fe8d0948b345334f61a5c924Tim Janik gconstpointer node2); 177e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janikstatic gboolean signal_emit_unlocked_R (SignalNode *node, 17883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 17983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance, 18083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GValue *return_value, 18183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik const GValue *instance_and_params); 182116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylorstatic const gchar * type_debug_name (GType type); 183ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 184ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 185ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- structures --- */ 186617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janiktypedef struct 187617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 188617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GSignalAccumulator func; 189617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gpointer data; 190617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} SignalAccumulator; 1919490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janiktypedef struct 1929490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik{ 1939490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik GHook hook; 1949490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik GQuark detail; 1959490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik} SignalHook; 1969490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik#define SIGNAL_HOOK(hook) ((SignalHook*) (hook)) 1979490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik 198ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalNode 199ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 200ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* permanent portion */ 201ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 202ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype; 2038161643a39772e9283f95811c18ac19901e17c65Matthias Clasen const gchar *name; 204ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint destroyed : 1; 205ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 206ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* reinitializable portion */ 207779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik guint test_class_offset : 12; 208ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint flags : 8; 209ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint n_params : 8; 210bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik GType *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */ 211bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */ 212a05a4b766073561baea10ba697fc7042c308719cTim Janik GBSearchArray *class_closure_bsa; 213617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalAccumulator *accumulator; 214ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalCMarshaller c_marshaller; 215ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GHookList *emission_hooks; 216ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 217779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik#define MAX_TEST_CLASS_OFFSET (4096) /* 2^12, 12 bits for test_class_offset */ 218779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik#define TEST_CLASS_MAGIC (1) /* indicates NULL class closure, candidate for NOP optimization */ 219ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 220ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _SignalKey 221ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 222ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype; 223ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GQuark quark; 224ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 225ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 226ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 227ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Emission 228ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 229a05a4b766073561baea10ba697fc7042c308719cTim Janik Emission *next; 230a05a4b766073561baea10ba697fc7042c308719cTim Janik gpointer instance; 231a05a4b766073561baea10ba697fc7042c308719cTim Janik GSignalInvocationHint ihint; 232a05a4b766073561baea10ba697fc7042c308719cTim Janik EmissionState state; 233a05a4b766073561baea10ba697fc7042c308719cTim Janik GType chain_type; 234ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 235ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 236ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _HandlerList 237ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 238ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 239ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handlers; 240ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *tail_before; /* normal signal handlers are appended here */ 241ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *tail_after; /* CONNECT_AFTER handlers are appended here */ 242ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 243abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik 244ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstruct _Handler 245ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 246830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik gulong sequential_number; 247f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik Handler *next; 248f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik Handler *prev; 249f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik GQuark detail; 250ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint ref_count; 251ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint block_count : 16; 252ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define HANDLER_MAX_BLOCK_COUNT (1 << 16) 25383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint after : 1; 25483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GClosure *closure; 25583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik}; 25683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstruct _HandlerMatch 2570cba1b531d5d28890fa4f48359d4e7adacf2a603Tim Janik{ 25883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler; 259ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerMatch *next; 260a05a4b766073561baea10ba697fc7042c308719cTim Janik guint signal_id; 261a05a4b766073561baea10ba697fc7042c308719cTim Janik}; 262a05a4b766073561baea10ba697fc7042c308719cTim Janik 263a05a4b766073561baea10ba697fc7042c308719cTim Janiktypedef struct 264a05a4b766073561baea10ba697fc7042c308719cTim Janik{ 265a05a4b766073561baea10ba697fc7042c308719cTim Janik GType instance_type; /* 0 for default closure */ 266ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GClosure *closure; 267ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} ClassClosure; 268a05a4b766073561baea10ba697fc7042c308719cTim Janik 2696d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik 2706d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik/* --- variables --- */ 2716d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janikstatic GBSearchArray *g_signal_key_bsa = NULL; 2726d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janikstatic const GBSearchConfig g_signal_key_bconfig = { 2736d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik sizeof (SignalKey), 2746d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik signal_key_cmp, 2756d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik G_BSEARCH_ARRAY_ALIGN_POWER2, 2766d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik}; 2776d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janikstatic GBSearchConfig g_signal_hlbsa_bconfig = { 2786d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik sizeof (HandlerList), 2796d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik handler_lists_cmp, 2806d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik 0, 2816d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik}; 2826d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janikstatic GBSearchConfig g_class_closure_bconfig = { 2836d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik sizeof (ClassClosure), 284ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik class_closures_cmp, 285ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 0, 286ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik}; 287abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikstatic GHashTable *g_handler_list_bsa_ht = NULL; 288ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Emission *g_recursive_emissions = NULL; 2899369e1e022978100c521634a968968a901dd934cTim Janikstatic Emission *g_restart_emissions = NULL; 2909369e1e022978100c521634a968968a901dd934cTim Janikstatic gulong g_handler_sequential_number = 1; 291ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikG_LOCK_DEFINE_STATIC (g_signal_mutex); 292ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define SIGNAL_LOCK() G_LOCK (g_signal_mutex) 293ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#define SIGNAL_UNLOCK() G_UNLOCK (g_signal_mutex) 294ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 295ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 296ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- signal nodes --- */ 297ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic guint g_n_signal_nodes = 0; 298ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic SignalNode **g_signal_nodes = NULL; 299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 300ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline SignalNode* 301ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikLOOKUP_SIGNAL_NODE (register guint signal_id) 302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 303ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (signal_id < g_n_signal_nodes) 304ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return g_signal_nodes[signal_id]; 305ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 306ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return NULL; 307ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 308ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 309ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 310ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/* --- functions --- */ 311ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline guint 312e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janiksignal_id_lookup (GQuark quark, 313e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GType itype) 314e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 315e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GType *ifaces, type = itype; 316e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalKey key; 317e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint n_ifaces; 318160cd96ae26a571e76af717c27ae29b8125a54a5Matthias Clasen 3198a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik key.quark = quark; 3208a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik 321e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* try looking up signals for this type and its ancestors */ 3228a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik do 323e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 324a05a4b766073561baea10ba697fc7042c308719cTim Janik SignalKey *signal_key; 3258a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik 3268a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik key.itype = type; 3278a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key); 3288a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik 329e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_key) 3308a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik return signal_key->signal_id; 331e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 332e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik type = g_type_parent (type); 333e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 334e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik while (type); 335e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 336e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* no luck, try interfaces it exports */ 337e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik ifaces = g_type_interfaces (itype, &n_ifaces); 338e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik while (n_ifaces--) 339e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 340a05a4b766073561baea10ba697fc7042c308719cTim Janik SignalKey *signal_key; 341e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 342e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik key.itype = ifaces[n_ifaces]; 343e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key); 344e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 345e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_key) 346e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 347e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (ifaces); 348e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return signal_key->signal_id; 349ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 3508a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik } 351ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (ifaces); 352ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 353ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return 0; 354a05a4b766073561baea10ba697fc7042c308719cTim Janik} 355a05a4b766073561baea10ba697fc7042c308719cTim Janik 356a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic gint 357a05a4b766073561baea10ba697fc7042c308719cTim Janikclass_closures_cmp (gconstpointer node1, 358a05a4b766073561baea10ba697fc7042c308719cTim Janik gconstpointer node2) 359a05a4b766073561baea10ba697fc7042c308719cTim Janik{ 360a05a4b766073561baea10ba697fc7042c308719cTim Janik const ClassClosure *c1 = node1, *c2 = node2; 361a05a4b766073561baea10ba697fc7042c308719cTim Janik 362a05a4b766073561baea10ba697fc7042c308719cTim Janik return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type); 363ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 364ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 365ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic gint 366ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lists_cmp (gconstpointer node1, 367ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gconstpointer node2) 368ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 369ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik const HandlerList *hlist1 = node1, *hlist2 = node2; 370ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 371ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id); 372ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 373ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 374ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList* 375ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_ensure (guint signal_id, 376ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance) 377ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 378a05a4b766073561baea10ba697fc7042c308719cTim Janik GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 379ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList key; 380ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3816d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik key.signal_id = signal_id; 3826d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik key.handlers = NULL; 383ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.tail_before = NULL; 384ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.tail_after = NULL; 385a05a4b766073561baea10ba697fc7042c308719cTim Janik if (!hlbsa) 386a05a4b766073561baea10ba697fc7042c308719cTim Janik { 387a05a4b766073561baea10ba697fc7042c308719cTim Janik hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig); 388a05a4b766073561baea10ba697fc7042c308719cTim Janik hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key); 3896d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa); 390a05a4b766073561baea10ba697fc7042c308719cTim Janik } 391a05a4b766073561baea10ba697fc7042c308719cTim Janik else 392a05a4b766073561baea10ba697fc7042c308719cTim Janik { 393a05a4b766073561baea10ba697fc7042c308719cTim Janik GBSearchArray *o = hlbsa; 394ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 395ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlbsa = g_bsearch_array_insert (o, &g_signal_hlbsa_bconfig, &key); 396ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (hlbsa != o) 397ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa); 398ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 399ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key); 400ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 401ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 402ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline HandlerList* 403ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_list_lookup (guint signal_id, 404ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance) 405a05a4b766073561baea10ba697fc7042c308719cTim Janik{ 406ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 407ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList key; 408ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 409ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.signal_id = signal_id; 410abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik 411ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL; 412ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 413ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 414ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic Handler* 415ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_lookup (gpointer instance, 416ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gulong handler_id, 417ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint *signal_id_p) 418ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 419ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 420ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 421a05a4b766073561baea10ba697fc7042c308719cTim Janik if (hlbsa) 422ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 423ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint i; 424ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 425abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik for (i = 0; i < hlbsa->n_nodes; i++) 426ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 427ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); 428ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler; 429ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 430ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (handler = hlist->handlers; handler; handler = handler->next) 431ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->sequential_number == handler_id) 432ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 433ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (signal_id_p) 434ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *signal_id_p = hlist->signal_id; 435ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 436ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return handler; 437ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 43883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 43983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 44083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 44183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return NULL; 44283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik} 44383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 44483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic inline HandlerMatch* 4450cba1b531d5d28890fa4f48359d4e7adacf2a603Tim Janikhandler_match_prepend (HandlerMatch *list, 44683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik Handler *handler, 44783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id) 4480cba1b531d5d28890fa4f48359d4e7adacf2a603Tim Janik{ 44983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *node; 45083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 45183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik node = g_slice_new (HandlerMatch); 45283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik node->handler = handler; 45383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik node->next = list; 45483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik node->signal_id = signal_id; 45583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik handler_ref (handler); 45683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 45783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return node; 45883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik} 4590cba1b531d5d28890fa4f48359d4e7adacf2a603Tim Janikstatic inline HandlerMatch* 4600cba1b531d5d28890fa4f48359d4e7adacf2a603Tim Janikhandler_match_free1_R (HandlerMatch *node, 46183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer instance) 46283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik{ 46383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik HandlerMatch *next = node->next; 46483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 46583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik handler_unref_R (node->signal_id, instance, node->handler); 46683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_slice_free (HandlerMatch, node); 46783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 46883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return next; 46983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik} 47083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 47183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikstatic HandlerMatch* 47283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikhandlers_find (gpointer instance, 47383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GSignalMatchType mask, 474ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id, 47583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GQuark detail, 47683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GClosure *closure, 477ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer func, 478ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer data, 479ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gboolean one_and_only) 480ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 481790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee HandlerMatch *mlist = NULL; 482ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 48355ec7f32a6852dba73abb29e650615b66b065ef9Tim Janik if (mask & G_SIGNAL_MATCH_ID) 484ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 485ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist = handler_list_lookup (signal_id, instance); 486ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler; 487ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node = NULL; 488ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 48983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (mask & G_SIGNAL_MATCH_FUNC) 490ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 491f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 492f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik if (!node || !node->c_marshaller) 493f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik return NULL; 494f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik } 495f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik 496f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik mask = ~mask; 497f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) 498f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik if (handler->sequential_number && 499f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && 500f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && 501f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && 502f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && 503f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && 504f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik handler->closure->meta_marshal == 0 && 505ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ((GCClosure*) handler->closure)->callback == func))) 506ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 507ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik mlist = handler_match_prepend (mlist, handler, signal_id); 508ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (one_and_only) 509ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return mlist; 510ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 511ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 512ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 513ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 514ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 515ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 516ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik mask = ~mask; 517a05a4b766073561baea10ba697fc7042c308719cTim Janik if (hlbsa) 518790a7bd3be608d9b12a18711d4400490d96b2a46Elliot Lee { 519ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint i; 520ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 521ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (i = 0; i < hlbsa->n_nodes; i++) 522ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 523ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); 524ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node = NULL; 525ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler; 526ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 52783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik if (!(mask & G_SIGNAL_MATCH_FUNC)) 528ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 529f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik node = LOOKUP_SIGNAL_NODE (hlist->signal_id); 530f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik if (!node->c_marshaller) 531f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik continue; 532f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik } 533f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik 534f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik for (handler = hlist->handlers; handler; handler = handler->next) 535f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik if (handler->sequential_number && 536f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && 537f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && 538f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && 539f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && 540f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && 541f0cfc267ba9d4366679fd485f363f9130433ef2eTim Janik handler->closure->meta_marshal == 0 && 542ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ((GCClosure*) handler->closure)->callback == func))) 543ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 544ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik mlist = handler_match_prepend (mlist, handler, hlist->signal_id); 545ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (one_and_only) 54683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return mlist; 547ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 548ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 549ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 550ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 551ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 5520cba1b531d5d28890fa4f48359d4e7adacf2a603Tim Janik return mlist; 553ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 554abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik 555ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Handler* 556ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_new (gboolean after) 557ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 558abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik Handler *handler = g_slice_new (Handler); 559ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifndef G_DISABLE_CHECKS 560ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (g_handler_sequential_number < 1) 561830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG); 562ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif 563ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 564ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->sequential_number = g_handler_sequential_number++; 565ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->prev = NULL; 566ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->next = NULL; 567ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->detail = 0; 568ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->ref_count = 1; 569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->block_count = 0; 570ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->after = after != FALSE; 571ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->closure = NULL; 572ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return handler; 574ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 5757afe2bb07a5ab089083d4193f4a1b0bc1591f282Dan Winship 576ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline void 577ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_ref (Handler *handler) 578ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 579ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (handler->ref_count > 0); 580ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 581ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_atomic_int_inc ((int *)&handler->ref_count); 582ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 58339ea11ce6b107bf3969a2f94807675b458a5a887Matthias Clasen 58439ea11ce6b107bf3969a2f94807675b458a5a887Matthias Clasenstatic inline void 585ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikhandler_unref_R (guint signal_id, 586ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance, 5877afe2bb07a5ab089083d4193f4a1b0bc1591f282Dan Winship Handler *handler) 58839ea11ce6b107bf3969a2f94807675b458a5a887Matthias Clasen{ 58939ea11ce6b107bf3969a2f94807675b458a5a887Matthias Clasen gboolean is_zero; 590ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 591ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (handler->ref_count > 0); 592ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 593c77ae3942c7412031383595ef2aef94674ba9553handler->prev) /* watch out for g_signal_handlers_destroy()! */ is_zero = g_atomic_int_dec_and_test ((int *)&handler->ref_count); 594ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 595ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (G_UNLIKELY (is_zero)) 596ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 597c77ae3942c7412031383595ef2aef94674ba9553signal_id, instance); HandlerList *hlist = NULL; 598ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 599ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->next) 600c77ae3942c7412031383595ef2aef94674ba9553instance) handler->next->prev = handler->prev; 601c77ae3942c7412031383595ef2aef94674ba9553!handler->after && (!handler->next || handler->next->after)) if (handler->prev) /* watch out for g_signal_handlers_destroy()! */ 602c77ae3942c7412031383595ef2aef94674ba9553!hlist) handler->prev->next = handler->next; 603c77ae3942c7412031383595ef2aef94674ba9553signal_id, instance); else 604c77ae3942c7412031383595ef2aef94674ba9553hlist) { 605c77ae3942c7412031383595ef2aef94674ba9553hlist->tail_before == handler); /* paranoid */ hlist = handler_list_lookup (signal_id, instance); 606c77ae3942c7412031383595ef2aef94674ba9553!handler->next) hlist->handlers = handler->next; 607c77ae3942c7412031383595ef2aef94674ba9553!hlist) } 608c77ae3942c7412031383595ef2aef94674ba9553signal_id, instance); 609c77ae3942c7412031383595ef2aef94674ba9553hlist) if (instance) 610c77ae3942c7412031383595ef2aef94674ba9553hlist->tail_after == handler); /* paranoid */ { 6119369e1e022978100c521634a968968a901dd934cTim Janik /* check if we are removing the handler pointed to by tail_before */ 612ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!handler->after && (!handler->next || handler->next->after)) 6139369e1e022978100c521634a968968a901dd934cTim Janik { 6140cba1b531d5d28890fa4f48359d4e7adacf2a603Tim Janik if (!hlist) 615ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlist = handler_list_lookup (signal_id, instance); 616ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (hlist) 617ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 618ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_assert (hlist->tail_before == handler); /* paranoid */ 619ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlist->tail_before = handler->prev; 620ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 621ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 622ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 623ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* check if we are removing the handler pointed to by tail_after */ 624ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!handler->next) 625e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 626ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!hlist) 627ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hlist = handler_list_lookup (signal_id, instance); 628ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (hlist) 629ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 630ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_assert (hlist->tail_after == handler); /* paranoid */ 631c77ae3942c7412031383595ef2aef94674ba9553!handler->after) hlist->tail_after = handler->prev; 632c77ae3942c7412031383595ef2aef94674ba9553handler->after) } 633ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 634ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 635ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 636c77ae3942c7412031383595ef2aef94674ba9553hlist->tail_before) SIGNAL_UNLOCK (); 637c77ae3942c7412031383595ef2aef94674ba9553handler->next) g_closure_unref (handler->closure); 638c77ae3942c7412031383595ef2aef94674ba9553handler->next) SIGNAL_LOCK (); 639ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_slice_free (Handler, handler); 640c77ae3942c7412031383595ef2aef94674ba9553!handler->next) } 641ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 642ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 643ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic void 644a05a4b766073561baea10ba697fc7042c308719cTim Janikhandler_insert (guint signal_id, 645a05a4b766073561baea10ba697fc7042c308719cTim Janik gpointer instance, 646a05a4b766073561baea10ba697fc7042c308719cTim Janik Handler *handler) 647ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 648ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik HandlerList *hlist; 649ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 650ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */ 651ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 652a05a4b766073561baea10ba697fc7042c308719cTim Janik hlist = handler_list_ensure (signal_id, instance); 653a05a4b766073561baea10ba697fc7042c308719cTim Janik if (!hlist->handlers) 654ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 655a05a4b766073561baea10ba697fc7042c308719cTim Janik hlist->handlers = handler; 656a05a4b766073561baea10ba697fc7042c308719cTim Janik if (!handler->after) 657a05a4b766073561baea10ba697fc7042c308719cTim Janik hlist->tail_before = handler; 658a05a4b766073561baea10ba697fc7042c308719cTim Janik } 659a05a4b766073561baea10ba697fc7042c308719cTim Janik else if (handler->after) 660a05a4b766073561baea10ba697fc7042c308719cTim Janik { 661a05a4b766073561baea10ba697fc7042c308719cTim Janik handler->prev = hlist->tail_after; 662a05a4b766073561baea10ba697fc7042c308719cTim Janik hlist->tail_after->next = handler; 663a05a4b766073561baea10ba697fc7042c308719cTim Janik } 664a05a4b766073561baea10ba697fc7042c308719cTim Janik else 665a05a4b766073561baea10ba697fc7042c308719cTim Janik { 666a05a4b766073561baea10ba697fc7042c308719cTim Janik if (hlist->tail_before) 667ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 668ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->next = hlist->tail_before->next; 669ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->next) 670ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->next->prev = handler; 671ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->prev = hlist->tail_before; 672830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik hlist->tail_before->next = handler; 673ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 674ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else /* insert !after handler into a list of only after handlers */ 675ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 676ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->next = hlist->handlers; 677ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->next) 678830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler->next->prev = handler; 679a05a4b766073561baea10ba697fc7042c308719cTim Janik hlist->handlers = handler; 680a05a4b766073561baea10ba697fc7042c308719cTim Janik } 681a05a4b766073561baea10ba697fc7042c308719cTim Janik hlist->tail_before = handler; 682a05a4b766073561baea10ba697fc7042c308719cTim Janik } 683a05a4b766073561baea10ba697fc7042c308719cTim Janik 684a05a4b766073561baea10ba697fc7042c308719cTim Janik if (!handler->next) 685a05a4b766073561baea10ba697fc7042c308719cTim Janik hlist->tail_after = handler; 68669c000f069ae934760678577506495fed061d9e4Tim Janik} 687a05a4b766073561baea10ba697fc7042c308719cTim Janik 68869c000f069ae934760678577506495fed061d9e4Tim Janikstatic inline void 689a05a4b766073561baea10ba697fc7042c308719cTim Janikemission_push (Emission **emission_list_p, 69069c000f069ae934760678577506495fed061d9e4Tim Janik Emission *emission) 691a05a4b766073561baea10ba697fc7042c308719cTim Janik{ 69269c000f069ae934760678577506495fed061d9e4Tim Janik emission->next = *emission_list_p; 69369c000f069ae934760678577506495fed061d9e4Tim Janik *emission_list_p = emission; 69469c000f069ae934760678577506495fed061d9e4Tim Janik} 69569c000f069ae934760678577506495fed061d9e4Tim Janik 69669c000f069ae934760678577506495fed061d9e4Tim Janikstatic inline void 69769c000f069ae934760678577506495fed061d9e4Tim Janikemission_pop (Emission **emission_list_p, 69869c000f069ae934760678577506495fed061d9e4Tim Janik Emission *emission) 69969c000f069ae934760678577506495fed061d9e4Tim Janik{ 70069c000f069ae934760678577506495fed061d9e4Tim Janik Emission *node, *last = NULL; 70169c000f069ae934760678577506495fed061d9e4Tim Janik 70269c000f069ae934760678577506495fed061d9e4Tim Janik for (node = *emission_list_p; node; last = node, node = last->next) 70369c000f069ae934760678577506495fed061d9e4Tim Janik if (node == emission) 70469c000f069ae934760678577506495fed061d9e4Tim Janik { 70569c000f069ae934760678577506495fed061d9e4Tim Janik if (last) 70669c000f069ae934760678577506495fed061d9e4Tim Janik last->next = node->next; 70769c000f069ae934760678577506495fed061d9e4Tim Janik else 708ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik *emission_list_p = node->next; 709ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return; 710ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 711ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_assert_not_reached (); 712ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 713ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 714ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikstatic inline Emission* 715ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_find (Emission *emission_list, 716ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id, 717ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GQuark detail, 718ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance) 719ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 720ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Emission *emission; 721ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 722ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (emission = emission_list; emission; emission = emission->next) 723465c7d1ead296b70b8d47ca333554a18f71da11dMatthias Clasen if (emission->instance == instance && 724ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission->ihint.signal_id == signal_id && 7259369e1e022978100c521634a968968a901dd934cTim Janik emission->ihint.detail == detail) 726ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return emission; 727ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return NULL; 728ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 729ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 7306d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janikstatic inline Emission* 731ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikemission_find_innermost (gpointer instance) 732ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 733ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Emission *emission, *s = NULL, *c = NULL; 734ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 735ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (emission = g_restart_emissions; emission; emission = emission->next) 736ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission->instance == instance) 7379369e1e022978100c521634a968968a901dd934cTim Janik { 738ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik s = emission; 739ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik break; 740ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 7413cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik for (emission = g_recursive_emissions; emission; emission = emission->next) 742ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission->instance == instance) 743ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 744ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik c = emission; 7459369e1e022978100c521634a968968a901dd934cTim Janik break; 74683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 747ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!s) 748ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return c; 749ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (!c) 750ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return s; 751ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 752ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return G_HAVE_GROWING_STACK ? MAX (c, s) : MIN (c, s); 753ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 754ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 755116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylorstatic gint 756ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janiksignal_key_cmp (gconstpointer node1, 757cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gconstpointer node2) 758ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 759ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik const SignalKey *key1 = node1, *key2 = node2; 7609369e1e022978100c521634a968968a901dd934cTim Janik 761ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (key1->itype == key2->itype) 762ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark); 763356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost else 764356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype); 765356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost} 766356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 767356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostvoid 7686347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Nattererg_signal_init (void) 769356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 7706347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer SIGNAL_LOCK (); 771356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (!g_n_signal_nodes) 7726347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer { 773356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */ 7746347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL); 775356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig); 776356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 777ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* invalid (0) signal_id */ 778ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_n_signal_nodes = 1; 779830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); 780830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_signal_nodes[0] = NULL; 781ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 782ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 783ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 784ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 785ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 786ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik_g_signals_destroy (GType itype) 7879369e1e022978100c521634a968968a901dd934cTim Janik{ 788ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint i; 789830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 790830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik SIGNAL_LOCK (); 791830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik for (i = 1; i < g_n_signal_nodes; i++) 7929369e1e022978100c521634a968968a901dd934cTim Janik { 793830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik SignalNode *node = g_signal_nodes[i]; 794830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 795e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->itype == itype) 796ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 797ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->destroyed) 798830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed", 799ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->name, 800ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik type_debug_name (node->itype)); 801ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 802a05a4b766073561baea10ba697fc7042c308719cTim Janik signal_destroy_R (node); 803ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 804ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 805a05a4b766073561baea10ba697fc7042c308719cTim Janik SIGNAL_UNLOCK (); 806a05a4b766073561baea10ba697fc7042c308719cTim Janik} 807ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 808ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/** 809ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * g_signal_stop_emission: 810ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @instance: the object whose signal handlers you wish to stop. 811ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @signal_id: the signal identifier, as returned by g_signal_lookup(). 812ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @detail: the detail which the signal was emitted with. 813ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 8149369e1e022978100c521634a968968a901dd934cTim Janik * Stops a signal's current emission. 815ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 816ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * This will prevent the default method from running, if the signal was 817617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * %G_SIGNAL_RUN_LAST and you connected normally (i.e. without the "after" 818617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * flag). 819617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * 820617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * Prints a warning if used on a signal which isn't being emitted. 821617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik */ 822617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikvoid 823617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikg_signal_stop_emission (gpointer instance, 824617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik guint signal_id, 825617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GQuark detail) 8269369e1e022978100c521634a968968a901dd934cTim Janik{ 827617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalNode *node; 8289369e1e022978100c521634a968968a901dd934cTim Janik 829617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 830617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_return_if_fail (signal_id > 0); 831617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 832356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_LOCK (); 833356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node = LOOKUP_SIGNAL_NODE (signal_id); 834356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (node && detail && !(node->flags & G_SIGNAL_DETAILED)) 835356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 836356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 837356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 838356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost return; 8396347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer } 840356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 841356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 842356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; 8436347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer Emission *emission = emission_find (emission_list, signal_id, detail, instance); 844356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 845356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (emission) 846abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik { 847617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (emission->state == EMISSION_HOOK) 848617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", 849617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->name, instance); 850617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik else if (emission->state == EMISSION_RUN) 851617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission->state = EMISSION_STOP; 852617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 853abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik else 854617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", 855617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->name, instance); 8569490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik } 857617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik else 858617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 859617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SIGNAL_UNLOCK (); 860617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} 8619369e1e022978100c521634a968968a901dd934cTim Janik 862617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janikstatic void 863ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasensignal_finalize_hook (GHookList *hook_list, 864617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GHook *hook) 865617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 8669369e1e022978100c521634a968968a901dd934cTim Janik GDestroyNotify destroy = hook->destroy; 867617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 868617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (destroy) 869ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen { 870ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen hook->destroy = NULL; 871ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen SIGNAL_UNLOCK (); 872ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen destroy (hook->data); 873ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen SIGNAL_LOCK (); 874ca4e2341135a8212ba45f2b3091f6f3cd9302b24Matthias Clasen } 875617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} 876617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 877617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik/** 8789369e1e022978100c521634a968968a901dd934cTim Janik * g_signal_add_emission_hook: 879617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @signal_id: the signal identifier, as returned by g_signal_lookup(). 880617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @detail: the detail on which to call the hook. 881617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @hook_func: a #GSignalEmissionHook function. 882617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @hook_data: user data for @hook_func. 883617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @data_destroy: a #GDestroyNotify for @hook_data. 8849490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik * 885617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * Adds an emission hook for a signal, which will get called for any emission 886617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * of that signal, independent of the instance. This is possible only 887617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * for signals which don't have #G_SIGNAL_NO_HOOKS flag set. 888617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * 889738c1cfd6bc87a410324209e8e96f76f90ada720Erwann Chenede * Returns: the hook id, for later use with g_signal_remove_emission_hook(). 890617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik */ 8919490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janikgulong 8929490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janikg_signal_add_emission_hook (guint signal_id, 893617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GQuark detail, 894617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GSignalEmissionHook hook_func, 895617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik gpointer hook_data, 8969369e1e022978100c521634a968968a901dd934cTim Janik GDestroyNotify data_destroy) 897617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 898617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik static gulong seq_hook_id = 1; 899617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalNode *node; 900617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GHook *hook; 901356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SignalHook *signal_hook; 902356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 903356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_return_val_if_fail (signal_id > 0, 0); 9046347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_return_val_if_fail (hook_func != NULL, 0); 905356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 9066347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer SIGNAL_LOCK (); 907356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node = LOOKUP_SIGNAL_NODE (signal_id); 908356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (!node || node->destroyed) 909617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 910abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); 911abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik SIGNAL_UNLOCK (); 912617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return 0; 913617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 914617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (node->flags & G_SIGNAL_NO_HOOKS) 915617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 916617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning ("%s: signal id `%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id); 917617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SIGNAL_UNLOCK (); 9189369e1e022978100c521634a968968a901dd934cTim Janik return 0; 919617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 920617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 921617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 922617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 923abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik SIGNAL_UNLOCK (); 9249369e1e022978100c521634a968968a901dd934cTim Janik return 0; 925617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 926617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (!node->emission_hooks) 9273cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik { 9283cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik node->emission_hooks = g_new (GHookList, 1); 9293cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_hook_list_init (node->emission_hooks, sizeof (SignalHook)); 9303cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik node->emission_hooks->finalize_hook = signal_finalize_hook; 9313cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik } 9323cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik hook = g_hook_alloc (node->emission_hooks); 9333cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik hook->data = hook_data; 9343cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik hook->func = (gpointer) hook_func; 9353cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik hook->destroy = data_destroy; 9363cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal_hook = SIGNAL_HOOK (hook); 9373cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal_hook->detail = detail; 9383cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik node->emission_hooks->seq_id = seq_hook_id; 9393cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_hook_append (node->emission_hooks, hook); 9403cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik seq_hook_id = node->emission_hooks->seq_id; 9413cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik SIGNAL_UNLOCK (); 9423cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 9433cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik return hook->hook_id; 9443cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik} 9453cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 9463cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik/** 9473cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik * g_signal_remove_emission_hook: 9483cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik * @signal_id: the id of the signal 9493cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik * @hook_id: the id of the emission hook, as returned by 9503cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik * g_signal_add_emission_hook() 9513cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik * 9523cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik * Deletes an emission hook. 9533cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik */ 9543cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikvoid 9553cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janikg_signal_remove_emission_hook (guint signal_id, 9563cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik gulong hook_id) 9573cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik{ 9583cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik SignalNode *node; 9593cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 9603cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_return_if_fail (signal_id > 0); 9613cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_return_if_fail (hook_id > 0); 9623cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 9633cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik SIGNAL_LOCK (); 9643cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 9653cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik if (!node || node->destroyed) 9663cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); 9673cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id)) 9683cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id); 9693cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik SIGNAL_UNLOCK (); 9703cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik} 971356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 972356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Koststatic inline guint 973356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostsignal_parse_name (const gchar *name, 974356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GType itype, 975356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GQuark *detail_p, 976356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost gboolean force_quark) 977356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 9786347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer const gchar *colon = strchr (name, ':'); 979356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost guint signal_id; 980356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 9816347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer if (!colon) 982356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 983356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_id = signal_id_lookup (g_quark_try_string (name), itype); 9843cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik if (signal_id && detail_p) 9853cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik *detail_p = 0; 9863cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik } 9873cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik else if (colon[1] == ':') 9883cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik { 9893cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik gchar buffer[32]; 9903cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik guint l = colon - name; 99137e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik 9923cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik if (l < 32) 9933cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik { 99483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik memcpy (buffer, name, l); 9953cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik buffer[l] = 0; 9963cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik signal_id = signal_id_lookup (g_quark_try_string (buffer), itype); 99783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 9989369e1e022978100c521634a968968a901dd934cTim Janik else 9993cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik { 10009369e1e022978100c521634a968968a901dd934cTim Janik gchar *signal = g_new (gchar, l + 1); 100137e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik 100237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik memcpy (signal, name, l); 100337e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik signal[l] = 0; 100437e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik signal_id = signal_id_lookup (g_quark_try_string (signal), itype); 10053cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik g_free (signal); 100637e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik } 100737e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik 100837e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik if (signal_id && detail_p) 100937e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0; 101037e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik } 101137e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik else 101237e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik signal_id = 0; 10133cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik return signal_id; 10143cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik} 1015356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 1016356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost/** 1017356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * g_signal_parse_name: 1018356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @detailed_signal: a string of the form "signal-name::detail". 10196347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @itype: The interface/instance type that introduced "signal-name". 1020356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @signal_id_p: Location to store the signal id. 10216347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @detail_p: Location to store the detail quark. 10226347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @force_detail_quark: %TRUE forces creation of a #GQuark for the detail. 1023356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 1024356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Internal function to parse a signal name into its @signal_id 1025e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * and @detail quark. 1026e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * 1027e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * Returns: Whether the signal name could successfully be parsed and @signal_id_p and @detail_p contain valid return values. 1028e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik */ 1029e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janikgboolean 1030e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janikg_signal_parse_name (const gchar *detailed_signal, 1031e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik GType itype, 1032e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik guint *signal_id_p, 1033e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik GQuark *detail_p, 1034e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik gboolean force_detail_quark) 1035e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik{ 10369369e1e022978100c521634a968968a901dd934cTim Janik SignalNode *node; 1037e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik GQuark detail = 0; 1038e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik guint signal_id; 1039e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 1040e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik g_return_val_if_fail (detailed_signal != NULL, FALSE); 1041e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE); 1042e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 1043e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik SIGNAL_LOCK (); 1044e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark); 1045e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik SIGNAL_UNLOCK (); 1046e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 1047e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL; 1048e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik if (!node || node->destroyed || 1049e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik (detail && !(node->flags & G_SIGNAL_DETAILED))) 1050e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik return FALSE; 1051e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 1052e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik if (signal_id_p) 1053e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik *signal_id_p = signal_id; 1054a05a4b766073561baea10ba697fc7042c308719cTim Janik if (detail_p) 1055e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik *detail_p = detail; 1056e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 1057a05a4b766073561baea10ba697fc7042c308719cTim Janik return TRUE; 1058a05a4b766073561baea10ba697fc7042c308719cTim Janik} 1059e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 1060e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik/** 1061e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * g_signal_stop_emission_by_name: 1062e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * @instance: the object whose signal handlers you wish to stop. 1063e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * @detailed_signal: a string of the form "signal-name::detail". 1064e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * 1065e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * Stops a signal's current emission. 1066e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * 10679369e1e022978100c521634a968968a901dd934cTim Janik * This is just like g_signal_stop_emission() except it will look up the 1068e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * signal id for you. 1069e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik */ 1070356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostvoid 1071356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostg_signal_stop_emission_by_name (gpointer instance, 1072356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost const gchar *detailed_signal) 1073356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 10746347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer guint signal_id; 10756347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer GQuark detail = 0; 10766347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer GType itype; 1077356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 10786347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 1079356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_return_if_fail (detailed_signal != NULL); 10806347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 1081356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_LOCK (); 10826347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer itype = G_TYPE_FROM_INSTANCE (instance); 1083356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); 1084356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (signal_id) 1085ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1086ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 1087ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1088ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 10898a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); 1090ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (!g_type_is_a (itype, node->itype)) 1091ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1092ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 10939369e1e022978100c521634a968968a901dd934cTim Janik { 10948a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; 10959369e1e022978100c521634a968968a901dd934cTim Janik Emission *emission = emission_find (emission_list, signal_id, detail, instance); 1096fd860cb987e0bc77b8a69363576c01069b40244eTim Janik 1097fd860cb987e0bc77b8a69363576c01069b40244eTim Janik if (emission) 1098fd860cb987e0bc77b8a69363576c01069b40244eTim Janik { 1099fd860cb987e0bc77b8a69363576c01069b40244eTim Janik if (emission->state == EMISSION_HOOK) 1100fa7a7b3e0ddc437b95b30f8322bb8ae1138c2bf4Stefan Kost g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", 1101fd860cb987e0bc77b8a69363576c01069b40244eTim Janik node->name, instance); 1102fd860cb987e0bc77b8a69363576c01069b40244eTim Janik else if (emission->state == EMISSION_RUN) 1103fd860cb987e0bc77b8a69363576c01069b40244eTim Janik emission->state = EMISSION_STOP; 1104fd860cb987e0bc77b8a69363576c01069b40244eTim Janik } 1105fd860cb987e0bc77b8a69363576c01069b40244eTim Janik else 1106fd860cb987e0bc77b8a69363576c01069b40244eTim Janik g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", 1107fd860cb987e0bc77b8a69363576c01069b40244eTim Janik node->name, instance); 1108fd860cb987e0bc77b8a69363576c01069b40244eTim Janik } 1109ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 11108a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik else 1111ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 1112ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 1113356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost} 1114356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 1115356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost/** 1116356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * g_signal_lookup: 11176347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @name: the signal's name. 1118356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @itype: the type that the signal operates on. 1119356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 1120356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Given the name of the signal and the type of object it connects to, gets 11216347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * the signal's identifying integer. Emitting the signal by number is 1122356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * somewhat faster than using the name each time. 1123356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 1124fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * Also tries the ancestors of the given type. 1125fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * 1126fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * See g_signal_new() for details on allowed signal names. 1127fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * 1128fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * Returns: the signal's identifying number, or 0 if no signal was found. 1129fd860cb987e0bc77b8a69363576c01069b40244eTim Janik */ 1130fd860cb987e0bc77b8a69363576c01069b40244eTim Janikguint 1131fd860cb987e0bc77b8a69363576c01069b40244eTim Janikg_signal_lookup (const gchar *name, 1132fd860cb987e0bc77b8a69363576c01069b40244eTim Janik GType itype) 1133fd860cb987e0bc77b8a69363576c01069b40244eTim Janik{ 1134fd860cb987e0bc77b8a69363576c01069b40244eTim Janik guint signal_id; 1135fd860cb987e0bc77b8a69363576c01069b40244eTim Janik g_return_val_if_fail (name != NULL, 0); 1136fd860cb987e0bc77b8a69363576c01069b40244eTim Janik g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); 11376d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik 11386d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik SIGNAL_LOCK (); 1139fd860cb987e0bc77b8a69363576c01069b40244eTim Janik signal_id = signal_id_lookup (g_quark_try_string (name), itype); 1140fd860cb987e0bc77b8a69363576c01069b40244eTim Janik SIGNAL_UNLOCK (); 1141fd860cb987e0bc77b8a69363576c01069b40244eTim Janik if (!signal_id) 1142fd860cb987e0bc77b8a69363576c01069b40244eTim Janik { 1143fd860cb987e0bc77b8a69363576c01069b40244eTim Janik /* give elaborate warnings */ 1144fd860cb987e0bc77b8a69363576c01069b40244eTim Janik if (!g_type_name (itype)) 1145fd860cb987e0bc77b8a69363576c01069b40244eTim Janik g_warning (G_STRLOC ": unable to lookup signal \"%s\" for invalid type id `%"G_GSIZE_FORMAT"'", 1146fd860cb987e0bc77b8a69363576c01069b40244eTim Janik name, itype); 1147fd860cb987e0bc77b8a69363576c01069b40244eTim Janik else if (!G_TYPE_IS_INSTANTIATABLE (itype)) 1148fd860cb987e0bc77b8a69363576c01069b40244eTim Janik g_warning (G_STRLOC ": unable to lookup signal \"%s\" for non instantiatable type `%s'", 1149fd860cb987e0bc77b8a69363576c01069b40244eTim Janik name, g_type_name (itype)); 1150fd860cb987e0bc77b8a69363576c01069b40244eTim Janik else if (!g_type_class_peek (itype)) 1151fd860cb987e0bc77b8a69363576c01069b40244eTim Janik g_warning (G_STRLOC ": unable to lookup signal \"%s\" of unloaded type `%s'", 1152fd860cb987e0bc77b8a69363576c01069b40244eTim Janik name, g_type_name (itype)); 1153fd860cb987e0bc77b8a69363576c01069b40244eTim Janik } 1154fd860cb987e0bc77b8a69363576c01069b40244eTim Janik 1155fd860cb987e0bc77b8a69363576c01069b40244eTim Janik return signal_id; 1156fd860cb987e0bc77b8a69363576c01069b40244eTim Janik} 1157fd860cb987e0bc77b8a69363576c01069b40244eTim Janik 1158fa7a7b3e0ddc437b95b30f8322bb8ae1138c2bf4Stefan Kost/** 1159fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * g_signal_list_ids: 1160edf4c171650ae713115235c678571e8900d4c9b8Cody Russell * @itype: Instance or interface type. 1161fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * @n_ids: Location to store the number of signal ids for @itype. 1162fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * 1163edf4c171650ae713115235c678571e8900d4c9b8Cody Russell * Lists the signals by id that a certain instance or interface type 1164fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * created. Further information about the signals can be acquired through 1165fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * g_signal_query(). 1166fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * 1167fd860cb987e0bc77b8a69363576c01069b40244eTim Janik * Returns: Newly allocated array of signal IDs. 1168fd860cb987e0bc77b8a69363576c01069b40244eTim Janik */ 1169fd860cb987e0bc77b8a69363576c01069b40244eTim Janikguint* 1170fd860cb987e0bc77b8a69363576c01069b40244eTim Janikg_signal_list_ids (GType itype, 1171356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost guint *n_ids) 1172356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 1173356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SignalKey *keys; 11746347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer GArray *result; 1175356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost guint n_nodes; 11766347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer guint i; 1177356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 11786347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL); 1179356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_return_val_if_fail (n_ids != NULL, NULL); 1180356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 11811c391cc69846713b0406545146ea232efc5f34e2Havoc Pennington SIGNAL_LOCK (); 1182ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0); 1183ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa); 1184ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik result = g_array_new (FALSE, FALSE, sizeof (guint)); 11858161643a39772e9283f95811c18ac19901e17c65Matthias Clasen 118683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik for (i = 0; i < n_nodes; i++) 11879369e1e022978100c521634a968968a901dd934cTim Janik if (keys[i].itype == itype) 1188ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1189ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik const gchar *name = g_quark_to_string (keys[i].quark); 11909369e1e022978100c521634a968968a901dd934cTim Janik 1191ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* Signal names with "_" in them are aliases to the same 11928161643a39772e9283f95811c18ac19901e17c65Matthias Clasen * name with "-" instead of "_". 1193ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 1194ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!strchr (name, '_')) 1195356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_array_append_val (result, keys[i].signal_id); 1196356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 1197356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost *n_ids = result->len; 1198356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 1199356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (!n_nodes) 12006347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer { 1201356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost /* give elaborate warnings */ 1202356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (!g_type_name (itype)) 1203356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_warning (G_STRLOC ": unable to list signals for invalid type id `%"G_GSIZE_FORMAT"'", 1204356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost itype); 1205356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost else if (!G_TYPE_IS_INSTANTIATABLE (itype) && !G_TYPE_IS_INTERFACE (itype)) 1206356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_warning (G_STRLOC ": unable to list signals of non instantiatable type `%s'", 1207356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_type_name (itype)); 1208ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (!g_type_class_peek (itype) && !G_TYPE_IS_INTERFACE (itype)) 1209ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": unable to list signals of unloaded type `%s'", 1210ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_type_name (itype)); 1211ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1212ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 121383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return (guint*) g_array_free (result, FALSE); 1214ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 121583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 12169369e1e022978100c521634a968968a901dd934cTim Janik/** 1217ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * g_signal_name: 1218ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @signal_id: the signal's identifying number. 1219ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 1220ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Given the signal's identifier, finds its name. 1221ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 1222ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Two different signals may have the same name, if they have differing types. 1223ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 1224ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Returns: the signal name, or %NULL if the signal number was invalid. 1225ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 1226ee23c09e83d06a0d131ebd234c132f1c3602c019Tim JanikG_CONST_RETURN gchar* 1227ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_name (guint signal_id) 1228ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1229ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node; 12309369e1e022978100c521634a968968a901dd934cTim Janik const gchar *name; 1231ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1232ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 1233356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node = LOOKUP_SIGNAL_NODE (signal_id); 1234356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost name = node ? node->name : NULL; 1235356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 12366347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 1237356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost return (char*) name; 12386347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer} 12396347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 1240356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost/** 12416347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * g_signal_query: 1242356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @signal_id: The signal id of the signal to query information for. 1243356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @query: A user provided structure that is filled in with constant 1244356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * values upon success. 1245356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 12466347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * Queries the signal system for in-depth information about a 1247356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * specific signal. This function will fill in a user-provided 12486347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * structure to hold signal-specific information. If an invalid 1249356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * signal id is passed in, the @signal_id member of the #GSignalQuery 1250356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * is 0. All members filled into the #GSignalQuery structure should 1251356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * be considered constant and have to be left untouched. 12526347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer */ 1253356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostvoid 12546347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Nattererg_signal_query (guint signal_id, 1255356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GSignalQuery *query) 1256356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 1257356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SignalNode *node; 12586347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 12596347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_return_if_fail (query != NULL); 1260356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 12616347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer SIGNAL_LOCK (); 12626347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer node = LOOKUP_SIGNAL_NODE (signal_id); 1263356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (!node || node->destroyed) 1264356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost query->signal_id = 0; 1265ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 1266fd860cb987e0bc77b8a69363576c01069b40244eTim Janik { 1267fd860cb987e0bc77b8a69363576c01069b40244eTim Janik query->signal_id = node->signal_id; 1268fd860cb987e0bc77b8a69363576c01069b40244eTim Janik query->signal_name = node->name; 1269fd860cb987e0bc77b8a69363576c01069b40244eTim Janik query->itype = node->itype; 1270fd860cb987e0bc77b8a69363576c01069b40244eTim Janik query->signal_flags = node->flags; 1271fd860cb987e0bc77b8a69363576c01069b40244eTim Janik query->return_type = node->return_type; 1272fd860cb987e0bc77b8a69363576c01069b40244eTim Janik query->n_params = node->n_params; 1273fd860cb987e0bc77b8a69363576c01069b40244eTim Janik query->param_types = node->param_types; 1274fd860cb987e0bc77b8a69363576c01069b40244eTim Janik } 1275fd860cb987e0bc77b8a69363576c01069b40244eTim Janik SIGNAL_UNLOCK (); 1276b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington} 1277b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington 1278b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington/** 1279b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * g_signal_new: 1280b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * @signal_name: the name for the signal 1281b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * @itype: the type this signal pertains to. It will also pertain to 1282b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * types which are derived from this type. 1283b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * @signal_flags: a combination of #GSignalFlags specifying detail of when 1284b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * the default handler is to be invoked. You should at least specify 128543b692c8eb49a82657d9cb09a222dc66f2cc0199Tim Janik * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST. 1286617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @class_offset: The offset of the function pointer in the class structure 1287b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * for this type. Used to invoke a class method generically. Pass 0 to 1288b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * not associate a class method with this signal. 1289b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * @accumulator: the accumulator for this signal; may be %NULL. 1290779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @accu_data: user data for the @accumulator. 1291779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @c_marshaller: the function to translate arrays of parameter values to 1292779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * signal emissions into C language callback invocations. 1293779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @return_type: the type of return value, or #G_TYPE_NONE for a signal 1294779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * without a return value. 1295779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @n_params: the number of parameter types to follow. 1296779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @...: a list of types, one for each parameter. 1297779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * 1298779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * Creates a new signal. (This is usually done in the class initializer.) 1299779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * 1300779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * A signal name consists of segments consisting of ASCII letters and 1301779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * digits, separated by either the '-' or '_' character. The first 1302b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * character of a signal name must be a letter. Names which violate these 1303b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * rules lead to undefined behaviour of the GSignal system. 1304b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * 1305b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Pennington * When registering a signal and looking up a signal, either separator can 130620d4f6da7324dece455eed2b64e3073895306440Michael Natterer * be used, but they cannot be mixed. 130720d4f6da7324dece455eed2b64e3073895306440Michael Natterer * 130820d4f6da7324dece455eed2b64e3073895306440Michael Natterer * Returns: the signal id 130920d4f6da7324dece455eed2b64e3073895306440Michael Natterer */ 131020d4f6da7324dece455eed2b64e3073895306440Michael Nattererguint 131120d4f6da7324dece455eed2b64e3073895306440Michael Nattererg_signal_new (const gchar *signal_name, 131220d4f6da7324dece455eed2b64e3073895306440Michael Natterer GType itype, 131320d4f6da7324dece455eed2b64e3073895306440Michael Natterer GSignalFlags signal_flags, 131420d4f6da7324dece455eed2b64e3073895306440Michael Natterer guint class_offset, 131520d4f6da7324dece455eed2b64e3073895306440Michael Natterer GSignalAccumulator accumulator, 131620d4f6da7324dece455eed2b64e3073895306440Michael Natterer gpointer accu_data, 131720d4f6da7324dece455eed2b64e3073895306440Michael Natterer GSignalCMarshaller c_marshaller, 131820d4f6da7324dece455eed2b64e3073895306440Michael Natterer GType return_type, 131920d4f6da7324dece455eed2b64e3073895306440Michael Natterer guint n_params, 132020d4f6da7324dece455eed2b64e3073895306440Michael Natterer ...) 132120d4f6da7324dece455eed2b64e3073895306440Michael Natterer{ 132220d4f6da7324dece455eed2b64e3073895306440Michael Natterer va_list args; 132320d4f6da7324dece455eed2b64e3073895306440Michael Natterer guint signal_id; 132420d4f6da7324dece455eed2b64e3073895306440Michael Natterer 132520d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_return_val_if_fail (signal_name != NULL, 0); 132620d4f6da7324dece455eed2b64e3073895306440Michael Natterer 132720d4f6da7324dece455eed2b64e3073895306440Michael Natterer va_start (args, n_params); 132820d4f6da7324dece455eed2b64e3073895306440Michael Natterer 132920d4f6da7324dece455eed2b64e3073895306440Michael Natterer signal_id = g_signal_new_valist (signal_name, itype, signal_flags, 133020d4f6da7324dece455eed2b64e3073895306440Michael Natterer class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL, 133120d4f6da7324dece455eed2b64e3073895306440Michael Natterer accumulator, accu_data, c_marshaller, 133220d4f6da7324dece455eed2b64e3073895306440Michael Natterer return_type, n_params, args); 133320d4f6da7324dece455eed2b64e3073895306440Michael Natterer 133420d4f6da7324dece455eed2b64e3073895306440Michael Natterer va_end (args); 133520d4f6da7324dece455eed2b64e3073895306440Michael Natterer 1336864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer /* optimize NOP emissions with NULL class handlers */ 133720d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (signal_id && G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE && 133820d4f6da7324dece455eed2b64e3073895306440Michael Natterer class_offset && class_offset < MAX_TEST_CLASS_OFFSET) 133920d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 134020d4f6da7324dece455eed2b64e3073895306440Michael Natterer SignalNode *node; 134120d4f6da7324dece455eed2b64e3073895306440Michael Natterer 134220d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_LOCK (); 134320d4f6da7324dece455eed2b64e3073895306440Michael Natterer node = LOOKUP_SIGNAL_NODE (signal_id); 134420d4f6da7324dece455eed2b64e3073895306440Michael Natterer node->test_class_offset = class_offset; 134520d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_UNLOCK (); 134620d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 134720d4f6da7324dece455eed2b64e3073895306440Michael Natterer 134820d4f6da7324dece455eed2b64e3073895306440Michael Natterer return signal_id; 134920d4f6da7324dece455eed2b64e3073895306440Michael Natterer} 135020d4f6da7324dece455eed2b64e3073895306440Michael Natterer 135120d4f6da7324dece455eed2b64e3073895306440Michael Natterer/** 135220d4f6da7324dece455eed2b64e3073895306440Michael Natterer * g_signal_new_class_handler: 135320d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @signal_name: the name for the signal 135420d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @itype: the type this signal pertains to. It will also pertain to 135520d4f6da7324dece455eed2b64e3073895306440Michael Natterer * types which are derived from this type. 135620d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @signal_flags: a combination of #GSignalFlags specifying detail of when 135720d4f6da7324dece455eed2b64e3073895306440Michael Natterer * the default handler is to be invoked. You should at least specify 135820d4f6da7324dece455eed2b64e3073895306440Michael Natterer * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST. 135920d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @class_handler: a #GCallback which acts as class implementation of 136020d4f6da7324dece455eed2b64e3073895306440Michael Natterer * this signal. Used to invoke a class method generically. Pass %NULL to 136120d4f6da7324dece455eed2b64e3073895306440Michael Natterer * not associate a class method with this signal. 136220d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @accumulator: the accumulator for this signal; may be %NULL. 136320d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @accu_data: user data for the @accumulator. 136420d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @c_marshaller: the function to translate arrays of parameter values to 136520d4f6da7324dece455eed2b64e3073895306440Michael Natterer * signal emissions into C language callback invocations. 136620d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @return_type: the type of return value, or #G_TYPE_NONE for a signal 136720d4f6da7324dece455eed2b64e3073895306440Michael Natterer * without a return value. 136820d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @n_params: the number of parameter types to follow. 136920d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @...: a list of types, one for each parameter. 137020d4f6da7324dece455eed2b64e3073895306440Michael Natterer * 137120d4f6da7324dece455eed2b64e3073895306440Michael Natterer * Creates a new signal. (This is usually done in the class initializer.) 137220d4f6da7324dece455eed2b64e3073895306440Michael Natterer * 1373a05a4b766073561baea10ba697fc7042c308719cTim Janik * This is a variant of g_signal_new() that takes a C callback instead 1374a05a4b766073561baea10ba697fc7042c308719cTim Janik * off a class offset for the signal's class handler. This function 1375a05a4b766073561baea10ba697fc7042c308719cTim Janik * doesn't need a function pointer exposed in the class structure of 1376a05a4b766073561baea10ba697fc7042c308719cTim Janik * an object definition, instead the function pointer is passed 1377a05a4b766073561baea10ba697fc7042c308719cTim Janik * directly and can be overriden by derived classes with 1378a05a4b766073561baea10ba697fc7042c308719cTim Janik * g_signal_override_class_closure() or 1379a05a4b766073561baea10ba697fc7042c308719cTim Janik * g_signal_override_class_handler()and chained to with 1380a05a4b766073561baea10ba697fc7042c308719cTim Janik * g_signal_chain_from_overridden() or 1381a05a4b766073561baea10ba697fc7042c308719cTim Janik * g_signal_chain_from_overridden_handler(). 1382a05a4b766073561baea10ba697fc7042c308719cTim Janik * 1383a05a4b766073561baea10ba697fc7042c308719cTim Janik * See g_signal_new() for information about signal names. 1384a05a4b766073561baea10ba697fc7042c308719cTim Janik * 1385a05a4b766073561baea10ba697fc7042c308719cTim Janik * Returns: the signal id 1386a05a4b766073561baea10ba697fc7042c308719cTim Janik * 1387a05a4b766073561baea10ba697fc7042c308719cTim Janik * Since: 2.18 1388a05a4b766073561baea10ba697fc7042c308719cTim Janik */ 1389a05a4b766073561baea10ba697fc7042c308719cTim Janikguint 1390a05a4b766073561baea10ba697fc7042c308719cTim Janikg_signal_new_class_handler (const gchar *signal_name, 1391a05a4b766073561baea10ba697fc7042c308719cTim Janik GType itype, 1392a05a4b766073561baea10ba697fc7042c308719cTim Janik GSignalFlags signal_flags, 1393a05a4b766073561baea10ba697fc7042c308719cTim Janik GCallback class_handler, 1394a05a4b766073561baea10ba697fc7042c308719cTim Janik GSignalAccumulator accumulator, 1395a05a4b766073561baea10ba697fc7042c308719cTim Janik gpointer accu_data, 1396a05a4b766073561baea10ba697fc7042c308719cTim Janik GSignalCMarshaller c_marshaller, 1397a05a4b766073561baea10ba697fc7042c308719cTim Janik GType return_type, 1398a05a4b766073561baea10ba697fc7042c308719cTim Janik guint n_params, 1399a05a4b766073561baea10ba697fc7042c308719cTim Janik ...) 1400a05a4b766073561baea10ba697fc7042c308719cTim Janik{ 1401a05a4b766073561baea10ba697fc7042c308719cTim Janik va_list args; 1402a05a4b766073561baea10ba697fc7042c308719cTim Janik guint signal_id; 1403a05a4b766073561baea10ba697fc7042c308719cTim Janik 1404a05a4b766073561baea10ba697fc7042c308719cTim Janik g_return_val_if_fail (signal_name != NULL, 0); 14056d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik 1406622f01012030fcba31ee2a68920873ac06bb62e4Kristian Rietveld va_start (args, n_params); 1407622f01012030fcba31ee2a68920873ac06bb62e4Kristian Rietveld 1408622f01012030fcba31ee2a68920873ac06bb62e4Kristian Rietveld signal_id = g_signal_new_valist (signal_name, itype, signal_flags, 1409622f01012030fcba31ee2a68920873ac06bb62e4Kristian Rietveld class_handler ? g_cclosure_new (class_handler, NULL, NULL) : NULL, 1410622f01012030fcba31ee2a68920873ac06bb62e4Kristian Rietveld accumulator, accu_data, c_marshaller, 1411622f01012030fcba31ee2a68920873ac06bb62e4Kristian Rietveld return_type, n_params, args); 1412a05a4b766073561baea10ba697fc7042c308719cTim Janik 1413a05a4b766073561baea10ba697fc7042c308719cTim Janik va_end (args); 1414a05a4b766073561baea10ba697fc7042c308719cTim Janik 1415a05a4b766073561baea10ba697fc7042c308719cTim Janik return signal_id; 1416a05a4b766073561baea10ba697fc7042c308719cTim Janik} 1417a05a4b766073561baea10ba697fc7042c308719cTim Janik 1418a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic inline ClassClosure* 1419a05a4b766073561baea10ba697fc7042c308719cTim Janiksignal_find_class_closure (SignalNode *node, 1420a05a4b766073561baea10ba697fc7042c308719cTim Janik GType itype) 1421a05a4b766073561baea10ba697fc7042c308719cTim Janik{ 1422779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik GBSearchArray *bsa = node->class_closure_bsa; 1423779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik ClassClosure *cc; 1424779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik 1425a05a4b766073561baea10ba697fc7042c308719cTim Janik if (bsa) 14266d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik { 1427a05a4b766073561baea10ba697fc7042c308719cTim Janik ClassClosure key; 1428a05a4b766073561baea10ba697fc7042c308719cTim Janik 1429a05a4b766073561baea10ba697fc7042c308719cTim Janik /* cc->instance_type is 0 for default closure */ 1430a05a4b766073561baea10ba697fc7042c308719cTim Janik 14316d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik key.instance_type = itype; 1432a05a4b766073561baea10ba697fc7042c308719cTim Janik cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key); 1433a05a4b766073561baea10ba697fc7042c308719cTim Janik while (!cc && key.instance_type) 1434a05a4b766073561baea10ba697fc7042c308719cTim Janik { 1435a05a4b766073561baea10ba697fc7042c308719cTim Janik key.instance_type = g_type_parent (key.instance_type); 1436a05a4b766073561baea10ba697fc7042c308719cTim Janik cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key); 1437356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 1438356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 1439356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost else 14406347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer cc = NULL; 1441db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasen return cc; 14426347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer} 1443db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasen 1444db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasenstatic inline GClosure* 1445db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasensignal_lookup_closure (SignalNode *node, 1446db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasen GTypeInstance *instance) 1447db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasen{ 14486347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer ClassClosure *cc; 1449db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasen 14506347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer if (node->class_closure_bsa && g_bsearch_array_get_n_nodes (node->class_closure_bsa) == 1) 1451db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasen { 1452db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasen cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0); 1453db830dd381bb3e1566ee35aaae6f9f3161a3a818Matthias Clasen if (cc && cc->instance_type == 0) /* check for default closure */ 14546347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer return cc->closure; 1455356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 14566347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance)); 1457356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost return cc ? cc->closure : NULL; 14586347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer} 1459356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 1460356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Koststatic void 1461b3c410dee1b3d3e72ad1e76c7dc597a07482137dHavoc Penningtonsignal_add_class_closure (SignalNode *node, 1462ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype, 1463ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GClosure *closure) 1464830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik{ 1465ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik ClassClosure key; 1466ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1467617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik /* can't optimize NOP emissions with overridden class closures */ 1468ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->test_class_offset = 0; 1469ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1470ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!node->class_closure_bsa) 1471ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig); 1472ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.instance_type = itype; 1473ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik key.closure = g_closure_ref (closure); 1474ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa, 1475ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik &g_class_closure_bconfig, 1476ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik &key); 1477ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_sink (closure); 1478ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure)) 1479ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_set_marshal (closure, node->c_marshaller); 1480ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 148143b692c8eb49a82657d9cb09a222dc66f2cc0199Tim Janik 1482617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik/** 1483ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * g_signal_newv: 1484617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @signal_name: the name for the signal 1485617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @itype: the type this signal pertains to. It will also pertain to 1486617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * types which are derived from this type 1487ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @signal_flags: a combination of #GSignalFlags specifying detail of when 14889abb30720036dfd464a142555aae7cce5e85c3d6Owen Taylor * the default handler is to be invoked. You should at least specify 1489ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST 14909369e1e022978100c521634a968968a901dd934cTim Janik * @class_closure: The closure to invoke on signal emission; may be %NULL 1491ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @accumulator: the accumulator for this signal; may be %NULL 14928a572c0da1be99527c52f620dc7fd04eb0775bdeTim Janik * @accu_data: user data for the @accumulator 1493ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @c_marshaller: the function to translate arrays of parameter values to 1494ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * signal emissions into C language callback invocations 1495ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @return_type: the type of return value, or #G_TYPE_NONE for a signal 1496ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * without a return value 1497ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @n_params: the length of @param_types 1498116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor * @param_types: an array of types, one for each parameter 1499ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 1500ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Creates a new signal. (This is usually done in the class initializer.) 15019369e1e022978100c521634a968968a901dd934cTim Janik * 1502ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * See g_signal_new() for details on allowed signal names. 1503ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 1504ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Returns: the signal id 1505ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 1506ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint 1507ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_newv (const gchar *signal_name, 1508116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor GType itype, 1509116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor GSignalFlags signal_flags, 1510ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GClosure *class_closure, 15119369e1e022978100c521634a968968a901dd934cTim Janik GSignalAccumulator accumulator, 1512ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer accu_data, 1513ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalCMarshaller c_marshaller, 1514ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType return_type, 151537e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik guint n_params, 1516ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType *param_types) 1517ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1518116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor gchar *name; 1519ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id, i; 15209369e1e022978100c521634a968968a901dd934cTim Janik SignalNode *node; 1521ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1522ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (signal_name != NULL, 0); 1523bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); 1524ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (n_params) 1525ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (param_types != NULL, 0); 1526116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0); 1527ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 15289369e1e022978100c521634a968968a901dd934cTim Janik g_return_val_if_fail (accumulator == NULL, 0); 1529ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!accumulator) 1530ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (accu_data == NULL, 0); 1531b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik 1532b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik name = g_strdup (signal_name); 1533b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); /* FIXME do character checks like for types */ 1534b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik 1535116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor SIGNAL_LOCK (); 1536b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik 15379369e1e022978100c521634a968968a901dd934cTim Janik signal_id = signal_id_lookup (g_quark_try_string (name), itype); 1538b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 1539b7d54841ee594eebfec33d6dc32596eef32acbfdTim Janik if (node && !node->destroyed) 1540ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1541ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s", 1542ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik name, 1543ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik type_debug_name (node->itype), 1544ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry"); 1545ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (name); 1546ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 1547ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return 0; 1548ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1549ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node && node->itype != itype) 1550ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1551ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'", 1552ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik name, 1553ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik type_debug_name (itype), 1554ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik type_debug_name (node->itype)); 1555ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_free (name); 15566d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik SIGNAL_UNLOCK (); 15578161643a39772e9283f95811c18ac19901e17c65Matthias Clasen return 0; 15588161643a39772e9283f95811c18ac19901e17c65Matthias Clasen } 15598161643a39772e9283f95811c18ac19901e17c65Matthias Clasen for (i = 0; i < n_params; i++) 15606d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1561ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1562ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type", 1563779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name); 1564779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik g_free (name); 1565ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 1566830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik return 0; 1567ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1568ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 1569ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1570a05a4b766073561baea10ba697fc7042c308719cTim Janik g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type", 1571617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik type_debug_name (return_type), type_debug_name (itype), name); 1572617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_free (name); 1573617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SIGNAL_UNLOCK (); 1574617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik return 0; 1575617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 1576617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (return_type != G_TYPE_NONE && 1577617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik (signal_flags & (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP)) == G_SIGNAL_RUN_FIRST) 1578617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 1579ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning (G_STRLOC ": signal \"%s::%s\" has return type `%s' and is only G_SIGNAL_RUN_FIRST", 1580ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik type_debug_name (itype), name, type_debug_name (return_type)); 1581a05a4b766073561baea10ba697fc7042c308719cTim Janik g_free (name); 1582a05a4b766073561baea10ba697fc7042c308719cTim Janik SIGNAL_UNLOCK (); 1583779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik return 0; 1584779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik } 1585779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik 1586779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik /* setup permanent portion of signal node */ 1587779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik if (!node) 15889369e1e022978100c521634a968968a901dd934cTim Janik { 1589a05a4b766073561baea10ba697fc7042c308719cTim Janik SignalKey key; 15908161643a39772e9283f95811c18ac19901e17c65Matthias Clasen 15918161643a39772e9283f95811c18ac19901e17c65Matthias Clasen signal_id = g_n_signal_nodes++; 1592a05a4b766073561baea10ba697fc7042c308719cTim Janik node = g_new (SignalNode, 1); 1593a05a4b766073561baea10ba697fc7042c308719cTim Janik node->signal_id = signal_id; 1594a05a4b766073561baea10ba697fc7042c308719cTim Janik g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); 1595356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_signal_nodes[signal_id] = node; 1596356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->itype = itype; 1597356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->name = name; 15986347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer key.itype = itype; 1599356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost key.quark = g_quark_from_string (node->name); 16006347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer key.signal_id = signal_id; 16016347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key); 1602356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_strdelimit (name, "_", '-'); 1603356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->name = g_intern_string (name); 1604356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost key.quark = g_quark_from_string (name); 1605356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key); 16066347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer } 1607356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->destroyed = FALSE; 16086347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer node->test_class_offset = 0; 1609356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 1610356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost /* setup reinitializable portion */ 1611356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; 16126347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer node->n_params = n_params; 1613356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->param_types = g_memdup (param_types, sizeof (GType) * n_params); 16146347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer node->return_type = return_type; 1615356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->class_closure_bsa = NULL; 16166347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer if (accumulator) 1617356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 1618356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->accumulator = g_new (SignalAccumulator, 1); 1619a05a4b766073561baea10ba697fc7042c308719cTim Janik node->accumulator->func = accumulator; 1620a05a4b766073561baea10ba697fc7042c308719cTim Janik node->accumulator->data = accu_data; 1621a05a4b766073561baea10ba697fc7042c308719cTim Janik } 1622a05a4b766073561baea10ba697fc7042c308719cTim Janik else 1623a05a4b766073561baea10ba697fc7042c308719cTim Janik node->accumulator = NULL; 1624a05a4b766073561baea10ba697fc7042c308719cTim Janik node->c_marshaller = c_marshaller; 1625a05a4b766073561baea10ba697fc7042c308719cTim Janik node->emission_hooks = NULL; 1626a05a4b766073561baea10ba697fc7042c308719cTim Janik if (class_closure) 1627a05a4b766073561baea10ba697fc7042c308719cTim Janik signal_add_class_closure (node, 0, class_closure); 1628a05a4b766073561baea10ba697fc7042c308719cTim Janik else if (G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE) 1629a05a4b766073561baea10ba697fc7042c308719cTim Janik { 1630a05a4b766073561baea10ba697fc7042c308719cTim Janik /* optimize NOP emissions */ 1631a05a4b766073561baea10ba697fc7042c308719cTim Janik node->test_class_offset = TEST_CLASS_MAGIC; 1632a05a4b766073561baea10ba697fc7042c308719cTim Janik } 1633a05a4b766073561baea10ba697fc7042c308719cTim Janik SIGNAL_UNLOCK (); 1634a05a4b766073561baea10ba697fc7042c308719cTim Janik 1635a05a4b766073561baea10ba697fc7042c308719cTim Janik g_free (name); 1636a05a4b766073561baea10ba697fc7042c308719cTim Janik 1637a05a4b766073561baea10ba697fc7042c308719cTim Janik return signal_id; 1638a05a4b766073561baea10ba697fc7042c308719cTim Janik} 1639a05a4b766073561baea10ba697fc7042c308719cTim Janik 1640a05a4b766073561baea10ba697fc7042c308719cTim Janik/** 1641a05a4b766073561baea10ba697fc7042c308719cTim Janik * g_signal_new_valist: 1642a05a4b766073561baea10ba697fc7042c308719cTim Janik * @signal_name: the name for the signal 1643a05a4b766073561baea10ba697fc7042c308719cTim Janik * @itype: the type this signal pertains to. It will also pertain to 1644a05a4b766073561baea10ba697fc7042c308719cTim Janik * types which are derived from this type. 1645a05a4b766073561baea10ba697fc7042c308719cTim Janik * @signal_flags: a combination of #GSignalFlags specifying detail of when 1646a05a4b766073561baea10ba697fc7042c308719cTim Janik * the default handler is to be invoked. You should at least specify 1647a05a4b766073561baea10ba697fc7042c308719cTim Janik * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST. 1648a05a4b766073561baea10ba697fc7042c308719cTim Janik * @class_closure: The closure to invoke on signal emission; may be %NULL. 1649a05a4b766073561baea10ba697fc7042c308719cTim Janik * @accumulator: the accumulator for this signal; may be %NULL. 1650ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @accu_data: user data for the @accumulator. 1651ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @c_marshaller: the function to translate arrays of parameter values to 1652ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * signal emissions into C language callback invocations. 1653ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @return_type: the type of return value, or #G_TYPE_NONE for a signal 1654ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * without a return value. 1655ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @n_params: the number of parameter types in @args. 1656ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @args: va_list of #GType, one for each parameter. 1657a05a4b766073561baea10ba697fc7042c308719cTim Janik * 1658ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Creates a new signal. (This is usually done in the class initializer.) 1659ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 1660ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * See g_signal_new() for details on allowed signal names. 1661779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * 1662ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Returns: the signal id 1663ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 1664ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikguint 1665a05a4b766073561baea10ba697fc7042c308719cTim Janikg_signal_new_valist (const gchar *signal_name, 1666ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType itype, 1667ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalFlags signal_flags, 1668ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GClosure *class_closure, 1669ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalAccumulator accumulator, 1670782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik gpointer accu_data, 1671ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalCMarshaller c_marshaller, 1672ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType return_type, 1673ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint n_params, 1674ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik va_list args) 1675ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1676ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GType *param_types; 1677a05a4b766073561baea10ba697fc7042c308719cTim Janik guint i; 1678ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id; 1679ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1680ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (n_params > 0) 1681ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 1682ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik param_types = g_new (GType, n_params); 1683ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1684ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik for (i = 0; i < n_params; i++) 16859369e1e022978100c521634a968968a901dd934cTim Janik param_types[i] = va_arg (args, GType); 1686ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 1687a05a4b766073561baea10ba697fc7042c308719cTim Janik else 1688a05a4b766073561baea10ba697fc7042c308719cTim Janik param_types = NULL; 1689a05a4b766073561baea10ba697fc7042c308719cTim Janik 1690a05a4b766073561baea10ba697fc7042c308719cTim Janik signal_id = g_signal_newv (signal_name, itype, signal_flags, 1691a05a4b766073561baea10ba697fc7042c308719cTim Janik class_closure, accumulator, accu_data, c_marshaller, 1692a05a4b766073561baea10ba697fc7042c308719cTim Janik return_type, n_params, param_types); 1693a05a4b766073561baea10ba697fc7042c308719cTim Janik g_free (param_types); 1694a05a4b766073561baea10ba697fc7042c308719cTim Janik 1695a05a4b766073561baea10ba697fc7042c308719cTim Janik return signal_id; 1696a05a4b766073561baea10ba697fc7042c308719cTim Janik} 16976d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik 1698a05a4b766073561baea10ba697fc7042c308719cTim Janikstatic void 1699617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janiksignal_destroy_R (SignalNode *signal_node) 1700ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 1701ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode node = *signal_node; 1702ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 1703ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->destroyed = TRUE; 1704ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 17059369e1e022978100c521634a968968a901dd934cTim Janik /* reentrancy caution, zero out real contents first */ 1706ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->test_class_offset = 0; 1707ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik signal_node->n_params = 0; 1708356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_node->param_types = NULL; 1709356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_node->return_type = 0; 1710356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_node->class_closure_bsa = NULL; 17116347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer signal_node->accumulator = NULL; 1712356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_node->c_marshaller = NULL; 1713356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_node->emission_hooks = NULL; 17146347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 1715356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost#ifdef G_ENABLE_DEBUG 1716356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost /* check current emissions */ 1717356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 171820d4f6da7324dece455eed2b64e3073895306440Michael Natterer Emission *emission; 171920d4f6da7324dece455eed2b64e3073895306440Michael Natterer 172020d4f6da7324dece455eed2b64e3073895306440Michael Natterer for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions; 172120d4f6da7324dece455eed2b64e3073895306440Michael Natterer emission; emission = emission->next) 1722356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (emission->ihint.signal_id == node.signal_id) 172335bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')", 172435bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik node.name, emission->instance); 172535bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik } 172635bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik#endif 172735bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik 1728a05a4b766073561baea10ba697fc7042c308719cTim Janik /* free contents that need to 172969c000f069ae934760678577506495fed061d9e4Tim Janik */ 1730a05a4b766073561baea10ba697fc7042c308719cTim Janik SIGNAL_UNLOCK (); 1731a05a4b766073561baea10ba697fc7042c308719cTim Janik g_free (node.param_types); 173269c000f069ae934760678577506495fed061d9e4Tim Janik if (node.class_closure_bsa) 1733a05a4b766073561baea10ba697fc7042c308719cTim Janik { 1734a05a4b766073561baea10ba697fc7042c308719cTim Janik guint i; 1735a05a4b766073561baea10ba697fc7042c308719cTim Janik 1736116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor for (i = 0; i < node.class_closure_bsa->n_nodes; i++) 1737a05a4b766073561baea10ba697fc7042c308719cTim Janik { 1738a05a4b766073561baea10ba697fc7042c308719cTim Janik ClassClosure *cc = g_bsearch_array_get_nth (node.class_closure_bsa, &g_class_closure_bconfig, i); 1739a05a4b766073561baea10ba697fc7042c308719cTim Janik 174069c000f069ae934760678577506495fed061d9e4Tim Janik g_closure_unref (cc->closure); 1741a05a4b766073561baea10ba697fc7042c308719cTim Janik } 1742116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor g_bsearch_array_free (node.class_closure_bsa, &g_class_closure_bconfig); 1743a05a4b766073561baea10ba697fc7042c308719cTim Janik } 1744a05a4b766073561baea10ba697fc7042c308719cTim Janik g_free (node.accumulator); 1745a05a4b766073561baea10ba697fc7042c308719cTim Janik if (node.emission_hooks) 1746a05a4b766073561baea10ba697fc7042c308719cTim Janik { 174735bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik g_hook_list_clear (node.emission_hooks); 174835bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik g_free (node.emission_hooks); 1749356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 175020d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_LOCK (); 175120d4f6da7324dece455eed2b64e3073895306440Michael Natterer} 175220d4f6da7324dece455eed2b64e3073895306440Michael Natterer 175320d4f6da7324dece455eed2b64e3073895306440Michael Natterer/** 175420d4f6da7324dece455eed2b64e3073895306440Michael Natterer * g_signal_override_class_closure: 175520d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @signal_id: the signal id 175620d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @instance_type: the instance type on which to override the class closure 175720d4f6da7324dece455eed2b64e3073895306440Michael Natterer * for the signal. 175820d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @class_closure: the closure. 175920d4f6da7324dece455eed2b64e3073895306440Michael Natterer * 176020d4f6da7324dece455eed2b64e3073895306440Michael Natterer * Overrides the class closure (i.e. the default handler) for the given signal 176120d4f6da7324dece455eed2b64e3073895306440Michael Natterer * for emissions on instances of @instance_type. @instance_type must be derived 176220d4f6da7324dece455eed2b64e3073895306440Michael Natterer * from the type to which the signal belongs. 176320d4f6da7324dece455eed2b64e3073895306440Michael Natterer * 176420d4f6da7324dece455eed2b64e3073895306440Michael Natterer * See g_signal_chain_from_overridden() and 176520d4f6da7324dece455eed2b64e3073895306440Michael Natterer * g_signal_chain_from_overridden_handler() for how to chain up to the 176620d4f6da7324dece455eed2b64e3073895306440Michael Natterer * parent class closure from inside the overridden one. 176720d4f6da7324dece455eed2b64e3073895306440Michael Natterer */ 176820d4f6da7324dece455eed2b64e3073895306440Michael Natterervoid 176920d4f6da7324dece455eed2b64e3073895306440Michael Nattererg_signal_override_class_closure (guint signal_id, 177020d4f6da7324dece455eed2b64e3073895306440Michael Natterer GType instance_type, 177120d4f6da7324dece455eed2b64e3073895306440Michael Natterer GClosure *class_closure) 177220d4f6da7324dece455eed2b64e3073895306440Michael Natterer{ 177320d4f6da7324dece455eed2b64e3073895306440Michael Natterer SignalNode *node; 177420d4f6da7324dece455eed2b64e3073895306440Michael Natterer 177520d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_return_if_fail (signal_id > 0); 177620d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_return_if_fail (class_closure != NULL); 177720d4f6da7324dece455eed2b64e3073895306440Michael Natterer 177820d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_LOCK (); 177920d4f6da7324dece455eed2b64e3073895306440Michael Natterer node = LOOKUP_SIGNAL_NODE (signal_id); 178020d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (!g_type_is_a (instance_type, node->itype)) 178120d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_warning ("%s: type `%s' cannot be overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id); 178220d4f6da7324dece455eed2b64e3073895306440Michael Natterer else 178320d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 178420d4f6da7324dece455eed2b64e3073895306440Michael Natterer ClassClosure *cc = signal_find_class_closure (node, instance_type); 178520d4f6da7324dece455eed2b64e3073895306440Michael Natterer 178620d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (cc && cc->instance_type == instance_type) 178720d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_warning ("%s: type `%s' is already overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id); 178820d4f6da7324dece455eed2b64e3073895306440Michael Natterer else 178920d4f6da7324dece455eed2b64e3073895306440Michael Natterer signal_add_class_closure (node, instance_type, class_closure); 1790356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 17916347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer SIGNAL_UNLOCK (); 17926347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer} 1793356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 1794356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost/** 17956347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * g_signal_override_class_handler: 1796356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @signal_name: the name for the signal 17976347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @instance_type: the instance type on which to override the class handler 179820d4f6da7324dece455eed2b64e3073895306440Michael Natterer * for the signal. 179920d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @class_handler: the handler. 1800356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 180135bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik * Overrides the class closure (i.e. the default handler) for the 180235bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik * given signal for emissions on instances of @instance_type with 180335bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik * callabck @class_handler. @instance_type must be derived from the 180435bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik * type to which the signal belongs. 1805a05a4b766073561baea10ba697fc7042c308719cTim Janik * 1806a05a4b766073561baea10ba697fc7042c308719cTim Janik * See g_signal_chain_from_overridden() and 1807a05a4b766073561baea10ba697fc7042c308719cTim Janik * g_signal_chain_from_overridden_handler() for how to chain up to the 180869c000f069ae934760678577506495fed061d9e4Tim Janik * parent class closure from inside the overridden one. 1809a05a4b766073561baea10ba697fc7042c308719cTim Janik * 1810a05a4b766073561baea10ba697fc7042c308719cTim Janik * Since: 2.18 1811a05a4b766073561baea10ba697fc7042c308719cTim Janik */ 1812a05a4b766073561baea10ba697fc7042c308719cTim Janikvoid 1813a05a4b766073561baea10ba697fc7042c308719cTim Janikg_signal_override_class_handler (const gchar *signal_name, 1814a05a4b766073561baea10ba697fc7042c308719cTim Janik GType instance_type, 1815a05a4b766073561baea10ba697fc7042c308719cTim Janik GCallback class_handler) 181669c000f069ae934760678577506495fed061d9e4Tim Janik{ 181769c000f069ae934760678577506495fed061d9e4Tim Janik guint signal_id; 1818a05a4b766073561baea10ba697fc7042c308719cTim Janik 181969c000f069ae934760678577506495fed061d9e4Tim Janik g_return_if_fail (signal_name != NULL); 182069c000f069ae934760678577506495fed061d9e4Tim Janik g_return_if_fail (instance_type != G_TYPE_NONE); 182169c000f069ae934760678577506495fed061d9e4Tim Janik g_return_if_fail (class_handler != NULL); 182269c000f069ae934760678577506495fed061d9e4Tim Janik 182369c000f069ae934760678577506495fed061d9e4Tim Janik signal_id = g_signal_lookup (signal_name, instance_type); 1824a05a4b766073561baea10ba697fc7042c308719cTim Janik 182569c000f069ae934760678577506495fed061d9e4Tim Janik if (signal_id) 1826a05a4b766073561baea10ba697fc7042c308719cTim Janik g_signal_override_class_closure (signal_id, instance_type, 1827a05a4b766073561baea10ba697fc7042c308719cTim Janik g_cclosure_new (class_handler, NULL, NULL)); 182869c000f069ae934760678577506495fed061d9e4Tim Janik else 1829a05a4b766073561baea10ba697fc7042c308719cTim Janik g_warning ("%s: signal name '%s' is invalid for type id '%"G_GSIZE_FORMAT"'", 1830a05a4b766073561baea10ba697fc7042c308719cTim Janik G_STRLOC, signal_name, instance_type); 183169c000f069ae934760678577506495fed061d9e4Tim Janik 1832a05a4b766073561baea10ba697fc7042c308719cTim Janik} 1833a05a4b766073561baea10ba697fc7042c308719cTim Janik 1834a05a4b766073561baea10ba697fc7042c308719cTim Janik/** 1835a05a4b766073561baea10ba697fc7042c308719cTim Janik * g_signal_chain_from_overridden: 1836a05a4b766073561baea10ba697fc7042c308719cTim Janik * @instance_and_params: the argument list of the signal emission. The first 1837a05a4b766073561baea10ba697fc7042c308719cTim Janik * element in the array is a #GValue for the instance the signal is being 1838a05a4b766073561baea10ba697fc7042c308719cTim Janik * emitted on. The rest are any arguments to be passed to the signal. 1839a05a4b766073561baea10ba697fc7042c308719cTim Janik * @return_value: Location for the return value. 1840a05a4b766073561baea10ba697fc7042c308719cTim Janik * 184169c000f069ae934760678577506495fed061d9e4Tim Janik * Calls the original class closure of a signal. This function should only 1842a05a4b766073561baea10ba697fc7042c308719cTim Janik * be called from an overridden class closure; see 1843a05a4b766073561baea10ba697fc7042c308719cTim Janik * g_signal_override_class_closure() and 184469c000f069ae934760678577506495fed061d9e4Tim Janik * g_signal_override_class_handler(). 184520d4f6da7324dece455eed2b64e3073895306440Michael Natterer */ 1846a05a4b766073561baea10ba697fc7042c308719cTim Janikvoid 1847a05a4b766073561baea10ba697fc7042c308719cTim Janikg_signal_chain_from_overridden (const GValue *instance_and_params, 1848a05a4b766073561baea10ba697fc7042c308719cTim Janik GValue *return_value) 1849a05a4b766073561baea10ba697fc7042c308719cTim Janik{ 1850a05a4b766073561baea10ba697fc7042c308719cTim Janik GType chain_type = 0, restore_type = 0; 1851a05a4b766073561baea10ba697fc7042c308719cTim Janik Emission *emission = NULL; 185269c000f069ae934760678577506495fed061d9e4Tim Janik GClosure *closure = NULL; 1853a05a4b766073561baea10ba697fc7042c308719cTim Janik guint n_params = 0; 1854a05a4b766073561baea10ba697fc7042c308719cTim Janik gpointer instance; 1855a05a4b766073561baea10ba697fc7042c308719cTim Janik 1856a05a4b766073561baea10ba697fc7042c308719cTim Janik g_return_if_fail (instance_and_params != NULL); 1857a05a4b766073561baea10ba697fc7042c308719cTim Janik instance = g_value_peek_pointer (instance_and_params); 1858a05a4b766073561baea10ba697fc7042c308719cTim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 185935bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik 186035bf561f5fb29e5053077986b4a7c3b00ea9b4b9Tim Janik SIGNAL_LOCK (); 1861356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost emission = emission_find_innermost (instance); 186220d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (emission) 186320d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 186420d4f6da7324dece455eed2b64e3073895306440Michael Natterer SignalNode *node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id); 186520d4f6da7324dece455eed2b64e3073895306440Michael Natterer 186620d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_assert (node != NULL); /* paranoid */ 186720d4f6da7324dece455eed2b64e3073895306440Michael Natterer 186820d4f6da7324dece455eed2b64e3073895306440Michael Natterer /* we should probably do the same parameter checks as g_signal_emit() here. 186920d4f6da7324dece455eed2b64e3073895306440Michael Natterer */ 187020d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (emission->chain_type != G_TYPE_NONE) 187120d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 187220d4f6da7324dece455eed2b64e3073895306440Michael Natterer ClassClosure *cc = signal_find_class_closure (node, emission->chain_type); 187320d4f6da7324dece455eed2b64e3073895306440Michael Natterer 187420d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_assert (cc != NULL); /* closure currently in call stack */ 187520d4f6da7324dece455eed2b64e3073895306440Michael Natterer 187620d4f6da7324dece455eed2b64e3073895306440Michael Natterer n_params = node->n_params; 187720d4f6da7324dece455eed2b64e3073895306440Michael Natterer restore_type = cc->instance_type; 187820d4f6da7324dece455eed2b64e3073895306440Michael Natterer cc = signal_find_class_closure (node, g_type_parent (cc->instance_type)); 187920d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (cc && cc->instance_type != restore_type) 188020d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 188120d4f6da7324dece455eed2b64e3073895306440Michael Natterer closure = cc->closure; 188220d4f6da7324dece455eed2b64e3073895306440Michael Natterer chain_type = cc->instance_type; 188320d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 188420d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 188520d4f6da7324dece455eed2b64e3073895306440Michael Natterer else 188620d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_warning ("%s: signal id `%u' cannot be chained from current emission stage for instance `%p'", G_STRLOC, node->signal_id, instance); 188720d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 188820d4f6da7324dece455eed2b64e3073895306440Michael Natterer else 188920d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_warning ("%s: no signal is currently being emitted for instance `%p'", G_STRLOC, instance); 189020d4f6da7324dece455eed2b64e3073895306440Michael Natterer 189120d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (closure) 189220d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 189320d4f6da7324dece455eed2b64e3073895306440Michael Natterer emission->chain_type = chain_type; 189420d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_UNLOCK (); 189520d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_closure_invoke (closure, 189620d4f6da7324dece455eed2b64e3073895306440Michael Natterer return_value, 189720d4f6da7324dece455eed2b64e3073895306440Michael Natterer n_params + 1, 189820d4f6da7324dece455eed2b64e3073895306440Michael Natterer instance_and_params, 189920d4f6da7324dece455eed2b64e3073895306440Michael Natterer &emission->ihint); 190020d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_LOCK (); 190120d4f6da7324dece455eed2b64e3073895306440Michael Natterer emission->chain_type = restore_type; 190220d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 190320d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_UNLOCK (); 190420d4f6da7324dece455eed2b64e3073895306440Michael Natterer} 190520d4f6da7324dece455eed2b64e3073895306440Michael Natterer 190620d4f6da7324dece455eed2b64e3073895306440Michael Natterer/** 190720d4f6da7324dece455eed2b64e3073895306440Michael Natterer * g_signal_chain_from_overridden_handler: 190820d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @instance: the instance the signal is being emitted on. 190920d4f6da7324dece455eed2b64e3073895306440Michael Natterer * @...: parameters to be passed to the parent class closure, followed by a 191020d4f6da7324dece455eed2b64e3073895306440Michael Natterer * location for the return value. If the return type of the signal 191120d4f6da7324dece455eed2b64e3073895306440Michael Natterer * is #G_TYPE_NONE, the return value location can be omitted. 191220d4f6da7324dece455eed2b64e3073895306440Michael Natterer * 191320d4f6da7324dece455eed2b64e3073895306440Michael Natterer * Calls the original class closure of a signal. This function should 191420d4f6da7324dece455eed2b64e3073895306440Michael Natterer * only be called from an overridden class closure; see 191520d4f6da7324dece455eed2b64e3073895306440Michael Natterer * g_signal_override_class_closure() and 191620d4f6da7324dece455eed2b64e3073895306440Michael Natterer * g_signal_override_class_handler(). 191720d4f6da7324dece455eed2b64e3073895306440Michael Natterer * 191820d4f6da7324dece455eed2b64e3073895306440Michael Natterer * Since: 2.18 191920d4f6da7324dece455eed2b64e3073895306440Michael Natterer */ 1920864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterervoid 192120d4f6da7324dece455eed2b64e3073895306440Michael Nattererg_signal_chain_from_overridden_handler (gpointer instance, 192220d4f6da7324dece455eed2b64e3073895306440Michael Natterer ...) 192320d4f6da7324dece455eed2b64e3073895306440Michael Natterer{ 192420d4f6da7324dece455eed2b64e3073895306440Michael Natterer GType chain_type = 0, restore_type = 0; 192520d4f6da7324dece455eed2b64e3073895306440Michael Natterer Emission *emission = NULL; 192620d4f6da7324dece455eed2b64e3073895306440Michael Natterer GClosure *closure = NULL; 192720d4f6da7324dece455eed2b64e3073895306440Michael Natterer SignalNode *node; 192820d4f6da7324dece455eed2b64e3073895306440Michael Natterer guint n_params = 0; 1929864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer 193020d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 193120d4f6da7324dece455eed2b64e3073895306440Michael Natterer 193220d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_LOCK (); 193320d4f6da7324dece455eed2b64e3073895306440Michael Natterer emission = emission_find_innermost (instance); 193420d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (emission) 193520d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 193620d4f6da7324dece455eed2b64e3073895306440Michael Natterer node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id); 193720d4f6da7324dece455eed2b64e3073895306440Michael Natterer 193820d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_assert (node != NULL); /* paranoid */ 193920d4f6da7324dece455eed2b64e3073895306440Michael Natterer 194020d4f6da7324dece455eed2b64e3073895306440Michael Natterer /* we should probably do the same parameter checks as g_signal_emit() here. 194120d4f6da7324dece455eed2b64e3073895306440Michael Natterer */ 194220d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (emission->chain_type != G_TYPE_NONE) 194320d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 194420d4f6da7324dece455eed2b64e3073895306440Michael Natterer ClassClosure *cc = signal_find_class_closure (node, emission->chain_type); 194520d4f6da7324dece455eed2b64e3073895306440Michael Natterer 194620d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_assert (cc != NULL); /* closure currently in call stack */ 194720d4f6da7324dece455eed2b64e3073895306440Michael Natterer 194820d4f6da7324dece455eed2b64e3073895306440Michael Natterer n_params = node->n_params; 194920d4f6da7324dece455eed2b64e3073895306440Michael Natterer restore_type = cc->instance_type; 195020d4f6da7324dece455eed2b64e3073895306440Michael Natterer cc = signal_find_class_closure (node, g_type_parent (cc->instance_type)); 195120d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (cc && cc->instance_type != restore_type) 195220d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 195320d4f6da7324dece455eed2b64e3073895306440Michael Natterer closure = cc->closure; 195420d4f6da7324dece455eed2b64e3073895306440Michael Natterer chain_type = cc->instance_type; 195520d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 1956864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer } 195720d4f6da7324dece455eed2b64e3073895306440Michael Natterer else 195820d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_warning ("%s: signal id `%u' cannot be chained from current emission stage for instance `%p'", G_STRLOC, node->signal_id, instance); 195920d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 196020d4f6da7324dece455eed2b64e3073895306440Michael Natterer else 196120d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_warning ("%s: no signal is currently being emitted for instance `%p'", G_STRLOC, instance); 196220d4f6da7324dece455eed2b64e3073895306440Michael Natterer 196320d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (closure) 196420d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 196520d4f6da7324dece455eed2b64e3073895306440Michael Natterer GValue *instance_and_params; 196620d4f6da7324dece455eed2b64e3073895306440Michael Natterer GType signal_return_type; 196720d4f6da7324dece455eed2b64e3073895306440Michael Natterer GValue *param_values; 196820d4f6da7324dece455eed2b64e3073895306440Michael Natterer va_list var_args; 196920d4f6da7324dece455eed2b64e3073895306440Michael Natterer guint i; 197020d4f6da7324dece455eed2b64e3073895306440Michael Natterer 197120d4f6da7324dece455eed2b64e3073895306440Michael Natterer va_start (var_args, instance); 197220d4f6da7324dece455eed2b64e3073895306440Michael Natterer 197320d4f6da7324dece455eed2b64e3073895306440Michael Natterer signal_return_type = node->return_type; 197420d4f6da7324dece455eed2b64e3073895306440Michael Natterer instance_and_params = g_slice_alloc (sizeof (GValue) * (n_params + 1)); 197520d4f6da7324dece455eed2b64e3073895306440Michael Natterer param_values = instance_and_params + 1; 197620d4f6da7324dece455eed2b64e3073895306440Michael Natterer 197720d4f6da7324dece455eed2b64e3073895306440Michael Natterer for (i = 0; i < node->n_params; i++) 197820d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 197920d4f6da7324dece455eed2b64e3073895306440Michael Natterer gchar *error; 198020d4f6da7324dece455eed2b64e3073895306440Michael Natterer GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE; 198120d4f6da7324dece455eed2b64e3073895306440Michael Natterer gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE; 198220d4f6da7324dece455eed2b64e3073895306440Michael Natterer 198320d4f6da7324dece455eed2b64e3073895306440Michael Natterer param_values[i].g_type = 0; 198420d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_UNLOCK (); 198520d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_value_init (param_values + i, ptype); 198620d4f6da7324dece455eed2b64e3073895306440Michael Natterer G_VALUE_COLLECT (param_values + i, 198720d4f6da7324dece455eed2b64e3073895306440Michael Natterer var_args, 198820d4f6da7324dece455eed2b64e3073895306440Michael Natterer static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, 198920d4f6da7324dece455eed2b64e3073895306440Michael Natterer &error); 199020d4f6da7324dece455eed2b64e3073895306440Michael Natterer if (error) 199120d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 199220d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_warning ("%s: %s", G_STRLOC, error); 199320d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_free (error); 199420d4f6da7324dece455eed2b64e3073895306440Michael Natterer 199520d4f6da7324dece455eed2b64e3073895306440Michael Natterer /* we purposely leak the value here, it might not be 199620d4f6da7324dece455eed2b64e3073895306440Michael Natterer * in a sane state if an error condition occoured 199720d4f6da7324dece455eed2b64e3073895306440Michael Natterer */ 199820d4f6da7324dece455eed2b64e3073895306440Michael Natterer while (i--) 199920d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_value_unset (param_values + i); 200020d4f6da7324dece455eed2b64e3073895306440Michael Natterer 200120d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_slice_free1 (sizeof (GValue) * (n_params + 1), instance_and_params); 200220d4f6da7324dece455eed2b64e3073895306440Michael Natterer va_end (var_args); 200320d4f6da7324dece455eed2b64e3073895306440Michael Natterer return; 200420d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 200520d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_LOCK (); 200620d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 200720d4f6da7324dece455eed2b64e3073895306440Michael Natterer 200820d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_UNLOCK (); 200920d4f6da7324dece455eed2b64e3073895306440Michael Natterer instance_and_params->g_type = 0; 201020d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance)); 201120d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_value_set_instance (instance_and_params, instance); 201220d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_LOCK (); 201320d4f6da7324dece455eed2b64e3073895306440Michael Natterer 201420d4f6da7324dece455eed2b64e3073895306440Michael Natterer emission->chain_type = chain_type; 201520d4f6da7324dece455eed2b64e3073895306440Michael Natterer SIGNAL_UNLOCK (); 201620d4f6da7324dece455eed2b64e3073895306440Michael Natterer 2017864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer if (signal_return_type == G_TYPE_NONE) 201820d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 201920d4f6da7324dece455eed2b64e3073895306440Michael Natterer g_closure_invoke (closure, 202020d4f6da7324dece455eed2b64e3073895306440Michael Natterer NULL, 202120d4f6da7324dece455eed2b64e3073895306440Michael Natterer n_params + 1, 202220d4f6da7324dece455eed2b64e3073895306440Michael Natterer instance_and_params, 202320d4f6da7324dece455eed2b64e3073895306440Michael Natterer &emission->ihint); 202420d4f6da7324dece455eed2b64e3073895306440Michael Natterer } 202520d4f6da7324dece455eed2b64e3073895306440Michael Natterer else 202620d4f6da7324dece455eed2b64e3073895306440Michael Natterer { 202720d4f6da7324dece455eed2b64e3073895306440Michael Natterer GValue return_value = { 0, }; 2028356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost gchar *error = NULL; 2029356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE; 20306347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE; 20316347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 20326347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_value_init (&return_value, rtype); 2033356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2034356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_closure_invoke (closure, 203569c000f069ae934760678577506495fed061d9e4Tim Janik &return_value, 203669c000f069ae934760678577506495fed061d9e4Tim Janik n_params + 1, 203769c000f069ae934760678577506495fed061d9e4Tim Janik instance_and_params, 203869c000f069ae934760678577506495fed061d9e4Tim Janik &emission->ihint); 203969c000f069ae934760678577506495fed061d9e4Tim Janik 204069c000f069ae934760678577506495fed061d9e4Tim Janik G_VALUE_LCOPY (&return_value, 204169c000f069ae934760678577506495fed061d9e4Tim Janik var_args, 204269c000f069ae934760678577506495fed061d9e4Tim Janik static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, 204369c000f069ae934760678577506495fed061d9e4Tim Janik &error); 204469c000f069ae934760678577506495fed061d9e4Tim Janik if (!error) 204569c000f069ae934760678577506495fed061d9e4Tim Janik { 204669c000f069ae934760678577506495fed061d9e4Tim Janik g_value_unset (&return_value); 204769c000f069ae934760678577506495fed061d9e4Tim Janik } 204869c000f069ae934760678577506495fed061d9e4Tim Janik else 2049356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 2050356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_warning ("%s: %s", G_STRLOC, error); 2051356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_free (error); 2052356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2053356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost /* we purposely leak the value here, it might not be 2054356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * in a sane state if an error condition occured 20556347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer */ 2056356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 20576347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer } 2058356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 20596347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer for (i = 0; i < n_params; i++) 2060356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_value_unset (param_values + i); 2061356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_value_unset (instance_and_params); 2062abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik g_slice_free1 (sizeof (GValue) * (n_params + 1), instance_and_params); 20633cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 20643cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik va_end (var_args); 20653cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik 20663cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik SIGNAL_LOCK (); 20673cc60a9ab1df2dcf393a15b8a66e0602817646bdTim Janik emission->chain_type = restore_type; 2068ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2069ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 2070abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik} 2071ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2072ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/** 2073ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * g_signal_get_invocation_hint: 2074ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @instance: the instance to query 2075ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 20769369e1e022978100c521634a968968a901dd934cTim Janik * Returns the invocation hint of the innermost signal emission of instance. 2077ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 2078e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * Returns: the invocation hint of the innermost signal emission. 2079830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik */ 2080e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim JanikGSignalInvocationHint* 2081e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_get_invocation_hint (gpointer instance) 2082e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 2083e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik Emission *emission = NULL; 2084e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2085e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL); 2086e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2087e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_LOCK (); 2088abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik emission = emission_find_innermost (instance); 2089e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 2090e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 209112a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik return emission ? &emission->ihint : NULL; 2092e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 2093e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2094e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik/** 2095e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * g_signal_connect_closure_by_id: 2096ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @instance: the instance to connect to. 2097ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @signal_id: the id of the signal. 2098ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @detail: the detail. 20999369e1e022978100c521634a968968a901dd934cTim Janik * @closure: the closure to connect. 2100ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @after: whether the handler should be called before or after the 2101abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik * default handler of the signal. 2102ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 2103ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Connects a closure to a signal for a particular object. 2104356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 2105356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Returns: the handler id 2106356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost */ 2107356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostgulong 2108356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostg_signal_connect_closure_by_id (gpointer instance, 21096347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer guint signal_id, 2110356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GQuark detail, 21116347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer GClosure *closure, 2112356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost gboolean after) 21136347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer{ 2114356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SignalNode *node; 2115356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost gulong handler_seq_no = 0; 2116abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik 2117e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 2118e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (signal_id > 0, 0); 2119e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_return_val_if_fail (closure != NULL, 0); 2120e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2121e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_LOCK (); 2122abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 2123abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik if (node) 2124e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 2125e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 2126e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 2127e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 2128e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 2129e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 2130e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 21319369e1e022978100c521634a968968a901dd934cTim Janik Handler *handler = handler_new (after); 2132e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2133e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_seq_no = handler->sequential_number; 2134e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->detail = detail; 2135e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->closure = g_closure_ref (closure); 2136e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_closure_sink (closure); 2137e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_insert (signal_id, instance, handler); 2138e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure)) 2139e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_closure_set_marshal (closure, node->c_marshaller); 2140e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2141e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2142e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 2143e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 2144e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 2145e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2146abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik return handler_seq_no; 2147e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 2148e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 214912a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik/** 2150e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * g_signal_connect_closure: 2151e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @instance: the instance to connect to. 2152e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @detailed_signal: a string of the form "signal-name::detail". 2153e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @closure: the closure to connect. 2154e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @after: whether the handler should be called before or after the 2155e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * default handler of the signal. 2156e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * 21579369e1e022978100c521634a968968a901dd934cTim Janik * Connects a closure to a signal for a particular object. 2158e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * 2159abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik * Returns: the handler id 2160e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik */ 2161e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikgulong 2162356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostg_signal_connect_closure (gpointer instance, 2163356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost const gchar *detailed_signal, 2164356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GClosure *closure, 2165356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost gboolean after) 2166356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 2167356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost guint signal_id; 2168356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost gulong handler_seq_no = 0; 2169356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GQuark detail = 0; 21706347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer GType itype; 2171356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2172356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 2173356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_return_val_if_fail (detailed_signal != NULL, 0); 2174356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_return_val_if_fail (closure != NULL, 0); 2175356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 21766347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer SIGNAL_LOCK (); 2177356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost itype = G_TYPE_FROM_INSTANCE (instance); 2178356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); 2179abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik if (signal_id) 2180e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 2181e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 2182e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2183e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 2184e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); 2185fd860cb987e0bc77b8a69363576c01069b40244eTim Janik else if (!g_type_is_a (itype, node->itype)) 2186e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 2187abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik else 2188abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik { 2189e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik Handler *handler = handler_new (after); 2190e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2191fd860cb987e0bc77b8a69363576c01069b40244eTim Janik handler_seq_no = handler->sequential_number; 2192fd860cb987e0bc77b8a69363576c01069b40244eTim Janik handler->detail = detail; 2193e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler->closure = g_closure_ref (closure); 2194e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_closure_sink (closure); 2195e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik handler_insert (signal_id, instance, handler); 2196e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) 2197fd860cb987e0bc77b8a69363576c01069b40244eTim Janik g_closure_set_marshal (handler->closure, node->c_marshaller); 2198fd860cb987e0bc77b8a69363576c01069b40244eTim Janik } 2199fd860cb987e0bc77b8a69363576c01069b40244eTim Janik } 22009369e1e022978100c521634a968968a901dd934cTim Janik else 2201e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 2202e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 2203e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2204e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return handler_seq_no; 2205e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 2206e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2207e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik/** 2208e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * g_signal_connect_data: 2209e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @instance: the instance to connect to. 2210e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @detailed_signal: a string of the form "signal-name::detail". 2211e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @c_handler: the #GCallback to connect. 2212e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @data: data to pass to @c_handler calls. 2213e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @destroy_data: a #GClosureNotify for @data. 2214e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @connect_flags: a combination of #GConnectFlags. 2215abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik * 2216e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * Connects a #GCallback function to a signal for a particular object. Similar 2217e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * to g_signal_connect(), but allows to provide a #GClosureNotify for the data 221812a0d19c11c29e3d4b7a5f02a07576309e2787a6Tim Janik * which will be called when the signal handler is disconnected and no longer 2219e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * used. Specify @connect_flags if you need <literal>..._after()</literal> or 2220e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * <literal>..._swapped()</literal> variants of this function. 2221e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * 2222e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * Returns: the handler id 2223e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik */ 2224e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikgulong 2225e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_connect_data (gpointer instance, 22269369e1e022978100c521634a968968a901dd934cTim Janik const gchar *detailed_signal, 2227e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GCallback c_handler, 2228abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik gpointer data, 2229e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GClosureNotify destroy_data, 2230e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GConnectFlags connect_flags) 2231356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 2232356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost guint signal_id; 2233356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost gulong handler_seq_no = 0; 2234356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GQuark detail = 0; 22356347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer GType itype; 22366347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer gboolean swapped, after; 22376347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 22386347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 22396347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_return_val_if_fail (detailed_signal != NULL, 0); 2240356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_return_val_if_fail (c_handler != NULL, 0); 22416347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 22426347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE; 2243356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost after = (connect_flags & G_CONNECT_AFTER) != FALSE; 2244356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2245ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 2246cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik itype = G_TYPE_FROM_INSTANCE (instance); 2247abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); 2248cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (signal_id) 2249cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 2250cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 2251cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2252cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 2253cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); 22549369e1e022978100c521634a968968a901dd934cTim Janik else if (!g_type_is_a (itype, node->itype)) 2255cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 2256cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik else 2257cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 2258cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik Handler *handler = handler_new (after); 2259cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2260cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler_seq_no = handler->sequential_number; 2261cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler->detail = detail; 2262cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data)); 2263cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_closure_sink (handler->closure); 2264cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler_insert (signal_id, instance, handler); 2265abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) 22669369e1e022978100c521634a968968a901dd934cTim Janik g_closure_set_marshal (handler->closure, node->c_marshaller); 2267cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik } 2268cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik } 2269356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost else 2270356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 2271356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 2272356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 22736347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer return handler_seq_no; 22746347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer} 22756347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 22766347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer/** 22776347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * g_signal_handler_block: 22786347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @instance: The instance to block the signal handler of. 22796347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @handler_id: Handler id of the handler to be blocked. 22806347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * 22816347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * Blocks a handler of an instance so it will not be called during any 22826347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * signal emissions unless it is unblocked again. Thus "blocking" a 22836347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * signal handler means to temporarily deactive it, a signal handler 22846347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * has to be unblocked exactly the same amount of times it has been 22856347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * blocked before to become active again. 2286356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 2287356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * The @handler_id has to be a valid signal handler id, connected to a 2288cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik * signal of @instance. 2289cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik */ 2290abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janikvoid 2291cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handler_block (gpointer instance, 2292cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gulong handler_id) 2293cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{ 2294cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik Handler *handler; 2295cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2296cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 22979369e1e022978100c521634a968968a901dd934cTim Janik g_return_if_fail (handler_id > 0); 2298cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2299cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik SIGNAL_LOCK (); 2300cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik handler = handler_lookup (instance, handler_id, NULL); 2301cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (handler) 2302cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 2303cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#ifndef G_DISABLE_CHECKS 2304abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1) 2305cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG); 2306cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik#endif 2307abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik handler->block_count += 1; 23089369e1e022978100c521634a968968a901dd934cTim Janik } 2309cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik else 2310cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); 2311356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 2312356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost} 2313356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2314356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost/** 23156347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * g_signal_handler_unblock: 23166347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @instance: The instance to unblock the signal handler of. 23176347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @handler_id: Handler id of the handler to be unblocked. 2318356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 23196347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * Undoes the effect of a previous g_signal_handler_block() call. A 23206347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * blocked handler is skipped during signal emissions and will not be 2321356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * invoked, unblocking it (for exactly the amount of times it has been 2322356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * blocked before) reverts its "blocked" state, so the handler will be 2323cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik * recognized by the signal system and is called upon future or 2324ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * currently ongoing signal emissions (since the order in which 2325abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik * handlers are called during signal emissions is deterministic, 2326ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * whether the unblocked handler in question is called as part of a 2327ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * currently ongoing emission depends on how far that emission has 2328ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * proceeded yet). 2329ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 2330ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * The @handler_id has to be a valid id of a signal handler that is 2331ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * connected to a signal of @instance and is currently blocked. 2332ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 23339369e1e022978100c521634a968968a901dd934cTim Janikvoid 2334ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_handler_unblock (gpointer instance, 2335ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gulong handler_id) 2336ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 2337abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik Handler *handler; 2338ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2339ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 2340ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (handler_id > 0); 2341ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2342abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik SIGNAL_LOCK (); 23439369e1e022978100c521634a968968a901dd934cTim Janik handler = handler_lookup (instance, handler_id, NULL); 2344ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler) 2345ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2346356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (handler->block_count) 2347356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost handler->block_count -= 1; 2348356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost else 2349356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_warning (G_STRLOC ": handler `%lu' of instance `%p' is not blocked", handler_id, instance); 23506347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer } 2351356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost else 23526347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); 2353356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 2354356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost} 235572df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik 235672df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik/** 235772df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * g_signal_handler_disconnect: 235872df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * @instance: The instance to remove the signal handler from. 235972df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * @handler_id: Handler id of the handler to be disconnected. 236072df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * 236172df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * Disconnects a handler from an instance so it will not be called during 236272df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * any future or currently ongoing emissions of the signal it has been 236372df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * connected to. The @handler_id becomes invalid and may be reused. 23649369e1e022978100c521634a968968a901dd934cTim Janik * 236572df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * The @handler_id has to be a valid signal handler id, connected to a 236672df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik * signal of @instance. 23679369e1e022978100c521634a968968a901dd934cTim Janik */ 236872df5e6cabe02f155ff767650cdaf10046c26e0eTim Janikvoid 236972df5e6cabe02f155ff767650cdaf10046c26e0eTim Janikg_signal_handler_disconnect (gpointer instance, 237072df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik gulong handler_id) 237172df5e6cabe02f155ff767650cdaf10046c26e0eTim Janik{ 2372ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler; 237383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik guint signal_id; 2374ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2375ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 2376ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (handler_id > 0); 2377ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2378ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 23799369e1e022978100c521634a968968a901dd934cTim Janik handler = handler_lookup (instance, handler_id, &signal_id); 2380ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler) 2381ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2382ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->sequential_number = 0; 2383ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->block_count = 1; 2384ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_unref_R (signal_id, instance, handler); 2385ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 2386ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 238783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); 2388ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 2389ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 2390a05a4b766073561baea10ba697fc7042c308719cTim Janik 2391ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/** 2392ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * g_signal_handler_is_connected: 2393ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @instance: The instance where a signal handler is sought. 2394ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @handler_id: the handler id. 2395ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 2396ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Returns whether @handler_id is the id of a handler connected to @instance. 2397ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 2398ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * Returns: whether @handler_id identifies a handler connected to @instance. 2399ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 2400ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikgboolean 2401ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikg_signal_handler_is_connected (gpointer instance, 2402abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik gulong handler_id) 2403ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 2404abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik Handler *handler; 2405ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gboolean connected; 2406ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2407ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 2408ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 24096d6e68f3e4d0387571039ef14685e5bb595c34a9Tim Janik SIGNAL_LOCK (); 2410ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler = handler_lookup (instance, handler_id, NULL); 24119369e1e022978100c521634a968968a901dd934cTim Janik connected = handler != NULL; 2412ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 2413ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2414356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost return connected; 2415356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost} 2416356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 24176347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterervoid 2418356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostg_signal_handlers_destroy (gpointer instance) 2419356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 2420356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GBSearchArray *hlbsa; 2421356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2422356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 2423356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 24246347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer SIGNAL_LOCK (); 2425356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); 2426356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (hlbsa) 2427356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 2428356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost guint i; 2429356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 24306347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer /* reentrancy caution, delete instance trace first */ 2431356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_hash_table_remove (g_handler_list_bsa_ht, instance); 2432356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2433abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik for (i = 0; i < hlbsa->n_nodes; i++) 2434cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 2435cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); 2436cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik Handler *handler = hlist->handlers; 2437cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2438cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik while (handler) 2439cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik { 2440cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik Handler *tmp = handler; 2441ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2442abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik handler = tmp->next; 2443ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp->block_count = 1; 2444cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik /* cruel unlink, this works because _all_ handlers vanish */ 2445cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik tmp->next = NULL; 244683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik tmp->prev = tmp; 2447cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik if (tmp->sequential_number) 2448ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 244983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik tmp->sequential_number = 0; 245083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik handler_unref_R (0, NULL, tmp); 24519369e1e022978100c521634a968968a901dd934cTim Janik } 245283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 245383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 245483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig); 2455abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik } 245683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik SIGNAL_UNLOCK (); 245783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik} 24589369e1e022978100c521634a968968a901dd934cTim Janik 2459ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik/** 246083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * g_signal_handler_find: 2461abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik * @instance: The instance owning the signal handler to be found. 2462ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @mask: Mask indicating which of @signal_id, @detail, @closure, @func 2463ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * and/or @data the handler has to match. 2464cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik * @signal_id: Signal the handler has to be connected to. 246583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * @detail: Signal detail the handler has to be connected to. 246683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * @closure: The closure the handler will invoke. 246783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * @func: The C closure callback of the handler (useless for non-C closures). 246883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * @data: The closure data of the handler's closure. 246983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * 247083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * Finds the first signal handler that matches certain selection criteria. 247183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * The criteria mask is passed as an OR-ed combination of #GSignalMatchType 247283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * flags, and the criteria values are passed as arguments. 2473abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik * The match @mask has to be non-0 for successful matches. 2474ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * If no handler was found, 0 is returned. 247583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * 2476cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik * Returns: A valid non-0 signal handler id for a successful match. 247783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik */ 247883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikgulong 247983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janikg_signal_handler_find (gpointer instance, 2480ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GSignalMatchType mask, 2481cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 2482abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik GQuark detail, 2483abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik GClosure *closure, 24849369e1e022978100c521634a968968a901dd934cTim Janik gpointer func, 2485abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik gpointer data) 24869369e1e022978100c521634a968968a901dd934cTim Janik{ 2487abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik gulong handler_seq_no = 0; 248883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 2489ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 249083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 2491cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2492ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (mask & G_SIGNAL_MATCH_MASK) 2493ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2494356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost HandlerMatch *mlist; 2495356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2496356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_LOCK (); 24976347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE); 2498356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (mlist) 2499356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 2500356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost handler_seq_no = mlist->handler->sequential_number; 2501356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost handler_match_free1_R (mlist, instance); 2502356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 2503356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 25046347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer } 2505356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 25066347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer return handler_seq_no; 2507356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost} 2508356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2509356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Koststatic guint 2510356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostsignal_handlers_foreach_matched_R (gpointer instance, 2511356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GSignalMatchType mask, 25126347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer guint signal_id, 2513356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GQuark detail, 2514356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GClosure *closure, 2515ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer func, 2516cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer data, 2517cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik void (*callback) (gpointer instance, 2518cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gulong handler_seq_no)) 2519cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{ 2520cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik HandlerMatch *mlist; 2521cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint n_handlers = 0; 2522cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2523ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE); 2524cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik while (mlist) 252583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik { 252610c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen n_handlers++; 252710c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen if (mlist->handler->sequential_number) 252883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik { 2529cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik SIGNAL_UNLOCK (); 2530cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik callback (instance, mlist->handler->sequential_number); 25319369e1e022978100c521634a968968a901dd934cTim Janik SIGNAL_LOCK (); 253283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 253383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik mlist = handler_match_free1_R (mlist, instance); 253483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 25359369e1e022978100c521634a968968a901dd934cTim Janik 2536cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik return n_handlers; 253783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik} 2538cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2539cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik/** 2540cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik * g_signal_handlers_block_matched: 2541356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @instance: The instance to block handlers from. 2542356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @mask: Mask indicating which of @signal_id, @detail, @closure, @func 2543356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * and/or @data the handlers have to match. 25446347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @signal_id: Signal the handlers have to be connected to. 2545356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @detail: Signal detail the handlers have to be connected to. 2546356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @closure: The closure the handlers will invoke. 2547356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @func: The C closure callback of the handlers (useless for non-C closures). 2548356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @data: The closure data of the handlers' closures. 2549356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 2550356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Blocks all handlers on an instance that match a certain selection criteria. 25516347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * The criteria mask is passed as an OR-ed combination of #GSignalMatchType 2552356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * flags, and the criteria values are passed as arguments. 2553356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC 2554356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches. 2555356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * If no handlers were found, 0 is returned, the number of blocked handlers 2556356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * otherwise. 2557356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 2558356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Returns: The number of handlers that matched. 2559356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost */ 25606347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Nattererguint 2561356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostg_signal_handlers_block_matched (gpointer instance, 2562356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GSignalMatchType mask, 2563cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 2564cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GQuark detail, 2565cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GClosure *closure, 2566cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer func, 2567cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer data) 2568cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{ 2569cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint n_handlers = 0; 2570cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2571cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 2572cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 2573ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 257410c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 257510c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen { 2576ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 2577cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 2578cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik closure, func, data, 25799369e1e022978100c521634a968968a901dd934cTim Janik g_signal_handler_block); 258083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik SIGNAL_UNLOCK (); 258183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 258283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 25839369e1e022978100c521634a968968a901dd934cTim Janik return n_handlers; 2584cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik} 258583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 2586cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik/** 2587cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik * g_signal_handlers_unblock_matched: 2588cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik * @instance: The instance to unblock handlers from. 2589356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @mask: Mask indicating which of @signal_id, @detail, @closure, @func 2590356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * and/or @data the handlers have to match. 2591356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @signal_id: Signal the handlers have to be connected to. 25926347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @detail: Signal detail the handlers have to be connected to. 2593356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @closure: The closure the handlers will invoke. 2594356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @func: The C closure callback of the handlers (useless for non-C closures). 2595356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @data: The closure data of the handlers' closures. 2596356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 2597356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Unblocks all handlers on an instance that match a certain selection 2598356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * criteria. The criteria mask is passed as an OR-ed combination of 25996347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * #GSignalMatchType flags, and the criteria values are passed as arguments. 26006347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC 26016347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches. 26026347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * If no handlers were found, 0 is returned, the number of unblocked handlers 26036347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * otherwise. The match criteria should not apply to any handlers that are 26046347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * not currently blocked. 26056347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * 26066347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * Returns: The number of handlers that matched. 26076347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer */ 26086347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Nattererguint 2609356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kostg_signal_handlers_unblock_matched (gpointer instance, 2610356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost GSignalMatchType mask, 2611cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 2612cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GQuark detail, 2613cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GClosure *closure, 2614cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer func, 2615cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik gpointer data) 2616cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik{ 2617cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint n_handlers = 0; 2618cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2619cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 2620cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 262183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 262210c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 262310c5cfa36f92c7290c73db78d10fb37cf60f8a7dMatthias Clasen { 262483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik SIGNAL_LOCK (); 2625cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 2626cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik closure, func, data, 26279369e1e022978100c521634a968968a901dd934cTim Janik g_signal_handler_unblock); 262883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik SIGNAL_UNLOCK (); 262983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik } 263083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 26319369e1e022978100c521634a968968a901dd934cTim Janik return n_handlers; 2632cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik} 263383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 2634cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik/** 2635ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * g_signal_handlers_disconnect_matched: 2636ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @instance: The instance to remove handlers from. 2637356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @mask: Mask indicating which of @signal_id, @detail, @closure, @func 2638356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * and/or @data the handlers have to match. 2639356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @signal_id: Signal the handlers have to be connected to. 2640356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @detail: Signal detail the handlers have to be connected to. 2641356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @closure: The closure the handlers will invoke. 2642356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * @func: The C closure callback of the handlers (useless for non-C closures). 26436347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * @data: The closure data of the handlers' closures. 2644356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * 2645356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Disconnects all handlers on an instance that match a certain 26466347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * selection criteria. The criteria mask is passed as an OR-ed 26476347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * combination of #GSignalMatchType flags, and the criteria values are 26486347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * passed as arguments. Passing at least one of the 26496347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC or 26506347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * %G_SIGNAL_MATCH_DATA match flags is required for successful 26516347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * matches. If no handlers were found, 0 is returned, the number of 26526347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * disconnected handlers otherwise. 26536347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * 2654356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost * Returns: The number of handlers that matched. 2655ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 2656cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikguint 2657cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janikg_signal_handlers_disconnect_matched (gpointer instance, 2658cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik GSignalMatchType mask, 2659cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik guint signal_id, 2660ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GQuark detail, 266183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik GClosure *closure, 266283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik gpointer func, 2663ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer data) 2664ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 2665ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint n_handlers = 0; 2666ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 26679369e1e022978100c521634a968968a901dd934cTim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); 2668830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); 2669830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 2670830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) 2671830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 2672830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik SIGNAL_LOCK (); 2673830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, 2674830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik closure, func, data, 26759369e1e022978100c521634a968968a901dd934cTim Janik g_signal_handler_disconnect); 2676830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik SIGNAL_UNLOCK (); 2677830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 2678830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 267983c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik return n_handlers; 268083c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik} 268183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik 268283c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik/** 268383c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * g_signal_has_handler_pending: 268483c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * @instance: the object whose signal handlers are sought. 268583c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * @signal_id: the signal id. 268683c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * @detail: the detail. 268783c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * @may_be_blocked: whether blocked handlers should count as match. 268883c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * 26899369e1e022978100c521634a968968a901dd934cTim Janik * Returns whether there are any handlers connected to @instance for the 2690ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * given signal id and detail. 269183c45024e3d3a56ac17eb08dcddae048005bbb71Tim Janik * 2692ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * One example of when you might use this is when the arguments to the 2693ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * signal are difficult to compute. A class implementor may opt to not 2694779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * emit the signal if no one is attached anyway, thus saving the cost 2695779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * of building the arguments. 2696779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * 2697779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * Returns: %TRUE if a handler is connected to the signal, %FALSE 2698779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * otherwise. 2699779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik */ 2700779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janikgboolean 2701779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janikg_signal_has_handler_pending (gpointer instance, 2702779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik guint signal_id, 2703779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik GQuark detail, 2704779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik gboolean may_be_blocked) 2705779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik{ 2706779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik HandlerMatch *mlist; 2707779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik gboolean has_pending; 2708779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik 2709779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); 2710779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik g_return_val_if_fail (signal_id > 0, FALSE); 2711779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik 2712779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik SIGNAL_LOCK (); 2713779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik if (detail) 2714779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik { 2715779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); 2716779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik 2717779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik if (!(node->flags & G_SIGNAL_DETAILED)) 2718779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik { 2719779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 2720779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik SIGNAL_UNLOCK (); 2721779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik return FALSE; 2722779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik } 2723779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik } 2724779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik mlist = handlers_find (instance, 2725779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), 2726779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik signal_id, detail, NULL, NULL, NULL, TRUE); 2727779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik if (mlist) 2728779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik { 2729779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik has_pending = TRUE; 2730779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik handler_match_free1_R (mlist, instance); 2731779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik } 2732779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik else 2733779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik has_pending = FALSE; 2734779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik SIGNAL_UNLOCK (); 2735779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik 2736779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik return has_pending; 2737779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik} 2738356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2739356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Koststatic inline gboolean 27406347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterersignal_check_skip_emission (SignalNode *node, 27416347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer gpointer instance, 27426347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer GQuark detail) 2743356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost{ 2744356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost HandlerList *hlist; 2745356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2746356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost /* are we able to check for NULL class handlers? */ 27476347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer if (!node->test_class_offset) 27486347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer return FALSE; 27496347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer 2750356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost /* are there emission hooks pending? */ 2751356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (node->emission_hooks && node->emission_hooks->hooks) 2752356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost return FALSE; 2753ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2754ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* is there a non-NULL class handler? */ 2755ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (node->test_class_offset != TEST_CLASS_MAGIC) 2756830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 2757ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GTypeClass *class = G_TYPE_INSTANCE_GET_CLASS (instance, G_TYPE_FROM_INSTANCE (instance), GTypeClass); 2758ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2759e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (G_STRUCT_MEMBER (gpointer, class, node->test_class_offset)) 2760e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return FALSE; 2761624a3c9689a9538af7df04aab389423edc82b51aDarin Adler } 27622147c486b0afb90ea32fdce9fefedcbebc2375a6Kjartan Maraas 2763ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* are signals being debugged? */ 2764624a3c9689a9538af7df04aab389423edc82b51aDarin Adler#ifdef G_ENABLE_DEBUG 2765ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik IF_DEBUG (SIGNALS, g_trace_instance_signals || g_trap_instance_signals) 2766ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return FALSE; 276737e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik#endif /* G_ENABLE_DEBUG */ 2768ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 2769ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik /* is this a no-recurse signal already in emission? */ 2770e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (node->flags & G_SIGNAL_NO_RECURSE && 27712147c486b0afb90ea32fdce9fefedcbebc2375a6Kjartan Maraas emission_find (g_restart_emissions, node->signal_id, detail, instance)) 2772ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return FALSE; 27732147c486b0afb90ea32fdce9fefedcbebc2375a6Kjartan Maraas 27742147c486b0afb90ea32fdce9fefedcbebc2375a6Kjartan Maraas /* do we have pending handlers? */ 27759369e1e022978100c521634a968968a901dd934cTim Janik hlist = handler_list_lookup (node->signal_id, instance); 2776ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (hlist && hlist->handlers) 2777e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return FALSE; 2778cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2779cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik /* none of the above, no emission required */ 27809369e1e022978100c521634a968968a901dd934cTim Janik return TRUE; 2781cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik} 2782cfe0780d3ea8a5a9bdd3497926437cde42298086Tim Janik 2783782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik/** 2784830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik * g_signal_emitv: 2785830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik * @instance_and_params: argument list for the signal emission. The first 2786830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik * element in the array is a #GValue for the instance the signal is 27879369e1e022978100c521634a968968a901dd934cTim Janik * being emitted on. The rest are any arguments to be passed to the 2788830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik * signal. 2789830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik * @signal_id: the signal id 2790ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * @detail: the detail 279137e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik * @return_value: Location to store the return value of the signal emission. 2792ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * 2793e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * Emits a signal. 2794e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * 2795116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor * Note that g_signal_emitv() doesn't change @return_value if no handlers are 2796ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik * connected, in contrast to g_signal_emit() and g_signal_emit_valist(). 2797ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik */ 2798ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janikvoid 27999369e1e022978100c521634a968968a901dd934cTim Janikg_signal_emitv (const GValue *instance_and_params, 2800ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik guint signal_id, 2801ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GQuark detail, 2802ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GValue *return_value) 2803ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik{ 2804ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gpointer instance; 2805ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalNode *node; 2806e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#ifdef G_ENABLE_DEBUG 2807e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik const GValue *param_values; 2808116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor guint i; 2809ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif 28109369e1e022978100c521634a968968a901dd934cTim Janik 2811ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (instance_and_params != NULL); 2812ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik instance = g_value_peek_pointer (instance_and_params); 281337e4b8c87e8b0574a806a6f1d2284e4ab45341b3Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 2814ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (signal_id > 0); 2815e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2816e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#ifdef G_ENABLE_DEBUG 2817116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor param_values = instance_and_params + 1; 2818ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#endif 2819ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 28209369e1e022978100c521634a968968a901dd934cTim Janik SIGNAL_LOCK (); 2821ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 2822ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 2823ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 2824ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 2825ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 2826782a8e2e7c69c3d98bd69bcfdbb65ded520576f4Tim Janik return; 2827e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2828779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik#ifdef G_ENABLE_DEBUG 2829779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 2830779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik { 2831779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 2832779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik SIGNAL_UNLOCK (); 2833779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik return; 2834779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik } 2835779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik for (i = 0; i < node->n_params; i++) 2836779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 28379369e1e022978100c521634a968968a901dd934cTim Janik { 2838e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'", 2839ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik G_STRLOC, 2840ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik type_debug_name (node->param_types[i]), 2841356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost i, 2842356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->name, 2843356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost G_VALUE_TYPE_NAME (param_values + i)); 2844356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 2845356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost return; 2846356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 2847356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (node->return_type != G_TYPE_NONE) 2848356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 28496347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer if (!return_value) 28506347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer { 28516347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)", 2852356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost G_STRLOC, 2853356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost type_debug_name (node->return_type), 2854356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->name); 2855e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 2856e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return; 2857e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2858e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) 2859e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 2860e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'", 2861864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer G_STRLOC, 2862e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik type_debug_name (node->return_type), 2863e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik node->name, 2864e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_VALUE_TYPE_NAME (return_value)); 2865e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik SIGNAL_UNLOCK (); 2866e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik return; 2867e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2868e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2869e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else 28709369e1e022978100c521634a968968a901dd934cTim Janik return_value = NULL; 2871e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#endif /* G_ENABLE_DEBUG */ 2872e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2873e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* optimize NOP emissions */ 2874e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_check_skip_emission (node, instance, detail)) 28759369e1e022978100c521634a968968a901dd934cTim Janik { 2876e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* nothing to do to emit this signal */ 2877e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 2878e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* g_printerr ("omitting emission of \"%s\"\n", node->name); */ 2879e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return; 2880e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2881e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 28829369e1e022978100c521634a968968a901dd934cTim Janik SIGNAL_UNLOCK (); 2883e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params); 2884e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 2885e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2886e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik/** 2887779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * g_signal_emit_valist: 2888779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @instance: the instance the signal is being emitted on. 2889779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @signal_id: the signal id 2890779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @detail: the detail 2891779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * @var_args: a list of parameters to be passed to the signal, followed by a 2892779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * location for the return value. If the return type of the signal 2893779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * is #G_TYPE_NONE, the return value location can be omitted. 2894779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * 2895779c44cdfb017c1f93d0c77e0e80e11c341a2c4aTim Janik * Emits a signal. 2896e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * 2897e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik * Note that g_signal_emit_valist() resets the return value to the default 2898864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer * if no handlers are connected, in contrast to g_signal_emitv(). 2899e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik */ 2900864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterervoid 2901e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit_valist (gpointer instance, 2902e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint signal_id, 2903e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GQuark detail, 2904e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik va_list var_args) 2905e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik{ 2906864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer GValue *instance_and_params; 2907e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GType signal_return_type; 29089369e1e022978100c521634a968968a901dd934cTim Janik GValue *param_values; 2909e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik SignalNode *node; 2910bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik guint i, n_params; 2911bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik 2912e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 2913bbc5a3adac7d6d5dbdcf956d7d185e9910c3034bTim Janik g_return_if_fail (signal_id > 0); 2914e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2915e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_LOCK (); 2916e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik node = LOOKUP_SIGNAL_NODE (signal_id); 2917e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) 2918e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 2919e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); 2920e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 2921e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return; 2922e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2923e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik#ifndef G_DISABLE_CHECKS 2924e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (detail && !(node->flags & G_SIGNAL_DETAILED)) 2925864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer { 2926e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); 2927e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 29289369e1e022978100c521634a968968a901dd934cTim Janik return; 2929e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 29309369e1e022978100c521634a968968a901dd934cTim Janik#endif /* !G_DISABLE_CHECKS */ 2931e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2932f3ec41e8d22b5fa99b93ea753acb0de873732e94Jonathan Blandford /* optimize NOP emissions */ 2933e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (signal_check_skip_emission (node, instance, detail)) 2934e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik { 2935e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik /* nothing to do to emit this signal */ 2936e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 2937e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* g_printerr ("omitting emission of \"%s\"\n", node->name); */ 2938e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik return; 2939e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik } 2940e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 2941e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik n_params = node->n_params; 2942e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik signal_return_type = node->return_type; 2943e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik instance_and_params = g_slice_alloc (sizeof (GValue) * (n_params + 1)); 2944e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik param_values = instance_and_params + 1; 2945e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 2946e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik for (i = 0; i < node->n_params; i++) 2947743f49cec9f4696c9eba32966d6ac78cd96c586dTim Janik { 2948743f49cec9f4696c9eba32966d6ac78cd96c586dTim Janik gchar *error; 2949e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE; 2950743f49cec9f4696c9eba32966d6ac78cd96c586dTim Janik gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE; 2951e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2952e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik param_values[i].g_type = 0; 2953e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik SIGNAL_UNLOCK (); 2954e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_init (param_values + i, ptype); 2955e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_VALUE_COLLECT (param_values + i, 2956e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik var_args, 2957e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, 2958e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik &error); 2959160cd96ae26a571e76af717c27ae29b8125a54a5Matthias Clasen if (error) 2960e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 2961e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_warning ("%s: %s", G_STRLOC, error); 2962e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_free (error); 2963e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik 2964e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik /* we purposely leak the value here, it might not be 2965e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * in a sane state if an error condition occoured 2966864fbce267ca1ed25f9f2a3ca7ede385c5787cbdMichael Natterer */ 2967e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik while (i--) 2968e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_unset (param_values + i); 2969356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 2970356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_slice_free1 (sizeof (GValue) * (n_params + 1), instance_and_params); 2971356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost return; 2972356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 2973356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_LOCK (); 2974356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 2975356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 2976356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost instance_and_params->g_type = 0; 29776347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance)); 29786347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_value_set_instance (instance_and_params, instance); 29796347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer if (signal_return_type == G_TYPE_NONE) 2980356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost signal_emit_unlocked_R (node, detail, instance, NULL, instance_and_params); 2981356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost else 2982356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 2983e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GValue return_value = { 0, }; 2984e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gchar *error = NULL; 2985e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE; 2986e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE; 2987e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2988e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_init (&return_value, rtype); 2989e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2990e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik signal_emit_unlocked_R (node, detail, instance, &return_value, instance_and_params); 2991e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 2992e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik G_VALUE_LCOPY (&return_value, 2993e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik var_args, 2994e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, 2995e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik &error); 2996356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (!error) 2997356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_value_unset (&return_value); 2998356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost else 2999356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 3000356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_warning ("%s: %s", G_STRLOC, error); 3001356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_free (error); 3002356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 30036347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer /* we purposely leak the value here, it might not be 30046347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer * in a sane state if an error condition occured 30056347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer */ 3006356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 3007356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 3008356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost for (i = 0; i < n_params; i++) 3009e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_unset (param_values + i); 3010e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_value_unset (instance_and_params); 3011e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik g_slice_free1 (sizeof (GValue) * (n_params + 1), instance_and_params); 3012e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik} 3013e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 3014e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik/** 3015e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * g_signal_emit: 3016e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @instance: the instance the signal is being emitted on. 3017e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @signal_id: the signal id 3018e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @detail: the detail 3019e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * @...: parameters to be passed to the signal, followed by a 30209369e1e022978100c521634a968968a901dd934cTim Janik * location for the return value. If the return type of the signal 3021e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * is #G_TYPE_NONE, the return value location can be omitted. 30229369e1e022978100c521634a968968a901dd934cTim Janik * 3023e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * Emits a signal. 3024e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * 3025e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * Note that g_signal_emit() resets the return value to the default 3026e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik * if no handlers are connected, in contrast to g_signal_emitv(). 3027e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik */ 3028e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikvoid 3029e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janikg_signal_emit (gpointer instance, 3030e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik guint signal_id, 3031e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik GQuark detail, 3032e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik ...) 3033e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik{ 3034e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik va_list var_args; 3035e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 3036617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik va_start (var_args, detail); 3037617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik g_signal_emit_valist (instance, signal_id, detail, var_args); 3038617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik va_end (var_args); 3039617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik} 3040617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 3041617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik/** 3042617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * g_signal_emit_by_name: 3043617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @instance: the instance the signal is being emitted on. 3044617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @detailed_signal: a string of the form "signal-name::detail". 3045617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * @...: parameters to be passed to the signal, followed by a 3046617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * location for the return value. If the return type of the signal 3047617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * is #G_TYPE_NONE, the return value location can be omitted. 3048617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * 3049617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * Emits a signal. 3050617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * 3051617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * Note that g_signal_emit_by_name() resets the return value to the default 3052617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik * if no handlers are connected, in contrast to g_signal_emitv(). 3053e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik */ 3054e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janikvoid 3055e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janikg_signal_emit_by_name (gpointer instance, 3056e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik const gchar *detailed_signal, 3057e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik ...) 3058e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik{ 3059ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GQuark detail = 0; 3060617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik guint signal_id; 3061a05a4b766073561baea10ba697fc7042c308719cTim Janik 3062ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); 3063ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_return_if_fail (detailed_signal != NULL); 3064830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 3065617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SIGNAL_LOCK (); 3066e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE); 3067abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik SIGNAL_UNLOCK (); 3068e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik 3069ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (signal_id) 307022357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik { 307122357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik va_list var_args; 307222357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik 307343b692c8eb49a82657d9cb09a222dc66f2cc0199Tim Janik va_start (var_args, detailed_signal); 307422357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik g_signal_emit_valist (instance, signal_id, detail, var_args); 307522357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik va_end (var_args); 307622357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik } 307722357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik else 307822357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); 307922357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik} 308022357542e9cb017e2dfeee0004d6a22ed8897468Tim Janik 308122357542e9cb017e2dfeee0004d6a22ed8897468Tim Janikstatic inline gboolean 30829369e1e022978100c521634a968968a901dd934cTim Janikaccumulate (GSignalInvocationHint *ihint, 3083e28e398eb03fcfc467524d17fed666d1afc6dc82Tim Janik GValue *return_accu, 3084ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik GValue *handler_return, 3085ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SignalAccumulator *accumulator) 3086a05a4b766073561baea10ba697fc7042c308719cTim Janik{ 3087ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gboolean continue_emission; 3088a05a4b766073561baea10ba697fc7042c308719cTim Janik 3089ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!accumulator) 3090a05a4b766073561baea10ba697fc7042c308719cTim Janik return TRUE; 30919369e1e022978100c521634a968968a901dd934cTim Janik 3092e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data); 3093ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_value_reset (handler_return); 3094ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3095ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return continue_emission; 3096ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik} 3097617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 30989369e1e022978100c521634a968968a901dd934cTim Janikstatic gboolean 3099617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janiksignal_emit_unlocked_R (SignalNode *node, 3100617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GQuark detail, 31019369e1e022978100c521634a968968a901dd934cTim Janik gpointer instance, 3102617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik GValue *emission_return, 3103617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik const GValue *instance_and_params) 3104617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik{ 3105a05a4b766073561baea10ba697fc7042c308719cTim Janik SignalAccumulator *accumulator; 3106a05a4b766073561baea10ba697fc7042c308719cTim Janik Emission emission; 3107a05a4b766073561baea10ba697fc7042c308719cTim Janik GClosure *class_closure; 3108a05a4b766073561baea10ba697fc7042c308719cTim Janik HandlerList *hlist; 3109a05a4b766073561baea10ba697fc7042c308719cTim Janik Handler *handler_list = NULL; 3110a05a4b766073561baea10ba697fc7042c308719cTim Janik GValue *return_accu, accu = { 0, }; 3111a05a4b766073561baea10ba697fc7042c308719cTim Janik guint signal_id; 3112a05a4b766073561baea10ba697fc7042c308719cTim Janik gulong max_sequential_handler_number; 3113ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik gboolean return_value_altered = FALSE; 3114ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3115ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik#ifdef G_ENABLE_DEBUG 3116830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance) 3117830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 3118abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik g_message ("%s::%s(%u) emitted (instance=%p, signal-node=%p)", 3119830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik g_type_name (G_TYPE_FROM_INSTANCE (instance)), 3120830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik node->name, detail, 3121830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik instance, node); 3122830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (g_trap_instance_signals == instance) 3123830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik G_BREAKPOINT (); 3124a05a4b766073561baea10ba697fc7042c308719cTim Janik } 3125830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik#endif /* G_ENABLE_DEBUG */ 3126ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3127ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 3128a05a4b766073561baea10ba697fc7042c308719cTim Janik signal_id = node->signal_id; 3129a05a4b766073561baea10ba697fc7042c308719cTim Janik if (node->flags & G_SIGNAL_NO_RECURSE) 3130a05a4b766073561baea10ba697fc7042c308719cTim Janik { 31319369e1e022978100c521634a968968a901dd934cTim Janik Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance); 3132617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 3133617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (node) 3134617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 3135617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik node->state = EMISSION_RESTART; 3136a05a4b766073561baea10ba697fc7042c308719cTim Janik SIGNAL_UNLOCK (); 3137a05a4b766073561baea10ba697fc7042c308719cTim Janik return return_value_altered; 3138a05a4b766073561baea10ba697fc7042c308719cTim Janik } 3139a05a4b766073561baea10ba697fc7042c308719cTim Janik } 31409369e1e022978100c521634a968968a901dd934cTim Janik accumulator = node->accumulator; 3141a05a4b766073561baea10ba697fc7042c308719cTim Janik if (accumulator) 3142e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik { 3143ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 3144a05a4b766073561baea10ba697fc7042c308719cTim Janik g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 3145ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return_accu = &accu; 3146a05a4b766073561baea10ba697fc7042c308719cTim Janik SIGNAL_LOCK (); 3147ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 3148ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 3149ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return_accu = emission_return; 3150ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.instance = instance; 3151ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.ihint.signal_id = node->signal_id; 3152617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission.ihint.detail = detail; 3153617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission.ihint.run_type = 0; 31549490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik emission.state = 0; 3155a05a4b766073561baea10ba697fc7042c308719cTim Janik emission.chain_type = G_TYPE_NONE; 3156617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission); 3157617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik class_closure = signal_lookup_closure (node, instance); 3158617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 31599490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik EMIT_RESTART: 3160617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 31619490f8d7e435d60b76d5fca12ba6332a5f058fa5Tim Janik if (handler_list) 3162617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik handler_unref_R (signal_id, instance, handler_list); 3163738c1cfd6bc87a410324209e8e96f76f90ada720Erwann Chenede max_sequential_handler_number = g_handler_sequential_number; 3164617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik hlist = handler_list_lookup (signal_id, instance); 3165617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik handler_list = hlist ? hlist->handlers : NULL; 3166617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (handler_list) 31679369e1e022978100c521634a968968a901dd934cTim Janik handler_ref (handler_list); 3168a05a4b766073561baea10ba697fc7042c308719cTim Janik 31699369e1e022978100c521634a968968a901dd934cTim Janik emission.ihint.run_type = G_SIGNAL_RUN_FIRST; 3170617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 3171617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure) 3172617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 3173617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission.state = EMISSION_RUN; 3174617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 3175617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik emission.chain_type = G_TYPE_FROM_INSTANCE (instance); 3176617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SIGNAL_UNLOCK (); 3177ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_invoke (class_closure, 3178a05a4b766073561baea10ba697fc7042c308719cTim Janik return_accu, 3179ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->n_params + 1, 3180ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik instance_and_params, 3181ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik &emission.ihint); 3182830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && 3183ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.state == EMISSION_RUN) 3184830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik emission.state = EMISSION_STOP; 3185ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 3186a05a4b766073561baea10ba697fc7042c308719cTim Janik emission.chain_type = G_TYPE_NONE; 3187ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return_value_altered = TRUE; 3188ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3189ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission.state == EMISSION_STOP) 3190ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_CLEANUP; 3191ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (emission.state == EMISSION_RESTART) 3192830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik goto EMIT_RESTART; 3193830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 3194830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 3195830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (node->emission_hooks) 3196830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 3197830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik gboolean need_destroy, was_in_call, may_recurse = TRUE; 3198abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik GHook *hook; 3199abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik 3200ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.state = EMISSION_HOOK; 32019369e1e022978100c521634a968968a901dd934cTim Janik hook = g_hook_first_valid (node->emission_hooks, may_recurse); 3202617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik while (hook) 3203617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 3204617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SignalHook *signal_hook = SIGNAL_HOOK (hook); 3205617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 3206a05a4b766073561baea10ba697fc7042c308719cTim Janik if (!signal_hook->detail || signal_hook->detail == detail) 3207a05a4b766073561baea10ba697fc7042c308719cTim Janik { 3208a05a4b766073561baea10ba697fc7042c308719cTim Janik GSignalEmissionHook hook_func = (GSignalEmissionHook) hook->func; 3209a05a4b766073561baea10ba697fc7042c308719cTim Janik 32109369e1e022978100c521634a968968a901dd934cTim Janik was_in_call = G_HOOK_IN_CALL (hook); 3211e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik hook->flags |= G_HOOK_FLAG_IN_CALL; 3212ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 3213a05a4b766073561baea10ba697fc7042c308719cTim Janik need_destroy = !hook_func (&emission.ihint, node->n_params + 1, instance_and_params, hook->data); 3214ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 3215ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!was_in_call) 3216ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik hook->flags &= ~G_HOOK_FLAG_IN_CALL; 3217ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (need_destroy) 3218ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_hook_destroy_link (node->emission_hooks, hook); 3219ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 3220830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse); 3221830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik } 3222ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3223ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (emission.state == EMISSION_RESTART) 3224ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_RESTART; 3225ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 3226a05a4b766073561baea10ba697fc7042c308719cTim Janik 3227ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler_list) 3228a05a4b766073561baea10ba697fc7042c308719cTim Janik { 3229ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler = handler_list; 3230ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3231ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.state = EMISSION_RUN; 3232a05a4b766073561baea10ba697fc7042c308719cTim Janik handler_ref (handler); 3233830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik do 3234ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 3235ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *tmp; 3236a05a4b766073561baea10ba697fc7042c308719cTim Janik 3237ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (handler->after) 3238a05a4b766073561baea10ba697fc7042c308719cTim Janik { 32399369e1e022978100c521634a968968a901dd934cTim Janik handler_unref_R (signal_id, instance, handler_list); 3240617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik handler_list = handler; 3241617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik break; 3242617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 3243617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik else if (!handler->block_count && (!handler->detail || handler->detail == detail) && 3244a05a4b766073561baea10ba697fc7042c308719cTim Janik handler->sequential_number < max_sequential_handler_number) 3245a05a4b766073561baea10ba697fc7042c308719cTim Janik { 3246a05a4b766073561baea10ba697fc7042c308719cTim Janik SIGNAL_UNLOCK (); 3247a05a4b766073561baea10ba697fc7042c308719cTim Janik g_closure_invoke (handler->closure, 32489369e1e022978100c521634a968968a901dd934cTim Janik return_accu, 3249a05a4b766073561baea10ba697fc7042c308719cTim Janik node->n_params + 1, 3250e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik instance_and_params, 3251ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik &emission.ihint); 3252a05a4b766073561baea10ba697fc7042c308719cTim Janik if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && 3253ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.state == EMISSION_RUN) 3254a05a4b766073561baea10ba697fc7042c308719cTim Janik emission.state = EMISSION_STOP; 3255ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 3256ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return_value_altered = TRUE; 3257ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3258830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik tmp = emission.state == EMISSION_RUN ? handler->next : NULL; 3259ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 3260830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik else 3261ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp = handler->next; 3262a05a4b766073561baea10ba697fc7042c308719cTim Janik 3263ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (tmp) 3264ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_ref (tmp); 3265ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_unref_R (signal_id, instance, handler_list); 3266ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_list = handler; 3267ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler = tmp; 3268abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik } 3269abc5cbbe3e1f6e6bdc40d94741713e9efb6d580dTim Janik while (handler); 3270ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 32719369e1e022978100c521634a968968a901dd934cTim Janik if (emission.state == EMISSION_STOP) 3272617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik goto EMIT_CLEANUP; 3273617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik else if (emission.state == EMISSION_RESTART) 3274617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik goto EMIT_RESTART; 3275617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik } 3276a05a4b766073561baea10ba697fc7042c308719cTim Janik 3277a05a4b766073561baea10ba697fc7042c308719cTim Janik emission.ihint.run_type = G_SIGNAL_RUN_LAST; 3278a05a4b766073561baea10ba697fc7042c308719cTim Janik 3279a05a4b766073561baea10ba697fc7042c308719cTim Janik if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure) 32809369e1e022978100c521634a968968a901dd934cTim Janik { 3281e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik emission.state = EMISSION_RUN; 3282ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3283a05a4b766073561baea10ba697fc7042c308719cTim Janik emission.chain_type = G_TYPE_FROM_INSTANCE (instance); 3284ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_UNLOCK (); 3285ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_invoke (class_closure, 3286ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return_accu, 3287ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->n_params + 1, 3288ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik instance_and_params, 3289ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik &emission.ihint); 3290ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && 3291ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.state == EMISSION_RUN) 3292ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.state = EMISSION_STOP; 3293ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik SIGNAL_LOCK (); 3294ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.chain_type = G_TYPE_NONE; 3295a05a4b766073561baea10ba697fc7042c308719cTim Janik return_value_altered = TRUE; 3296ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3297a05a4b766073561baea10ba697fc7042c308719cTim Janik if (emission.state == EMISSION_STOP) 3298ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_CLEANUP; 3299ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else if (emission.state == EMISSION_RESTART) 3300ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_RESTART; 3301ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 3302ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3303a05a4b766073561baea10ba697fc7042c308719cTim Janik if (handler_list) 3304830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik { 3305ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik Handler *handler = handler_list; 3306ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik 3307830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik emission.state = EMISSION_RUN; 3308830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik handler_ref (handler); 3309a05a4b766073561baea10ba697fc7042c308719cTim Janik do 3310ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik { 3311a05a4b766073561baea10ba697fc7042c308719cTim Janik Handler *tmp; 33129369e1e022978100c521634a968968a901dd934cTim Janik 3313617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) && 3314ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler->sequential_number < max_sequential_handler_number) 3315617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik { 3316617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik SIGNAL_UNLOCK (); 3317ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik g_closure_invoke (handler->closure, 3318ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik return_accu, 3319ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik node->n_params + 1, 3320ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik instance_and_params, 3321830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik &emission.ihint); 3322a05a4b766073561baea10ba697fc7042c308719cTim Janik if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && 3323830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik emission.state == EMISSION_RUN) 3324ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik emission.state = EMISSION_STOP; 33259369e1e022978100c521634a968968a901dd934cTim Janik SIGNAL_LOCK (); 3326a05a4b766073561baea10ba697fc7042c308719cTim Janik return_value_altered = TRUE; 3327830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 3328a05a4b766073561baea10ba697fc7042c308719cTim Janik tmp = emission.state == EMISSION_RUN ? handler->next : NULL; 3329ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 3330ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik else 3331ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik tmp = handler->next; 3332830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik 3333830d808c5ce0d94524807d4777a4c8257efcbf8aTim Janik if (tmp) 3334ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik handler_ref (tmp); 3335a05a4b766073561baea10ba697fc7042c308719cTim Janik handler_unref_R (signal_id, instance, handler); 33369369e1e022978100c521634a968968a901dd934cTim Janik handler = tmp; 3337ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik } 3338e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik while (handler); 3339617332234d4426ed0941ec1e2cb9f0736bd796c3Tim Janik 3340e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik if (emission.state == EMISSION_STOP) 3341ee23c09e83d06a0d131ebd234c132f1c3602c019Tim Janik goto EMIT_CLEANUP; 3342e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik else if (emission.state == EMISSION_RESTART) 3343116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor goto EMIT_RESTART; 3344116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor } 3345116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor 3346116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor EMIT_CLEANUP: 3347116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor 3348116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor emission.ihint.run_type = G_SIGNAL_RUN_CLEANUP; 3349116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor 3350116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure) 3351116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor { 3352116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor gboolean need_unset = FALSE; 3353116b90dfb1c0fb09e45469114f6079f1f2576bd0Owen Taylor 3354e773d7dba66cf51c7d6ad7d1973ab3635e986e2eTim Janik emission.state = EMISSION_STOP; 3355356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 3356356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost emission.chain_type = G_TYPE_FROM_INSTANCE (instance); 3357356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_UNLOCK (); 3358356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (node->return_type != G_TYPE_NONE && !accumulator) 3359356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost { 3360356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 33616347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer need_unset = TRUE; 3362356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost } 3363356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost g_closure_invoke (class_closure, 3364356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->return_type != G_TYPE_NONE ? &accu : NULL, 3365356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost node->n_params + 1, 3366356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost instance_and_params, 3367356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost &emission.ihint); 3368356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (need_unset) 33696347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer g_value_unset (&accu); 3370356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost SIGNAL_LOCK (); 33716347be5fb68fc3e5e9d5bfedc3cbd5349ef40074Michael Natterer emission.chain_type = G_TYPE_NONE; 3372356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost 3373356fe46531106b75f2c240ee63cd9f77d2df3df9Stefan Kost if (emission.state == EMISSION_RESTART) 337432bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor goto EMIT_RESTART; 337532bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor } 337632bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor 337732bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor if (handler_list) 337832bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor handler_unref_R (signal_id, instance, handler_list); 337932bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor 338032bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission); 338132bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor SIGNAL_UNLOCK (); 338232bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor if (accumulator) 338332bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor g_value_unset (&accu); 338432bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor 338532bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor return return_value_altered; 338632bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor} 338732bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylor 338832bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylorstatic const gchar* 338932bc3c419726f26bd771ccd03c60cd03243037f6Owen Taylortype_debug_name (GType type) 3390f0b9abe801c2e0cccb7930421a81bb77031e3251Tim Janik{ 33915602b7e275ef5fb76cf7847f35b120dce3111705Michael Natterer if (type) 33923448a27829133bebb3bf1e29a30574304c899040Matthias Clasen { 33933448a27829133bebb3bf1e29a30574304c899040Matthias Clasen const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE); 33943448a27829133bebb3bf1e29a30574304c899040Matthias Clasen return name ? name : "<unknown>"; 3395 } 3396 else 3397 return "<invalid>"; 3398} 3399 3400/** 3401 * g_signal_accumulator_true_handled: 3402 * @ihint: standard #GSignalAccumulator parameter 3403 * @return_accu: standard #GSignalAccumulator parameter 3404 * @handler_return: standard #GSignalAccumulator parameter 3405 * @dummy: standard #GSignalAccumulator parameter 3406 * 3407 * A predefined #GSignalAccumulator for signals that return a 3408 * boolean values. The behavior that this accumulator gives is 3409 * that a return of %TRUE stops the signal emission: no further 3410 * callbacks will be invoked, while a return of %FALSE allows 3411 * the emission to coninue. The idea here is that a %TRUE return 3412 * indicates that the callback <emphasis>handled</emphasis> the signal, 3413 * and no further handling is needed. 3414 * 3415 * Since: 2.4 3416 * 3417 * Returns: standard #GSignalAccumulator result 3418 */ 3419gboolean 3420g_signal_accumulator_true_handled (GSignalInvocationHint *ihint, 3421 GValue *return_accu, 3422 const GValue *handler_return, 3423 gpointer dummy) 3424{ 3425 gboolean continue_emission; 3426 gboolean signal_handled; 3427 3428 signal_handled = g_value_get_boolean (handler_return); 3429 g_value_set_boolean (return_accu, signal_handled); 3430 continue_emission = !signal_handled; 3431 3432 return continue_emission; 3433} 3434 3435/* --- compile standard marshallers --- */ 3436#include "gmarshal.c" 3437 3438#define __G_SIGNAL_C__ 3439#include "gobjectaliasdef.c" 3440