GObject's signals have nothing to do with standard UNIX signals: they connect arbitrary application-specific events with any number of listeners. For example, in GTK+, every user event (keystroke or mouse move) is received from the windowing system and generates a GTK+ event in the form of a signal emission on the widget object instance.
Each signal is registered in the type system together with the type on which it can be emitted: users of the type are said to connect to the signal on a given type instance when they register a closure to be invoked upon the signal emission. Users can also emit the signal by themselves or stop the emission of the signal from within one of the closures connected to the signal.
When a signal is emitted on a given type instance, all the closures connected to this signal on this type instance will be invoked. All the closures connected to such a signal represent callbacks whose signature looks like:
return_type function_callback (gpointer instance, …, gpointer user_data);
1 2 3 4 5 6 7 8 9 10
guint g_signal_newv (const gchar *signal_name, GType itype, GSignalFlags signal_flags, GClosure *class_closure, GSignalAccumulator accumulator, gpointer accu_data, GSignalCMarshaller c_marshaller, GType return_type, guint n_params, GType *param_types);
The number of parameters to these functions is a bit intimidating but they are relatively simple:
signal_name: is a string which can be used to uniquely identify a given signal.
itype: is the instance type on which this signal can be emitted.
signal_flags: partly defines the order in which closures which were connected to the signal are invoked.
class_closure: this is the default closure for the signal: if it is not NULL upon the signal emission, it will be invoked upon this emission of the signal. The moment where this closure is invoked compared to other closures connected to that signal depends partly on the signal_flags.
accumulator: this is a function pointer which is invoked after each closure has been invoked. If it returns FALSE, signal emission is stopped. If it returns TRUE, signal emission proceeds normally. It is also used to compute the return value of the signal based on the return value of all the invoked closures. For example, an accumulator could ignore
NULLreturns from closures; or it could build a list of the values returned by the closures.
accumulator_data: this pointer will be passed down to each invocation of the accumulator during emission.
c_marshaller: this is the default C marshaller for any closure which is connected to this signal.
return_type: this is the type of the return value of the signal.
n_params: this is the number of parameters this signal takes.
param_types: this is an array of GTypes which indicate the type of each parameter of the signal. The length of this array is indicated by n_params.
As you can see from the above definition, a signal is basically a description of the closures which can be connected to this signal and a description of the order in which the closures connected to this signal will be invoked.
If you want to connect to a signal with a closure, you have three possibilities:
You can register a class closure at signal registration: this is a system-wide operation. i.e.: the class closure will be invoked during each emission of a given signal on any of the instances of the type which supports that signal.
You can use
g_signal_override_class_closurewhich overrides the class closure of a given type. It is possible to call this function only on a derived type of the type on which the signal was registered. This function is of use only to language bindings.
You can register a closure with the
g_signal_connectfamily of functions. This is an instance-specific operation: the closure will be invoked only during emission of a given signal on a given instance.
It is also possible to connect a different kind of callback on a given signal:
emission hooks are invoked whenever a given signal is emitted whatever the instance on
which it is emitted. Emission hooks are used for example to get all mouse_clicked
emissions in an application to be able to emit the small mouse click sound.
Emission hooks are connected with
and removed with
Signal emission is done through the use of the
1 2 3 4
void g_signal_emitv (const GValue *instance_and_params, guint signal_id, GQuark detail, GValue *return_value);
instance_and_paramsarray of GValues contains the list of input parameters to the signal. The first element of the array is the instance pointer on which to invoke the signal. The following elements of the array contain the list of parameters to the signal.
signal_ididentifies the signal to invoke.
detailidentifies the specific detail of the signal to invoke. A detail is a kind of magic token/argument which is passed around during signal emission and which is used by closures connected to the signal to filter out unwanted signal emissions. In most cases, you can safely set this value to zero. See the section called “The detail argument” for more details about this parameter.
return_valueholds the return value of the last closure invoked during emission if no accumulator was specified. If an accumulator was specified during signal creation, this accumulator is used to calculate the return value as a function of the return values of all the closures invoked during emission. If no closure is invoked during emission, the
return_valueis nonetheless initialized to zero/null.
Signal emission can be decomposed in 5 steps:
RUN_FIRST: if the
G_SIGNAL_RUN_FIRSTflag was used during signal registration and if there exists a class closure for this signal, the class closure is invoked.
EMISSION_HOOK: if any emission hook was added to the signal, they are invoked from first to last added. Accumulate return values.
HANDLER_RUN_FIRST: if any closure were connected with the
g_signal_connectfamily of functions, and if they are not blocked (with the
g_signal_handler_blockfamily of functions) they are run here, from first to last connected.
RUN_LAST: if the
G_SIGNAL_RUN_LASTflag was set during registration and if a class closure was set, it is invoked here.
HANDLER_RUN_LAST: if any closure were connected with the
g_signal_connect_afterfamily of functions, if they were not invoked during
HANDLER_RUN_FIRSTand if they are not blocked, they are run here, from first to last connected.
RUN_CLEANUP: if the
G_SIGNAL_RUN_CLEANUPflag was set during registration and if a class closure was set, it is invoked here. Signal emission is completed here.
If, at any point during emission (except in
RUN_CLEANUP state), one of the
closures or emission hook stops the signal emission with
emission jumps to
If, at any point during emission, one of the closures or emission hook
emits the same signal on the same instance, emission is restarted from
The accumulator function is invoked in all states, after invocation
of each closure (except in
RUN_CLEANUP). It accumulates
the closure return value into the signal return value and returns TRUE or
FALSE. If, at any point, it does not return TRUE, emission jumps
If no accumulator function was provided, the value returned by the last handler
run will be returned by
All the functions related to signal emission or signal connection have a parameter named the detail. Sometimes, this parameter is hidden by the API but it is always there, in one form or another.
The two other functions,
hide the detail parameter in the signal name identification.
detailed_signal parameter is a
string which identifies the name of the signal to connect to.
The format of this string should match
signal_name::detail_name. For example,
connecting to the signal named
notify::cursor_position will actually
connect to the signal named notify with the
Internally, the detail string is transformed to a GQuark if it is present.
Of the four main signal emission functions, one hides it in its
signal name parameter:
The other three have an explicit detail parameter as a
If a detail is provided by the user to the emission function, it is used during emission to match against the closures which also provide a detail. If a closure's detail does not match the detail provided by the user, it will not be invoked (even though it is connected to a signal which is being emitted).
This completely optional filtering mechanism is mainly used as an optimization for signals
which are often emitted for many different reasons: the clients can filter out which events they are
interested in before the closure's marshalling code runs. For example, this is used extensively
notify signal of GObject: whenever a property is modified on a GObject,
instead of just emitting the notify signal, GObject associates as a detail to this
signal emission the name of the property modified. This allows clients who wish to be notified of changes
to only one property to filter most events before receiving them.
As a simple rule, users can and should set the detail parameter to zero: this will disable completely this optional filtering for that signal.