summaryrefslogtreecommitdiff
path: root/docs/reference/gobject/tut_gsignal.xml
blob: d690d1690e1bf382a25235c728769521cc6bdb2d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
<?xml version='1.0' encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN" 
               "http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
]>
<chapter id="chapter-signal">
  <title>The GObject messaging system</title>

  <sect1 id="closure">
    <title>Closures</title>

    <para>
      Closures are central to the concept of asynchronous signal delivery
      which is widely used throughout GTK and GNOME applications. A closure is an 
      abstraction, a generic representation of a callback. It is a small structure
      which contains three objects:
      <itemizedlist>
        <listitem><para>a function pointer (the callback itself) whose prototype looks like:
<informalexample><programlisting>
return_type function_callback (… , gpointer user_data);
</programlisting></informalexample>
        </para></listitem>
        <listitem><para>
           the <parameter>user_data</parameter> pointer which is passed to the callback upon invocation of the closure
          </para></listitem>
        <listitem><para>
           a function pointer which represents the destructor of the closure: whenever the
           closure's refcount reaches zero, this function will be called before the closure
           structure is freed.
          </para></listitem>
      </itemizedlist>
    </para>

    <para>
      The <link linkend="GClosure"><type>GClosure</type></link> structure represents the common functionality of all
      closure implementations: there exists a different closure implementation for
      each separate runtime which wants to use the GObject type system.
      <footnote><para>
        In practice, closures sit at the boundary of language runtimes: if you are
        writing Python code and one of your Python callbacks receives a signal from
        a GTK widget, the C code in GTK needs to execute your Python
        code. The closure invoked by the GTK object invokes the Python callback:
        it behaves as a normal C object for GTK and as a normal Python object for
        Python code.
      </para></footnote>
      The GObject library provides a simple <link linkend="GCClosure"><type>GCClosure</type></link> type which
      is a specific implementation of closures to be used with C/C++ callbacks.
    </para>
    <para>
      A <link linkend="GClosure"><type>GClosure</type></link> provides simple services:
      <itemizedlist>
        <listitem><para>
          Invocation (<function><link linkend="g-closure-invoke">g_closure_invoke</link></function>): this is what closures 
          were created for: they hide the details of callback invocation from the
          callback invoker.</para>
        </listitem>
        <listitem><para>
          Notification: the closure notifies listeners of certain events such as
          closure invocation, closure invalidation and closure finalization. Listeners
          can be registered with <function><link linkend="g-closure-add-finalize-notifier">g_closure_add_finalize_notifier</link></function>
          (finalization notification), <function><link linkend="g-closure-add-invalidate-notifier">g_closure_add_invalidate_notifier</link></function> 
          (invalidation notification) and 
          <function><link linkend="g-closure-add-marshal-guards">g_closure_add_marshal_guards</link></function> (invocation notification).
          There exist symmetric deregistration functions for finalization and invalidation
          events (<function><link linkend="g-closure-remove-finalize-notifier">g_closure_remove_finalize_notifier</link></function> and
          <function><link linkend="g-closure-remove-invalidate-notifier">g_closure_remove_invalidate_notifier</link></function>) but not for the invocation 
          process.
          <footnote><para>
            Closures are reference counted and notify listeners of their destruction in a two-stage
            process: the invalidation notifiers are invoked before the finalization notifiers.
          </para></footnote></para>
        </listitem>
      </itemizedlist>
    </para>

    <sect2>
      <title>C Closures</title>

      <para>
        If you are using C or C++
        to connect a callback to a given event, you will either use simple <link linkend="GCClosure"><type>GCClosure</type></link>s
        which have a pretty minimal API or the even simpler <function><link linkend="g-signal-connect">g_signal_connect</link></function> 
        functions (which will be presented a bit later).
      </para>

      <para>
        <function><link linkend="g-cclosure-new">g_cclosure_new</link></function> will create a new closure which can invoke the
        user-provided callback_func with the user-provided
        <parameter>user_data</parameter> as its last parameter. When the closure
        is finalized (second stage of the destruction process), it will invoke
        the <parameter>destroy_data</parameter> function if the user has
        supplied one.
      </para>
  
      <para>
        <function><link linkend="g-cclosure-new-swap">g_cclosure_new_swap</link></function> will create a new closure which can invoke the
        user-provided <parameter>callback_func</parameter> with the
        user-provided <parameter>user_data</parameter> as its first parameter
        (instead of being the 
        last parameter as with <function><link linkend="g-cclosure-new">g_cclosure_new</link></function>). When the closure
        is finalized (second stage of the destruction process), it will invoke
        the <parameter>destroy_data</parameter> function if the user has
        supplied one.
      </para>
    </sect2>

    <sect2>
      <title>Non-C closures (for the fearless)</title>

      <para>
        As was explained above, closures hide the details of callback invocation. In C,
        callback invocation is just like function invocation: it is a matter of creating
        the correct stack frame for the called function and executing a <emphasis>call</emphasis>
        assembly instruction.
      </para>
  
      <para>
        C closure marshallers transform the array of GValues which represent 
        the parameters to the target function into a C-style function parameter list, invoke
        the user-supplied C function with this new parameter list, get the return value of the
        function, transform it into a GValue and return this GValue to the marshaller caller.
      </para>

      <para>
        A generic C closure marshaller is available as
        <link linkend="g-cclosure-marshal-generic"><function>g_cclosure_marshal_generic</function></link>
        which implements marshalling for all function types using libffi. Custom
        marshallers for different types are not needed apart from performance
        critical code where the libffi-based marshaller may be too slow.
      </para>

      <para>
        An example of a custom marshaller is given below, illustrating how
        <type>GValue</type>s can be converted to a C function call. The
        marshaller is for a C function which takes an integer as its first
        parameter and returns void.
<informalexample><programlisting>
g_cclosure_marshal_VOID__INT (GClosure     *closure,
                              GValue       *return_value,
                              guint         n_param_values,
                              const GValue *param_values,
                              gpointer      invocation_hint,
                              gpointer      marshal_data)
{
  typedef void (*GMarshalFunc_VOID__INT) (gpointer     data1,
                                          gint         arg_1,
                                          gpointer     data2);
  register GMarshalFunc_VOID__INT callback;
  register GCClosure *cc = (GCClosure*) closure;
  register gpointer data1, data2;

  g_return_if_fail (n_param_values == 2);

  data1 = g_value_peek_pointer (param_values + 0);
  data2 = closure->data;

  callback = (GMarshalFunc_VOID__INT) (marshal_data ? marshal_data : cc->callback);

  callback (data1,
            g_marshal_value_peek_int (param_values + 1),
            data2);
}
</programlisting></informalexample>
      </para>
  
      <para>
        There exist other kinds of marshallers, for example there is a generic
        Python marshaller which is used by all Python closures (a Python closure
        is used to invoke a callback written in Python). This Python marshaller
        transforms the input GValue list representing the function parameters
        into a Python tuple which is the equivalent structure in Python.
      </para>

    </sect2>
  </sect1>

  <sect1 id="signal">
    <title>Signals</title>

    <para>
      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.
    </para>

    <para>
      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 <emphasis>connect</emphasis>
      to the signal on a given type instance when they register a closure to be  
      invoked upon the signal emission. The closure will be called synchronously on 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.
    </para>

    <para>
      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:
<informalexample><programlisting>
return_type function_callback (gpointer instance, …, gpointer user_data);
</programlisting></informalexample>
    </para>

    <sect2 id="signal-registration">
      <title>Signal registration</title>

	  <para>
		To register a new signal on an existing type, we can use any of <function><link linkend="g-signal-newv">g_signal_newv</link></function>,
		<function><link linkend="g-signal-new-valist">g_signal_new_valist</link></function> or <function><link linkend="g-signal-new">g_signal_new</link></function> functions:
<informalexample><programlisting>
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);
</programlisting></informalexample>
		The number of parameters to these functions is a bit intimidating but they are relatively
		simple:
		<itemizedlist>
		  <listitem><para>
			  <parameter>signal_name</parameter>: is a string which can be used to uniquely identify a given signal.
			</para></listitem>
		  <listitem><para>
			  <parameter>itype</parameter>: is the instance type on which this signal can be emitted.
			</para></listitem>
		  <listitem><para>
			  <parameter>signal_flags</parameter>: partly defines the order in which closures which were connected to the
			  signal are invoked.
			</para></listitem>
		  <listitem><para>
			  <parameter>class_closure</parameter>: 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.
			</para></listitem>
			<listitem><para>
			  <parameter>accumulator</parameter>: 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
			  <literal>NULL</literal> returns from closures; or it
			  could build a list of the values returned by the
			  closures.
			</para></listitem>
		  <listitem><para>
			  <parameter>accu_data</parameter>: this pointer will be passed down to each invocation of the
			  accumulator during emission.
			</para></listitem>
		  <listitem><para>
			  <parameter>c_marshaller</parameter>: this is the default C marshaller for any closure which is connected to
			this signal.
			</para></listitem>
		  <listitem><para>
			  <parameter>return_type</parameter>: this is the type of the return value of the signal.
			</para></listitem>
		  <listitem><para>
			  <parameter>n_params</parameter>: this is the number of parameters this signal takes.
			</para></listitem>
		  <listitem><para>
			  <parameter>param_types</parameter>: 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.
			</para></listitem>
		</itemizedlist>
      </para>

	  <para>
		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.
	  </para>

	</sect2>

	<sect2 id="signal-connection">
	  <title>Signal connection</title>

	  <para>
		If you want to connect to a signal with a closure, you have three possibilities:
		<itemizedlist>
		  <listitem><para>
		  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 <emphasis>any</emphasis> of the instances of the type which supports that signal.
			</para></listitem>
		  <listitem><para>
		  You can use <function><link linkend="g-signal-override-class-closure">g_signal_override_class_closure</link></function> which
		  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.
			</para></listitem>
		  <listitem><para>
		  You can register a closure with the <function><link linkend="g-signal-connect">g_signal_connect</link></function>
		  family of functions. This is an instance-specific operation: the closure
		  will be invoked only during emission of a given signal on a given instance.
			</para></listitem>
		</itemizedlist>
		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 <function><link linkend="g-signal-add-emission-hook">g_signal_add_emission_hook</link></function>
		and removed with <function><link linkend="g-signal-remove-emission-hook">g_signal_remove_emission_hook</link></function>.
	  </para>

	</sect2>

	<sect2 id="signal-emission">
	  <title>Signal emission</title>

	  <para>
		Signal emission is done through the use of the <function><link linkend="g-signal-emit">g_signal_emit</link></function> family 
		of functions.
<informalexample><programlisting>
void g_signal_emitv (const GValue *instance_and_params,
                     guint         signal_id,
                     GQuark        detail,
                     GValue       *return_value);
</programlisting></informalexample>
		<itemizedlist>
		  <listitem><para>
			The <parameter>instance_and_params</parameter> array 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.
			</para></listitem>
		  <listitem><para>
			<parameter>signal_id</parameter> identifies the signal to invoke.
			</para></listitem>
		  <listitem><para>
			<parameter>detail</parameter> identifies 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 <xref linkend="signal-detail"/> for
			more details about this parameter.
			</para></listitem>
		  <listitem><para>
			<parameter>return_value</parameter> holds 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 <parameter>return_value</parameter> is nonetheless initialized to zero/null.
			</para></listitem>
		  </itemizedlist>
		</para>

	  <para>
		Signal emission is done synchronously and can be decomposed in 5 steps:
		<orderedlist>
		  <listitem><para>
			<literal>RUN_FIRST</literal>: if the
			<link linkend="G-SIGNAL-RUN-FIRST:CAPS"><literal>G_SIGNAL_RUN_FIRST</literal></link> flag was used
			during signal registration and if there exists a class closure for this signal,
			the class closure is invoked.
			</para></listitem>
		  <listitem><para>
			<literal>EMISSION_HOOK</literal>: if any emission hook was added to
			the signal, they are invoked from first to last added. Accumulate return values.
			</para></listitem>
		  <listitem><para>
			<literal>HANDLER_RUN_FIRST</literal>: if any closure were connected
			with the <function><link linkend="g-signal-connect">g_signal_connect</link></function> family of 
			functions, and if they are not blocked (with the <function><link linkend="g-signal-handler-block">g_signal_handler_block</link></function>
			family of functions) they are run here, from first to last connected.
			</para></listitem>
		  <listitem><para>
			<literal>RUN_LAST</literal>: if the <literal>G_SIGNAL_RUN_LAST</literal>
			flag was set during registration and if a class closure
			was set, it is invoked here.
			</para></listitem>
		  <listitem><para>
			<literal>HANDLER_RUN_LAST</literal>: if any closure were connected
			with the <function>g_signal_connect_after</function> family of 
			functions, if they were not invoked during <literal>HANDLER_RUN_FIRST</literal> and if they 
			are not blocked, they are run here, from first to last connected.
			</para></listitem>
		  <listitem><para>
			<literal>RUN_CLEANUP</literal>: if the <literal>G_SIGNAL_RUN_CLEANUP</literal> flag
			was set during registration and if a class closure was set,
			it is invoked here. Signal emission is completed here.
			</para></listitem>
		</orderedlist>
	  </para>
  
	  <para>
		If, at any point during emission (except in <literal>RUN_CLEANUP</literal> or
		<literal>EMISSION_HOOK</literal> state), one of the closures stops the signal emission with
		<function><link linkend="g-signal-stop-emission">g_signal_stop_emission</link></function>,
		emission jumps to <literal>RUN_CLEANUP</literal> state.
	  </para>
  
	  <para>
		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 <literal>RUN_FIRST</literal> state.
	  </para>
  
	  <para>
		The accumulator function is invoked in all states, after invocation
		of each closure (except in <literal>RUN_EMISSION_HOOK</literal> and
		<literal>RUN_CLEANUP</literal>). 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
		to <literal>RUN_CLEANUP</literal> state.
	  </para>

	  <para>
		If no accumulator function was provided, the value returned by the last handler
		run will be returned by <function><link linkend="g-signal-emit">g_signal_emit</link></function>.
	  </para>

	</sect2>


	<sect2 id="signal-detail">
	  <title>The <emphasis>detail</emphasis> argument</title>

	  <para>All the functions related to signal emission or signal connection have a parameter
		named the <emphasis>detail</emphasis>. Sometimes, this parameter is hidden by the API
		but it is always there, in one form or another. 
	  </para>

	  <para>
	    Of the three main connection functions,
		only one has an explicit detail parameter as a <link linkend="GQuark"><type>GQuark</type></link>:
		<link linkend="g-signal-connect-closure-by-id"><function>g_signal_connect_closure_by_id</function></link>.
		<footnote>
		  <para>A GQuark is an integer which uniquely represents a string. It is possible to transform
		   back and forth between the integer and string representations with the functions 
		   <function><link linkend="g-quark-from-string">g_quark_from_string</link></function> and <function><link linkend="g-quark-to-string">g_quark_to_string</link></function>.
		  </para>
		</footnote>
	  </para>
	  <para>
	    The two other functions,
	    <link linkend="g-signal-connect-closure"><function>g_signal_connect_closure</function></link> and
	    <link linkend="g-signal-connect-data"><function>g_signal_connect_data</function></link>
	    hide the detail parameter in the signal name identification.
		Their <parameter>detailed_signal</parameter> parameter is a
		string which identifies the name of the signal to connect to.
		The format of this string should match
		<emphasis>signal_name::detail_name</emphasis>. For example,
		connecting to the signal named
		<emphasis>notify::cursor_position</emphasis> will actually
		connect to the signal named <emphasis>notify</emphasis> with the
		<emphasis>cursor_position</emphasis> detail.
		Internally, the detail string is transformed to a GQuark if it is present.
	  </para>

	  <para>
	    Of the four main signal emission functions, one hides it in its
	    signal name parameter:
	    <link linkend="g-signal-connect"><function>g_signal_connect</function></link>.
	    The other three have an explicit detail parameter as a
	    <link linkend="GQuark"><type>GQuark</type></link> again:
	    <link linkend="g-signal-emit"><function>g_signal_emit</function></link>,
	    <link linkend="g-signal-emitv"><function>g_signal_emitv</function></link> and
	    <link linkend="g-signal-emit-valist"><function>g_signal_emit_valist</function></link>.
	  </para>

	  <para>
        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).
	  </para>

	  <para>
		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
		by the <link linkend="GObject-notify"><structfield>notify</structfield></link> signal of GObject: whenever a property is modified on a GObject,
		instead of just emitting the <emphasis>notify</emphasis> 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.
	  </para>

	  <para>
		As a simple rule, users can and should set the detail parameter to zero: this will disable completely
        this optional filtering for that signal.
	  </para>

	</sect2>

  </sect1>
</chapter>