|
1 /* GObject - GLib Type, Object, Parameter and Signal Library |
|
2 * Copyright (C) 2000-2001 Red Hat, Inc. |
|
3 * Portions copyright (c) 2006-2009 Nokia Corporation. All rights reserved. |
|
4 * |
|
5 * This library is free software; you can redistribute it and/or |
|
6 * modify it under the terms of the GNU Lesser General Public |
|
7 * License as published by the Free Software Foundation; either |
|
8 * version 2 of the License, or (at your option) any later version. |
|
9 * |
|
10 * This library is distributed in the hope that it will be useful, |
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
13 * Lesser General Public License for more details. |
|
14 * |
|
15 * You should have received a copy of the GNU Lesser General |
|
16 * Public License along with this library; if not, write to the |
|
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330, |
|
18 * Boston, MA 02111-1307, USA. |
|
19 * |
|
20 * this code is based on the original GtkSignal implementation |
|
21 * for the Gtk+ library by Peter Mattis <petm@xcf.berkeley.edu> |
|
22 */ |
|
23 |
|
24 /* |
|
25 * MT safe |
|
26 */ |
|
27 |
|
28 #include "config.h" |
|
29 |
|
30 #include <string.h> |
|
31 #include <signal.h> |
|
32 |
|
33 #include "gsignal.h" |
|
34 #include "gbsearcharray.h" |
|
35 #include "gvaluecollector.h" |
|
36 #include "gvaluetypes.h" |
|
37 #include "gboxed.h" |
|
38 #include "gobject.h" |
|
39 #include "genums.h" |
|
40 #include "gobjectalias.h" |
|
41 #ifdef __SYMBIAN32__ |
|
42 #include <glib_global.h> |
|
43 #include "gobject_wsd.h" |
|
44 #endif /* __SYMBIAN32__ */ |
|
45 |
|
46 /** |
|
47 * SECTION:signals |
|
48 * @short_description: A means for customization of object behaviour |
|
49 * and a general purpose notification mechanism |
|
50 * @title: Signals |
|
51 * |
|
52 * The basic concept of the signal system is that of the |
|
53 * <emphasis>emission</emphasis> of a signal. Signals are introduced |
|
54 * per-type and are identified through strings. Signals introduced |
|
55 * for a parent type are available in derived types as well, so |
|
56 * basically they are a per-type facility that is inherited. A signal |
|
57 * emission mainly involves invocation of a certain set of callbacks |
|
58 * in precisely defined manner. There are two main categories of such |
|
59 * callbacks, per-object |
|
60 * <footnote><para>Although signals can deal with any kind of instantiatable |
|
61 * type, i'm referring to those types as "object types" in the following, |
|
62 * simply because that is the context most users will encounter signals in. |
|
63 * </para></footnote> |
|
64 * ones and user provided ones. |
|
65 * The per-object callbacks are most often referred to as "object method |
|
66 * handler" or "default (signal) handler", while user provided callbacks are |
|
67 * usually just called "signal handler". |
|
68 * The object method handler is provided at signal creation time (this most |
|
69 * frequently happens at the end of an object class' creation), while user |
|
70 * provided handlers are frequently connected and disconnected to/from a certain |
|
71 * signal on certain object instances. |
|
72 * |
|
73 * A signal emission consists of five stages, unless prematurely stopped: |
|
74 * <variablelist> |
|
75 * <varlistentry><term></term><listitem><para> |
|
76 * 1 - Invocation of the object method handler for %G_SIGNAL_RUN_FIRST signals |
|
77 * </para></listitem></varlistentry> |
|
78 * <varlistentry><term></term><listitem><para> |
|
79 * 2 - Invocation of normal user-provided signal handlers (<emphasis>after</emphasis> flag %FALSE) |
|
80 * </para></listitem></varlistentry> |
|
81 * <varlistentry><term></term><listitem><para> |
|
82 * 3 - Invocation of the object method handler for %G_SIGNAL_RUN_LAST signals |
|
83 * </para></listitem></varlistentry> |
|
84 * <varlistentry><term></term><listitem><para> |
|
85 * 4 - Invocation of user provided signal handlers, connected with an <emphasis>after</emphasis> flag of %TRUE |
|
86 * </para></listitem></varlistentry> |
|
87 * <varlistentry><term></term><listitem><para> |
|
88 * 5 - Invocation of the object method handler for %G_SIGNAL_RUN_CLEANUP signals |
|
89 * </para></listitem></varlistentry> |
|
90 * </variablelist> |
|
91 * The user-provided signal handlers are called in the order they were |
|
92 * connected in. |
|
93 * All handlers may prematurely stop a signal emission, and any number of |
|
94 * handlers may be connected, disconnected, blocked or unblocked during |
|
95 * a signal emission. |
|
96 * There are certain criteria for skipping user handlers in stages 2 and 4 |
|
97 * of a signal emission. |
|
98 * First, user handlers may be <emphasis>blocked</emphasis>, blocked handlers are omitted |
|
99 * during callback invocation, to return from the "blocked" state, a |
|
100 * handler has to get unblocked exactly the same amount of times |
|
101 * it has been blocked before. |
|
102 * Second, upon emission of a %G_SIGNAL_DETAILED signal, an additional |
|
103 * "detail" argument passed in to g_signal_emit() has to match the detail |
|
104 * argument of the signal handler currently subject to invocation. |
|
105 * Specification of no detail argument for signal handlers (omission of the |
|
106 * detail part of the signal specification upon connection) serves as a |
|
107 * wildcard and matches any detail argument passed in to emission. |
|
108 */ |
|
109 |
|
110 |
|
111 #define REPORT_BUG "please report occurrence circumstances to gtk-devel-list@gnome.org" |
|
112 #ifdef G_ENABLE_DEBUG |
|
113 #define IF_DEBUG(debug_type, cond) if ((_g_type_debug_flags & G_TYPE_DEBUG_ ## debug_type) || cond) |
|
114 |
|
115 #if EMULATOR |
|
116 |
|
117 PLS(g_trace_instance_signals,gsignal,volatile gpointer ) |
|
118 PLS(g_trap_instance_signals,gsignal,volatile gpointer ) |
|
119 |
|
120 #define g_trace_instance_signals (*FUNCTION_NAME(g_trace_instance_signals,gsignal)()) |
|
121 #define g_trap_instance_signals (*FUNCTION_NAME(g_trap_instance_signals,gsignal)()) |
|
122 |
|
123 #else |
|
124 |
|
125 static volatile gpointer g_trace_instance_signals = NULL; |
|
126 static volatile gpointer g_trap_instance_signals = NULL; |
|
127 |
|
128 #endif /* EMULATOR */ |
|
129 #endif /* G_ENABLE_DEBUG */ |
|
130 |
|
131 |
|
132 /* --- typedefs --- */ |
|
133 typedef struct _SignalNode SignalNode; |
|
134 typedef struct _SignalKey SignalKey; |
|
135 typedef struct _Emission Emission; |
|
136 typedef struct _Handler Handler; |
|
137 typedef struct _HandlerList HandlerList; |
|
138 typedef struct _HandlerMatch HandlerMatch; |
|
139 typedef enum |
|
140 { |
|
141 EMISSION_STOP, |
|
142 EMISSION_RUN, |
|
143 EMISSION_HOOK, |
|
144 EMISSION_RESTART |
|
145 } EmissionState; |
|
146 |
|
147 |
|
148 /* --- prototypes --- */ |
|
149 static inline guint signal_id_lookup (GQuark quark, |
|
150 GType itype); |
|
151 static void signal_destroy_R (SignalNode *signal_node); |
|
152 static inline HandlerList* handler_list_ensure (guint signal_id, |
|
153 gpointer instance); |
|
154 static inline HandlerList* handler_list_lookup (guint signal_id, |
|
155 gpointer instance); |
|
156 static inline Handler* handler_new (gboolean after); |
|
157 static void handler_insert (guint signal_id, |
|
158 gpointer instance, |
|
159 Handler *handler); |
|
160 static Handler* handler_lookup (gpointer instance, |
|
161 gulong handler_id, |
|
162 guint *signal_id_p); |
|
163 static inline HandlerMatch* handler_match_prepend (HandlerMatch *list, |
|
164 Handler *handler, |
|
165 guint signal_id); |
|
166 static inline HandlerMatch* handler_match_free1_R (HandlerMatch *node, |
|
167 gpointer instance); |
|
168 static HandlerMatch* handlers_find (gpointer instance, |
|
169 GSignalMatchType mask, |
|
170 guint signal_id, |
|
171 GQuark detail, |
|
172 GClosure *closure, |
|
173 gpointer func, |
|
174 gpointer data, |
|
175 gboolean one_and_only); |
|
176 static inline void handler_ref (Handler *handler); |
|
177 static inline void handler_unref_R (guint signal_id, |
|
178 gpointer instance, |
|
179 Handler *handler); |
|
180 static gint handler_lists_cmp (gconstpointer node1, |
|
181 gconstpointer node2); |
|
182 static inline void emission_push (Emission **emission_list_p, |
|
183 Emission *emission); |
|
184 static inline void emission_pop (Emission **emission_list_p, |
|
185 Emission *emission); |
|
186 static inline Emission* emission_find (Emission *emission_list, |
|
187 guint signal_id, |
|
188 GQuark detail, |
|
189 gpointer instance); |
|
190 static gint class_closures_cmp (gconstpointer node1, |
|
191 gconstpointer node2); |
|
192 static gint signal_key_cmp (gconstpointer node1, |
|
193 gconstpointer node2); |
|
194 static gboolean signal_emit_unlocked_R (SignalNode *node, |
|
195 GQuark detail, |
|
196 gpointer instance, |
|
197 GValue *return_value, |
|
198 const GValue *instance_and_params); |
|
199 static const gchar * type_debug_name (GType type); |
|
200 |
|
201 |
|
202 /* --- structures --- */ |
|
203 typedef struct |
|
204 { |
|
205 GSignalAccumulator func; |
|
206 gpointer data; |
|
207 } SignalAccumulator; |
|
208 typedef struct |
|
209 { |
|
210 GHook hook; |
|
211 GQuark detail; |
|
212 } SignalHook; |
|
213 #define SIGNAL_HOOK(hook) ((SignalHook*) (hook)) |
|
214 |
|
215 struct _SignalNode |
|
216 { |
|
217 /* permanent portion */ |
|
218 guint signal_id; |
|
219 GType itype; |
|
220 const gchar *name; |
|
221 guint destroyed : 1; |
|
222 |
|
223 /* reinitializable portion */ |
|
224 guint test_class_offset : 12; |
|
225 guint flags : 8; |
|
226 guint n_params : 8; |
|
227 GType *param_types; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */ |
|
228 GType return_type; /* mangled with G_SIGNAL_TYPE_STATIC_SCOPE flag */ |
|
229 GBSearchArray *class_closure_bsa; |
|
230 SignalAccumulator *accumulator; |
|
231 GSignalCMarshaller c_marshaller; |
|
232 GHookList *emission_hooks; |
|
233 }; |
|
234 #define MAX_TEST_CLASS_OFFSET (4096) /* 2^12, 12 bits for test_class_offset */ |
|
235 #define TEST_CLASS_MAGIC (1) /* indicates NULL class closure, candidate for NOP optimization */ |
|
236 |
|
237 struct _SignalKey |
|
238 { |
|
239 GType itype; |
|
240 GQuark quark; |
|
241 guint signal_id; |
|
242 }; |
|
243 |
|
244 struct _Emission |
|
245 { |
|
246 Emission *next; |
|
247 gpointer instance; |
|
248 GSignalInvocationHint ihint; |
|
249 EmissionState state; |
|
250 GType chain_type; |
|
251 }; |
|
252 |
|
253 struct _HandlerList |
|
254 { |
|
255 guint signal_id; |
|
256 Handler *handlers; |
|
257 Handler *tail_before; /* normal signal handlers are appended here */ |
|
258 Handler *tail_after; /* CONNECT_AFTER handlers are appended here */ |
|
259 }; |
|
260 |
|
261 struct _Handler |
|
262 { |
|
263 gulong sequential_number; |
|
264 Handler *next; |
|
265 Handler *prev; |
|
266 GQuark detail; |
|
267 guint ref_count; |
|
268 guint block_count : 16; |
|
269 #define HANDLER_MAX_BLOCK_COUNT (1 << 16) |
|
270 guint after : 1; |
|
271 GClosure *closure; |
|
272 }; |
|
273 struct _HandlerMatch |
|
274 { |
|
275 Handler *handler; |
|
276 HandlerMatch *next; |
|
277 guint signal_id; |
|
278 }; |
|
279 |
|
280 typedef struct |
|
281 { |
|
282 GType instance_type; /* 0 for default closure */ |
|
283 GClosure *closure; |
|
284 } ClassClosure; |
|
285 |
|
286 |
|
287 /* --- variables --- */ |
|
288 #if EMULATOR |
|
289 |
|
290 PLS(g_signal_key_bsa,gsignal,GBSearchArray *) |
|
291 PLS(g_signal_hlbsa_bconfig,gsignal,GBSearchConfig) |
|
292 PLS(g_class_closure_bconfig,gsignal,GBSearchConfig) |
|
293 PLS(g_handler_list_bsa_ht,gsignal,GHashTable *) |
|
294 PLS(g_recursive_emissions,gsignal,Emission *) |
|
295 PLS(g_restart_emissions ,gsignal,Emission *) |
|
296 PLS(g_handler_sequential_number ,gsignal,gulong) |
|
297 PLS_MACRO(g_signal_mutex,gsignal,GStaticMutex) |
|
298 PLS(g_n_signal_nodes,gsignal,guint) |
|
299 PLS(g_signal_nodes ,gsignal,SignalNode **) |
|
300 |
|
301 #define g_signal_key_bsa (*FUNCTION_NAME(g_signal_key_bsa,gsignal)()) |
|
302 #define g_signal_hlbsa_bconfig (*FUNCTION_NAME(g_signal_hlbsa_bconfig,gsignal)()) |
|
303 #define g_class_closure_bconfig (*FUNCTION_NAME(g_class_closure_bconfig,gsignal)()) |
|
304 #define g_handler_list_bsa_ht (*FUNCTION_NAME(g_handler_list_bsa_ht,gsignal)()) |
|
305 #define g_recursive_emissions (*FUNCTION_NAME(g_recursive_emissions,gsignal)()) |
|
306 #define g_restart_emissions (*FUNCTION_NAME(g_restart_emissions ,gsignal)()) |
|
307 #define g_handler_sequential_number (*FUNCTION_NAME(g_handler_sequential_number ,gsignal)()) |
|
308 #define g__g_signal_mutex_lock (*FUNCTION_NAME_MACRO(g_signal_mutex,gsignal)()) |
|
309 #define g_n_signal_nodes (*FUNCTION_NAME(g_n_signal_nodes,gsignal)()) |
|
310 #define g_signal_nodes (*FUNCTION_NAME(g_signal_nodes,gsignal)()) |
|
311 |
|
312 const GBSearchConfig temp_g_signal_hlbsa_bconfig = { |
|
313 sizeof (HandlerList), |
|
314 handler_lists_cmp, |
|
315 0, |
|
316 }; |
|
317 |
|
318 const GBSearchConfig temp_g_class_closure_bconfig = { |
|
319 sizeof (ClassClosure), |
|
320 class_closures_cmp, |
|
321 0, |
|
322 }; |
|
323 |
|
324 #else |
|
325 static GBSearchArray *g_signal_key_bsa = NULL; |
|
326 #endif//EMULATOR |
|
327 static const GBSearchConfig g_signal_key_bconfig = { |
|
328 sizeof (SignalKey), |
|
329 signal_key_cmp, |
|
330 G_BSEARCH_ARRAY_ALIGN_POWER2, |
|
331 }; |
|
332 #if (!EMULATOR) |
|
333 static GBSearchConfig g_signal_hlbsa_bconfig = { |
|
334 sizeof (HandlerList), |
|
335 handler_lists_cmp, |
|
336 0, |
|
337 }; |
|
338 static GBSearchConfig g_class_closure_bconfig = { |
|
339 sizeof (ClassClosure), |
|
340 class_closures_cmp, |
|
341 0, |
|
342 }; |
|
343 static GHashTable *g_handler_list_bsa_ht = NULL; |
|
344 static Emission *g_recursive_emissions = NULL; |
|
345 static Emission *g_restart_emissions = NULL; |
|
346 static gulong g_handler_sequential_number = 1; |
|
347 G_LOCK_DEFINE_STATIC (g_signal_mutex); |
|
348 #endif//EMULATOR |
|
349 |
|
350 #define SIGNAL_LOCK() G_LOCK (g_signal_mutex) |
|
351 #define SIGNAL_UNLOCK() G_UNLOCK (g_signal_mutex) |
|
352 |
|
353 /* --- signal nodes --- */ |
|
354 #if (!EMULATOR) |
|
355 static guint g_n_signal_nodes = 0; |
|
356 static SignalNode **g_signal_nodes = NULL; |
|
357 |
|
358 #endif /* EMULATOR */ |
|
359 |
|
360 static inline SignalNode* |
|
361 LOOKUP_SIGNAL_NODE (register guint signal_id) |
|
362 { |
|
363 if (signal_id < g_n_signal_nodes) |
|
364 return g_signal_nodes[signal_id]; |
|
365 else |
|
366 return NULL; |
|
367 } |
|
368 |
|
369 |
|
370 /* --- functions --- */ |
|
371 static inline guint |
|
372 signal_id_lookup (GQuark quark, |
|
373 GType itype) |
|
374 { |
|
375 GType *ifaces, type = itype; |
|
376 SignalKey key; |
|
377 guint n_ifaces; |
|
378 |
|
379 key.quark = quark; |
|
380 |
|
381 /* try looking up signals for this type and its ancestors */ |
|
382 do |
|
383 { |
|
384 SignalKey *signal_key; |
|
385 |
|
386 key.itype = type; |
|
387 signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key); |
|
388 |
|
389 if (signal_key) |
|
390 return signal_key->signal_id; |
|
391 |
|
392 type = g_type_parent (type); |
|
393 } |
|
394 while (type); |
|
395 |
|
396 /* no luck, try interfaces it exports */ |
|
397 ifaces = g_type_interfaces (itype, &n_ifaces); |
|
398 while (n_ifaces--) |
|
399 { |
|
400 SignalKey *signal_key; |
|
401 |
|
402 key.itype = ifaces[n_ifaces]; |
|
403 signal_key = g_bsearch_array_lookup (g_signal_key_bsa, &g_signal_key_bconfig, &key); |
|
404 |
|
405 if (signal_key) |
|
406 { |
|
407 g_free (ifaces); |
|
408 return signal_key->signal_id; |
|
409 } |
|
410 } |
|
411 g_free (ifaces); |
|
412 |
|
413 return 0; |
|
414 } |
|
415 |
|
416 static gint |
|
417 class_closures_cmp (gconstpointer node1, |
|
418 gconstpointer node2) |
|
419 { |
|
420 const ClassClosure *c1 = node1, *c2 = node2; |
|
421 |
|
422 return G_BSEARCH_ARRAY_CMP (c1->instance_type, c2->instance_type); |
|
423 } |
|
424 |
|
425 static gint |
|
426 handler_lists_cmp (gconstpointer node1, |
|
427 gconstpointer node2) |
|
428 { |
|
429 const HandlerList *hlist1 = node1, *hlist2 = node2; |
|
430 |
|
431 return G_BSEARCH_ARRAY_CMP (hlist1->signal_id, hlist2->signal_id); |
|
432 } |
|
433 |
|
434 static inline HandlerList* |
|
435 handler_list_ensure (guint signal_id, |
|
436 gpointer instance) |
|
437 { |
|
438 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); |
|
439 HandlerList key; |
|
440 |
|
441 key.signal_id = signal_id; |
|
442 key.handlers = NULL; |
|
443 key.tail_before = NULL; |
|
444 key.tail_after = NULL; |
|
445 if (!hlbsa) |
|
446 { |
|
447 hlbsa = g_bsearch_array_create (&g_signal_hlbsa_bconfig); |
|
448 hlbsa = g_bsearch_array_insert (hlbsa, &g_signal_hlbsa_bconfig, &key); |
|
449 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa); |
|
450 } |
|
451 else |
|
452 { |
|
453 GBSearchArray *o = hlbsa; |
|
454 |
|
455 hlbsa = g_bsearch_array_insert (o, &g_signal_hlbsa_bconfig, &key); |
|
456 if (hlbsa != o) |
|
457 g_hash_table_insert (g_handler_list_bsa_ht, instance, hlbsa); |
|
458 } |
|
459 return g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key); |
|
460 } |
|
461 |
|
462 static inline HandlerList* |
|
463 handler_list_lookup (guint signal_id, |
|
464 gpointer instance) |
|
465 { |
|
466 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); |
|
467 HandlerList key; |
|
468 |
|
469 key.signal_id = signal_id; |
|
470 |
|
471 return hlbsa ? g_bsearch_array_lookup (hlbsa, &g_signal_hlbsa_bconfig, &key) : NULL; |
|
472 } |
|
473 |
|
474 static Handler* |
|
475 handler_lookup (gpointer instance, |
|
476 gulong handler_id, |
|
477 guint *signal_id_p) |
|
478 { |
|
479 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); |
|
480 |
|
481 if (hlbsa) |
|
482 { |
|
483 guint i; |
|
484 |
|
485 for (i = 0; i < hlbsa->n_nodes; i++) |
|
486 { |
|
487 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); |
|
488 Handler *handler; |
|
489 |
|
490 for (handler = hlist->handlers; handler; handler = handler->next) |
|
491 if (handler->sequential_number == handler_id) |
|
492 { |
|
493 if (signal_id_p) |
|
494 *signal_id_p = hlist->signal_id; |
|
495 |
|
496 return handler; |
|
497 } |
|
498 } |
|
499 } |
|
500 |
|
501 return NULL; |
|
502 } |
|
503 |
|
504 static inline HandlerMatch* |
|
505 handler_match_prepend (HandlerMatch *list, |
|
506 Handler *handler, |
|
507 guint signal_id) |
|
508 { |
|
509 HandlerMatch *node; |
|
510 |
|
511 node = g_slice_new (HandlerMatch); |
|
512 node->handler = handler; |
|
513 node->next = list; |
|
514 node->signal_id = signal_id; |
|
515 handler_ref (handler); |
|
516 |
|
517 return node; |
|
518 } |
|
519 static inline HandlerMatch* |
|
520 handler_match_free1_R (HandlerMatch *node, |
|
521 gpointer instance) |
|
522 { |
|
523 HandlerMatch *next = node->next; |
|
524 |
|
525 handler_unref_R (node->signal_id, instance, node->handler); |
|
526 g_slice_free (HandlerMatch, node); |
|
527 |
|
528 return next; |
|
529 } |
|
530 |
|
531 static HandlerMatch* |
|
532 handlers_find (gpointer instance, |
|
533 GSignalMatchType mask, |
|
534 guint signal_id, |
|
535 GQuark detail, |
|
536 GClosure *closure, |
|
537 gpointer func, |
|
538 gpointer data, |
|
539 gboolean one_and_only) |
|
540 { |
|
541 HandlerMatch *mlist = NULL; |
|
542 |
|
543 if (mask & G_SIGNAL_MATCH_ID) |
|
544 { |
|
545 HandlerList *hlist = handler_list_lookup (signal_id, instance); |
|
546 Handler *handler; |
|
547 SignalNode *node = NULL; |
|
548 |
|
549 if (mask & G_SIGNAL_MATCH_FUNC) |
|
550 { |
|
551 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
552 if (!node || !node->c_marshaller) |
|
553 return NULL; |
|
554 } |
|
555 |
|
556 mask = ~mask; |
|
557 for (handler = hlist ? hlist->handlers : NULL; handler; handler = handler->next) |
|
558 if (handler->sequential_number && |
|
559 ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && |
|
560 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && |
|
561 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && |
|
562 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && |
|
563 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && |
|
564 handler->closure->meta_marshal == 0 && |
|
565 ((GCClosure*) handler->closure)->callback == func))) |
|
566 { |
|
567 mlist = handler_match_prepend (mlist, handler, signal_id); |
|
568 if (one_and_only) |
|
569 return mlist; |
|
570 } |
|
571 } |
|
572 else |
|
573 { |
|
574 GBSearchArray *hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); |
|
575 |
|
576 mask = ~mask; |
|
577 if (hlbsa) |
|
578 { |
|
579 guint i; |
|
580 |
|
581 for (i = 0; i < hlbsa->n_nodes; i++) |
|
582 { |
|
583 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); |
|
584 SignalNode *node = NULL; |
|
585 Handler *handler; |
|
586 |
|
587 if (!(mask & G_SIGNAL_MATCH_FUNC)) |
|
588 { |
|
589 node = LOOKUP_SIGNAL_NODE (hlist->signal_id); |
|
590 if (!node->c_marshaller) |
|
591 continue; |
|
592 } |
|
593 |
|
594 for (handler = hlist->handlers; handler; handler = handler->next) |
|
595 if (handler->sequential_number && |
|
596 ((mask & G_SIGNAL_MATCH_DETAIL) || handler->detail == detail) && |
|
597 ((mask & G_SIGNAL_MATCH_CLOSURE) || handler->closure == closure) && |
|
598 ((mask & G_SIGNAL_MATCH_DATA) || handler->closure->data == data) && |
|
599 ((mask & G_SIGNAL_MATCH_UNBLOCKED) || handler->block_count == 0) && |
|
600 ((mask & G_SIGNAL_MATCH_FUNC) || (handler->closure->marshal == node->c_marshaller && |
|
601 handler->closure->meta_marshal == 0 && |
|
602 ((GCClosure*) handler->closure)->callback == func))) |
|
603 { |
|
604 mlist = handler_match_prepend (mlist, handler, hlist->signal_id); |
|
605 if (one_and_only) |
|
606 return mlist; |
|
607 } |
|
608 } |
|
609 } |
|
610 } |
|
611 |
|
612 return mlist; |
|
613 } |
|
614 |
|
615 static inline Handler* |
|
616 handler_new (gboolean after) |
|
617 { |
|
618 Handler *handler = g_slice_new (Handler); |
|
619 #ifndef G_DISABLE_CHECKS |
|
620 if (g_handler_sequential_number < 1) |
|
621 g_error (G_STRLOC ": handler id overflow, %s", REPORT_BUG); |
|
622 #endif |
|
623 |
|
624 handler->sequential_number = g_handler_sequential_number++; |
|
625 handler->prev = NULL; |
|
626 handler->next = NULL; |
|
627 handler->detail = 0; |
|
628 handler->ref_count = 1; |
|
629 handler->block_count = 0; |
|
630 handler->after = after != FALSE; |
|
631 handler->closure = NULL; |
|
632 |
|
633 return handler; |
|
634 } |
|
635 |
|
636 static inline void |
|
637 handler_ref (Handler *handler) |
|
638 { |
|
639 g_return_if_fail (handler->ref_count > 0); |
|
640 |
|
641 g_atomic_int_inc ((int *)&handler->ref_count); |
|
642 } |
|
643 |
|
644 static inline void |
|
645 handler_unref_R (guint signal_id, |
|
646 gpointer instance, |
|
647 Handler *handler) |
|
648 { |
|
649 gboolean is_zero; |
|
650 |
|
651 g_return_if_fail (handler->ref_count > 0); |
|
652 |
|
653 is_zero = g_atomic_int_dec_and_test ((int *)&handler->ref_count); |
|
654 |
|
655 if (G_UNLIKELY (is_zero)) |
|
656 { |
|
657 HandlerList *hlist = NULL; |
|
658 |
|
659 if (handler->next) |
|
660 handler->next->prev = handler->prev; |
|
661 if (handler->prev) /* watch out for g_signal_handlers_destroy()! */ |
|
662 handler->prev->next = handler->next; |
|
663 else |
|
664 { |
|
665 hlist = handler_list_lookup (signal_id, instance); |
|
666 hlist->handlers = handler->next; |
|
667 } |
|
668 |
|
669 if (instance) |
|
670 { |
|
671 /* check if we are removing the handler pointed to by tail_before */ |
|
672 if (!handler->after && (!handler->next || handler->next->after)) |
|
673 { |
|
674 if (!hlist) |
|
675 hlist = handler_list_lookup (signal_id, instance); |
|
676 if (hlist) |
|
677 { |
|
678 g_assert (hlist->tail_before == handler); /* paranoid */ |
|
679 hlist->tail_before = handler->prev; |
|
680 } |
|
681 } |
|
682 |
|
683 /* check if we are removing the handler pointed to by tail_after */ |
|
684 if (!handler->next) |
|
685 { |
|
686 if (!hlist) |
|
687 hlist = handler_list_lookup (signal_id, instance); |
|
688 if (hlist) |
|
689 { |
|
690 g_assert (hlist->tail_after == handler); /* paranoid */ |
|
691 hlist->tail_after = handler->prev; |
|
692 } |
|
693 } |
|
694 } |
|
695 |
|
696 SIGNAL_UNLOCK (); |
|
697 g_closure_unref (handler->closure); |
|
698 SIGNAL_LOCK (); |
|
699 g_slice_free (Handler, handler); |
|
700 } |
|
701 } |
|
702 |
|
703 static void |
|
704 handler_insert (guint signal_id, |
|
705 gpointer instance, |
|
706 Handler *handler) |
|
707 { |
|
708 HandlerList *hlist; |
|
709 |
|
710 g_assert (handler->prev == NULL && handler->next == NULL); /* paranoid */ |
|
711 |
|
712 hlist = handler_list_ensure (signal_id, instance); |
|
713 if (!hlist->handlers) |
|
714 { |
|
715 hlist->handlers = handler; |
|
716 if (!handler->after) |
|
717 hlist->tail_before = handler; |
|
718 } |
|
719 else if (handler->after) |
|
720 { |
|
721 handler->prev = hlist->tail_after; |
|
722 hlist->tail_after->next = handler; |
|
723 } |
|
724 else |
|
725 { |
|
726 if (hlist->tail_before) |
|
727 { |
|
728 handler->next = hlist->tail_before->next; |
|
729 if (handler->next) |
|
730 handler->next->prev = handler; |
|
731 handler->prev = hlist->tail_before; |
|
732 hlist->tail_before->next = handler; |
|
733 } |
|
734 else /* insert !after handler into a list of only after handlers */ |
|
735 { |
|
736 handler->next = hlist->handlers; |
|
737 if (handler->next) |
|
738 handler->next->prev = handler; |
|
739 hlist->handlers = handler; |
|
740 } |
|
741 hlist->tail_before = handler; |
|
742 } |
|
743 |
|
744 if (!handler->next) |
|
745 hlist->tail_after = handler; |
|
746 } |
|
747 |
|
748 static inline void |
|
749 emission_push (Emission **emission_list_p, |
|
750 Emission *emission) |
|
751 { |
|
752 emission->next = *emission_list_p; |
|
753 *emission_list_p = emission; |
|
754 } |
|
755 |
|
756 static inline void |
|
757 emission_pop (Emission **emission_list_p, |
|
758 Emission *emission) |
|
759 { |
|
760 Emission *node, *last = NULL; |
|
761 |
|
762 for (node = *emission_list_p; node; last = node, node = last->next) |
|
763 if (node == emission) |
|
764 { |
|
765 if (last) |
|
766 last->next = node->next; |
|
767 else |
|
768 *emission_list_p = node->next; |
|
769 return; |
|
770 } |
|
771 g_assert_not_reached (); |
|
772 } |
|
773 |
|
774 static inline Emission* |
|
775 emission_find (Emission *emission_list, |
|
776 guint signal_id, |
|
777 GQuark detail, |
|
778 gpointer instance) |
|
779 { |
|
780 Emission *emission; |
|
781 |
|
782 for (emission = emission_list; emission; emission = emission->next) |
|
783 if (emission->instance == instance && |
|
784 emission->ihint.signal_id == signal_id && |
|
785 emission->ihint.detail == detail) |
|
786 return emission; |
|
787 return NULL; |
|
788 } |
|
789 |
|
790 static inline Emission* |
|
791 emission_find_innermost (gpointer instance) |
|
792 { |
|
793 Emission *emission, *s = NULL, *c = NULL; |
|
794 |
|
795 for (emission = g_restart_emissions; emission; emission = emission->next) |
|
796 if (emission->instance == instance) |
|
797 { |
|
798 s = emission; |
|
799 break; |
|
800 } |
|
801 for (emission = g_recursive_emissions; emission; emission = emission->next) |
|
802 if (emission->instance == instance) |
|
803 { |
|
804 c = emission; |
|
805 break; |
|
806 } |
|
807 if (!s) |
|
808 return c; |
|
809 else if (!c) |
|
810 return s; |
|
811 else |
|
812 return G_HAVE_GROWING_STACK ? MAX (c, s) : MIN (c, s); |
|
813 } |
|
814 |
|
815 static gint |
|
816 signal_key_cmp (gconstpointer node1, |
|
817 gconstpointer node2) |
|
818 { |
|
819 const SignalKey *key1 = node1, *key2 = node2; |
|
820 |
|
821 if (key1->itype == key2->itype) |
|
822 return G_BSEARCH_ARRAY_CMP (key1->quark, key2->quark); |
|
823 else |
|
824 return G_BSEARCH_ARRAY_CMP (key1->itype, key2->itype); |
|
825 } |
|
826 |
|
827 void |
|
828 g_signal_init (void) |
|
829 { |
|
830 SIGNAL_LOCK (); |
|
831 if (!g_n_signal_nodes) |
|
832 { |
|
833 /* setup handler list binary searchable array hash table (in german, that'd be one word ;) */ |
|
834 g_handler_list_bsa_ht = g_hash_table_new (g_direct_hash, NULL); |
|
835 g_signal_key_bsa = g_bsearch_array_create (&g_signal_key_bconfig); |
|
836 |
|
837 /* invalid (0) signal_id */ |
|
838 g_n_signal_nodes = 1; |
|
839 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); |
|
840 g_signal_nodes[0] = NULL; |
|
841 } |
|
842 SIGNAL_UNLOCK (); |
|
843 } |
|
844 |
|
845 void |
|
846 _g_signals_destroy (GType itype) |
|
847 { |
|
848 guint i; |
|
849 |
|
850 SIGNAL_LOCK (); |
|
851 for (i = 1; i < g_n_signal_nodes; i++) |
|
852 { |
|
853 SignalNode *node = g_signal_nodes[i]; |
|
854 |
|
855 if (node->itype == itype) |
|
856 { |
|
857 if (node->destroyed) |
|
858 g_warning (G_STRLOC ": signal \"%s\" of type `%s' already destroyed", |
|
859 node->name, |
|
860 type_debug_name (node->itype)); |
|
861 else |
|
862 signal_destroy_R (node); |
|
863 } |
|
864 } |
|
865 SIGNAL_UNLOCK (); |
|
866 } |
|
867 |
|
868 /** |
|
869 * g_signal_stop_emission: |
|
870 * @instance: the object whose signal handlers you wish to stop. |
|
871 * @signal_id: the signal identifier, as returned by g_signal_lookup(). |
|
872 * @detail: the detail which the signal was emitted with. |
|
873 * |
|
874 * Stops a signal's current emission. |
|
875 * |
|
876 * This will prevent the default method from running, if the signal was |
|
877 * %G_SIGNAL_RUN_LAST and you connected normally (i.e. without the "after" |
|
878 * flag). |
|
879 * |
|
880 * Prints a warning if used on a signal which isn't being emitted. |
|
881 */ |
|
882 EXPORT_C void |
|
883 g_signal_stop_emission (gpointer instance, |
|
884 guint signal_id, |
|
885 GQuark detail) |
|
886 { |
|
887 SignalNode *node; |
|
888 |
|
889 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
890 g_return_if_fail (signal_id > 0); |
|
891 |
|
892 SIGNAL_LOCK (); |
|
893 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
894 if (node && detail && !(node->flags & G_SIGNAL_DETAILED)) |
|
895 { |
|
896 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); |
|
897 SIGNAL_UNLOCK (); |
|
898 return; |
|
899 } |
|
900 if (node && g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) |
|
901 { |
|
902 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; |
|
903 Emission *emission = emission_find (emission_list, signal_id, detail, instance); |
|
904 |
|
905 if (emission) |
|
906 { |
|
907 if (emission->state == EMISSION_HOOK) |
|
908 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", |
|
909 node->name, instance); |
|
910 else if (emission->state == EMISSION_RUN) |
|
911 emission->state = EMISSION_STOP; |
|
912 } |
|
913 else |
|
914 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", |
|
915 node->name, instance); |
|
916 } |
|
917 else |
|
918 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); |
|
919 SIGNAL_UNLOCK (); |
|
920 } |
|
921 |
|
922 static void |
|
923 signal_finalize_hook (GHookList *hook_list, |
|
924 GHook *hook) |
|
925 { |
|
926 GDestroyNotify destroy = hook->destroy; |
|
927 |
|
928 if (destroy) |
|
929 { |
|
930 hook->destroy = NULL; |
|
931 SIGNAL_UNLOCK (); |
|
932 destroy (hook->data); |
|
933 SIGNAL_LOCK (); |
|
934 } |
|
935 } |
|
936 |
|
937 #if EMULATOR |
|
938 PLS(seq_hook_id ,g_signal_add_emission_hook ,gulong) |
|
939 #define seq_hook_id (*FUNCTION_NAME(seq_hook_id ,g_signal_add_emission_hook)()) |
|
940 #endif /* EMULATOR */ |
|
941 |
|
942 /** |
|
943 * g_signal_add_emission_hook: |
|
944 * @signal_id: the signal identifier, as returned by g_signal_lookup(). |
|
945 * @detail: the detail on which to call the hook. |
|
946 * @hook_func: a #GSignalEmissionHook function. |
|
947 * @hook_data: user data for @hook_func. |
|
948 * @data_destroy: a #GDestroyNotify for @hook_data. |
|
949 * |
|
950 * Adds an emission hook for a signal, which will get called for any emission |
|
951 * of that signal, independent of the instance. This is possible only |
|
952 * for signals which don't have #G_SIGNAL_NO_HOOKS flag set. |
|
953 * |
|
954 * Returns: the hook id, for later use with g_signal_remove_emission_hook(). |
|
955 */ |
|
956 EXPORT_C gulong |
|
957 g_signal_add_emission_hook (guint signal_id, |
|
958 GQuark detail, |
|
959 GSignalEmissionHook hook_func, |
|
960 gpointer hook_data, |
|
961 GDestroyNotify data_destroy) |
|
962 { |
|
963 #if !(EMULATOR) |
|
964 static gulong seq_hook_id = 1; |
|
965 #endif /* EMULATOR */ |
|
966 SignalNode *node; |
|
967 GHook *hook; |
|
968 SignalHook *signal_hook; |
|
969 |
|
970 g_return_val_if_fail (signal_id > 0, 0); |
|
971 g_return_val_if_fail (hook_func != NULL, 0); |
|
972 |
|
973 SIGNAL_LOCK (); |
|
974 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
975 if (!node || node->destroyed) |
|
976 { |
|
977 g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); |
|
978 SIGNAL_UNLOCK (); |
|
979 return 0; |
|
980 } |
|
981 if (node->flags & G_SIGNAL_NO_HOOKS) |
|
982 { |
|
983 g_warning ("%s: signal id `%u' does not support emission hooks (G_SIGNAL_NO_HOOKS flag set)", G_STRLOC, signal_id); |
|
984 SIGNAL_UNLOCK (); |
|
985 return 0; |
|
986 } |
|
987 if (detail && !(node->flags & G_SIGNAL_DETAILED)) |
|
988 { |
|
989 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); |
|
990 SIGNAL_UNLOCK (); |
|
991 return 0; |
|
992 } |
|
993 if (!node->emission_hooks) |
|
994 { |
|
995 node->emission_hooks = g_new (GHookList, 1); |
|
996 g_hook_list_init (node->emission_hooks, sizeof (SignalHook)); |
|
997 node->emission_hooks->finalize_hook = signal_finalize_hook; |
|
998 } |
|
999 hook = g_hook_alloc (node->emission_hooks); |
|
1000 hook->data = hook_data; |
|
1001 hook->func = (gpointer) hook_func; |
|
1002 hook->destroy = data_destroy; |
|
1003 signal_hook = SIGNAL_HOOK (hook); |
|
1004 signal_hook->detail = detail; |
|
1005 node->emission_hooks->seq_id = seq_hook_id; |
|
1006 g_hook_append (node->emission_hooks, hook); |
|
1007 seq_hook_id = node->emission_hooks->seq_id; |
|
1008 SIGNAL_UNLOCK (); |
|
1009 |
|
1010 return hook->hook_id; |
|
1011 } |
|
1012 |
|
1013 #if EMULATOR |
|
1014 #undef seq_hook_id |
|
1015 #endif /* EMULATOR */ |
|
1016 |
|
1017 /** |
|
1018 * g_signal_remove_emission_hook: |
|
1019 * @signal_id: the id of the signal |
|
1020 * @hook_id: the id of the emission hook, as returned by |
|
1021 * g_signal_add_emission_hook() |
|
1022 * |
|
1023 * Deletes an emission hook. |
|
1024 */ |
|
1025 EXPORT_C void |
|
1026 g_signal_remove_emission_hook (guint signal_id, |
|
1027 gulong hook_id) |
|
1028 { |
|
1029 SignalNode *node; |
|
1030 |
|
1031 g_return_if_fail (signal_id > 0); |
|
1032 g_return_if_fail (hook_id > 0); |
|
1033 |
|
1034 SIGNAL_LOCK (); |
|
1035 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
1036 if (!node || node->destroyed) |
|
1037 g_warning ("%s: invalid signal id `%u'", G_STRLOC, signal_id); |
|
1038 else if (!node->emission_hooks || !g_hook_destroy (node->emission_hooks, hook_id)) |
|
1039 g_warning ("%s: signal \"%s\" had no hook (%lu) to remove", G_STRLOC, node->name, hook_id); |
|
1040 SIGNAL_UNLOCK (); |
|
1041 } |
|
1042 |
|
1043 static inline guint |
|
1044 signal_parse_name (const gchar *name, |
|
1045 GType itype, |
|
1046 GQuark *detail_p, |
|
1047 gboolean force_quark) |
|
1048 { |
|
1049 const gchar *colon = strchr (name, ':'); |
|
1050 guint signal_id; |
|
1051 |
|
1052 if (!colon) |
|
1053 { |
|
1054 signal_id = signal_id_lookup (g_quark_try_string (name), itype); |
|
1055 if (signal_id && detail_p) |
|
1056 *detail_p = 0; |
|
1057 } |
|
1058 else if (colon[1] == ':') |
|
1059 { |
|
1060 gchar buffer[32]; |
|
1061 guint l = colon - name; |
|
1062 |
|
1063 if (l < 32) |
|
1064 { |
|
1065 memcpy (buffer, name, l); |
|
1066 buffer[l] = 0; |
|
1067 signal_id = signal_id_lookup (g_quark_try_string (buffer), itype); |
|
1068 } |
|
1069 else |
|
1070 { |
|
1071 gchar *signal = g_new (gchar, l + 1); |
|
1072 |
|
1073 memcpy (signal, name, l); |
|
1074 signal[l] = 0; |
|
1075 signal_id = signal_id_lookup (g_quark_try_string (signal), itype); |
|
1076 g_free (signal); |
|
1077 } |
|
1078 |
|
1079 if (signal_id && detail_p) |
|
1080 *detail_p = colon[2] ? (force_quark ? g_quark_from_string : g_quark_try_string) (colon + 2) : 0; |
|
1081 } |
|
1082 else |
|
1083 signal_id = 0; |
|
1084 return signal_id; |
|
1085 } |
|
1086 |
|
1087 /** |
|
1088 * g_signal_parse_name: |
|
1089 * @detailed_signal: a string of the form "signal-name::detail". |
|
1090 * @itype: The interface/instance type that introduced "signal-name". |
|
1091 * @signal_id_p: Location to store the signal id. |
|
1092 * @detail_p: Location to store the detail quark. |
|
1093 * @force_detail_quark: %TRUE forces creation of a #GQuark for the detail. |
|
1094 * |
|
1095 * Internal function to parse a signal name into its @signal_id |
|
1096 * and @detail quark. |
|
1097 * |
|
1098 * Returns: Whether the signal name could successfully be parsed and @signal_id_p and @detail_p contain valid return values. |
|
1099 */ |
|
1100 EXPORT_C gboolean |
|
1101 g_signal_parse_name (const gchar *detailed_signal, |
|
1102 GType itype, |
|
1103 guint *signal_id_p, |
|
1104 GQuark *detail_p, |
|
1105 gboolean force_detail_quark) |
|
1106 { |
|
1107 SignalNode *node; |
|
1108 GQuark detail = 0; |
|
1109 guint signal_id; |
|
1110 |
|
1111 g_return_val_if_fail (detailed_signal != NULL, FALSE); |
|
1112 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), FALSE); |
|
1113 |
|
1114 SIGNAL_LOCK (); |
|
1115 signal_id = signal_parse_name (detailed_signal, itype, &detail, force_detail_quark); |
|
1116 SIGNAL_UNLOCK (); |
|
1117 |
|
1118 node = signal_id ? LOOKUP_SIGNAL_NODE (signal_id) : NULL; |
|
1119 if (!node || node->destroyed || |
|
1120 (detail && !(node->flags & G_SIGNAL_DETAILED))) |
|
1121 return FALSE; |
|
1122 |
|
1123 if (signal_id_p) |
|
1124 *signal_id_p = signal_id; |
|
1125 if (detail_p) |
|
1126 *detail_p = detail; |
|
1127 |
|
1128 return TRUE; |
|
1129 } |
|
1130 |
|
1131 /** |
|
1132 * g_signal_stop_emission_by_name: |
|
1133 * @instance: the object whose signal handlers you wish to stop. |
|
1134 * @detailed_signal: a string of the form "signal-name::detail". |
|
1135 * |
|
1136 * Stops a signal's current emission. |
|
1137 * |
|
1138 * This is just like g_signal_stop_emission() except it will look up the |
|
1139 * signal id for you. |
|
1140 */ |
|
1141 EXPORT_C void |
|
1142 g_signal_stop_emission_by_name (gpointer instance, |
|
1143 const gchar *detailed_signal) |
|
1144 { |
|
1145 guint signal_id; |
|
1146 GQuark detail = 0; |
|
1147 GType itype; |
|
1148 |
|
1149 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
1150 g_return_if_fail (detailed_signal != NULL); |
|
1151 |
|
1152 SIGNAL_LOCK (); |
|
1153 itype = G_TYPE_FROM_INSTANCE (instance); |
|
1154 signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); |
|
1155 if (signal_id) |
|
1156 { |
|
1157 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); |
|
1158 |
|
1159 if (detail && !(node->flags & G_SIGNAL_DETAILED)) |
|
1160 g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); |
|
1161 else if (!g_type_is_a (itype, node->itype)) |
|
1162 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); |
|
1163 else |
|
1164 { |
|
1165 Emission *emission_list = node->flags & G_SIGNAL_NO_RECURSE ? g_restart_emissions : g_recursive_emissions; |
|
1166 Emission *emission = emission_find (emission_list, signal_id, detail, instance); |
|
1167 |
|
1168 if (emission) |
|
1169 { |
|
1170 if (emission->state == EMISSION_HOOK) |
|
1171 g_warning (G_STRLOC ": emission of signal \"%s\" for instance `%p' cannot be stopped from emission hook", |
|
1172 node->name, instance); |
|
1173 else if (emission->state == EMISSION_RUN) |
|
1174 emission->state = EMISSION_STOP; |
|
1175 } |
|
1176 else |
|
1177 g_warning (G_STRLOC ": no emission of signal \"%s\" to stop for instance `%p'", |
|
1178 node->name, instance); |
|
1179 } |
|
1180 } |
|
1181 else |
|
1182 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); |
|
1183 SIGNAL_UNLOCK (); |
|
1184 } |
|
1185 |
|
1186 /** |
|
1187 * g_signal_lookup: |
|
1188 * @name: the signal's name. |
|
1189 * @itype: the type that the signal operates on. |
|
1190 * |
|
1191 * Given the name of the signal and the type of object it connects to, gets |
|
1192 * the signal's identifying integer. Emitting the signal by number is |
|
1193 * somewhat faster than using the name each time. |
|
1194 * |
|
1195 * Also tries the ancestors of the given type. |
|
1196 * |
|
1197 * See g_signal_new() for details on allowed signal names. |
|
1198 * |
|
1199 * Returns: the signal's identifying number, or 0 if no signal was found. |
|
1200 */ |
|
1201 EXPORT_C guint |
|
1202 g_signal_lookup (const gchar *name, |
|
1203 GType itype) |
|
1204 { |
|
1205 guint signal_id; |
|
1206 g_return_val_if_fail (name != NULL, 0); |
|
1207 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); |
|
1208 |
|
1209 SIGNAL_LOCK (); |
|
1210 signal_id = signal_id_lookup (g_quark_try_string (name), itype); |
|
1211 SIGNAL_UNLOCK (); |
|
1212 if (!signal_id) |
|
1213 { |
|
1214 /* give elaborate warnings */ |
|
1215 if (!g_type_name (itype)) |
|
1216 g_warning (G_STRLOC ": unable to lookup signal \"%s\" for invalid type id `%"G_GSIZE_FORMAT"'", |
|
1217 name, itype); |
|
1218 else if (!G_TYPE_IS_INSTANTIATABLE (itype)) |
|
1219 g_warning (G_STRLOC ": unable to lookup signal \"%s\" for non instantiatable type `%s'", |
|
1220 name, g_type_name (itype)); |
|
1221 else if (!g_type_class_peek (itype)) |
|
1222 g_warning (G_STRLOC ": unable to lookup signal \"%s\" of unloaded type `%s'", |
|
1223 name, g_type_name (itype)); |
|
1224 } |
|
1225 |
|
1226 return signal_id; |
|
1227 } |
|
1228 |
|
1229 /** |
|
1230 * g_signal_list_ids: |
|
1231 * @itype: Instance or interface type. |
|
1232 * @n_ids: Location to store the number of signal ids for @itype. |
|
1233 * |
|
1234 * Lists the signals by id that a certain instance or interface type |
|
1235 * created. Further information about the signals can be acquired through |
|
1236 * g_signal_query(). |
|
1237 * |
|
1238 * Returns: Newly allocated array of signal IDs. |
|
1239 */ |
|
1240 EXPORT_C guint* |
|
1241 g_signal_list_ids (GType itype, |
|
1242 guint *n_ids) |
|
1243 { |
|
1244 SignalKey *keys; |
|
1245 GArray *result; |
|
1246 guint n_nodes; |
|
1247 guint i; |
|
1248 |
|
1249 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), NULL); |
|
1250 g_return_val_if_fail (n_ids != NULL, NULL); |
|
1251 |
|
1252 SIGNAL_LOCK (); |
|
1253 keys = g_bsearch_array_get_nth (g_signal_key_bsa, &g_signal_key_bconfig, 0); |
|
1254 n_nodes = g_bsearch_array_get_n_nodes (g_signal_key_bsa); |
|
1255 result = g_array_new (FALSE, FALSE, sizeof (guint)); |
|
1256 |
|
1257 for (i = 0; i < n_nodes; i++) |
|
1258 if (keys[i].itype == itype) |
|
1259 { |
|
1260 const gchar *name = g_quark_to_string (keys[i].quark); |
|
1261 |
|
1262 /* Signal names with "_" in them are aliases to the same |
|
1263 * name with "-" instead of "_". |
|
1264 */ |
|
1265 if (!strchr (name, '_')) |
|
1266 g_array_append_val (result, keys[i].signal_id); |
|
1267 } |
|
1268 *n_ids = result->len; |
|
1269 SIGNAL_UNLOCK (); |
|
1270 if (!n_nodes) |
|
1271 { |
|
1272 /* give elaborate warnings */ |
|
1273 if (!g_type_name (itype)) |
|
1274 g_warning (G_STRLOC ": unable to list signals for invalid type id `%"G_GSIZE_FORMAT"'", |
|
1275 itype); |
|
1276 else if (!G_TYPE_IS_INSTANTIATABLE (itype) && !G_TYPE_IS_INTERFACE (itype)) |
|
1277 g_warning (G_STRLOC ": unable to list signals of non instantiatable type `%s'", |
|
1278 g_type_name (itype)); |
|
1279 else if (!g_type_class_peek (itype) && !G_TYPE_IS_INTERFACE (itype)) |
|
1280 g_warning (G_STRLOC ": unable to list signals of unloaded type `%s'", |
|
1281 g_type_name (itype)); |
|
1282 } |
|
1283 |
|
1284 return (guint*) g_array_free (result, FALSE); |
|
1285 } |
|
1286 |
|
1287 /** |
|
1288 * g_signal_name: |
|
1289 * @signal_id: the signal's identifying number. |
|
1290 * |
|
1291 * Given the signal's identifier, finds its name. |
|
1292 * |
|
1293 * Two different signals may have the same name, if they have differing types. |
|
1294 * |
|
1295 * Returns: the signal name, or %NULL if the signal number was invalid. |
|
1296 */ |
|
1297 EXPORT_C G_CONST_RETURN gchar* |
|
1298 g_signal_name (guint signal_id) |
|
1299 { |
|
1300 SignalNode *node; |
|
1301 const gchar *name; |
|
1302 |
|
1303 SIGNAL_LOCK (); |
|
1304 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
1305 name = node ? node->name : NULL; |
|
1306 SIGNAL_UNLOCK (); |
|
1307 |
|
1308 return (char*) name; |
|
1309 } |
|
1310 |
|
1311 /** |
|
1312 * g_signal_query: |
|
1313 * @signal_id: The signal id of the signal to query information for. |
|
1314 * @query: A user provided structure that is filled in with constant |
|
1315 * values upon success. |
|
1316 * |
|
1317 * Queries the signal system for in-depth information about a |
|
1318 * specific signal. This function will fill in a user-provided |
|
1319 * structure to hold signal-specific information. If an invalid |
|
1320 * signal id is passed in, the @signal_id member of the #GSignalQuery |
|
1321 * is 0. All members filled into the #GSignalQuery structure should |
|
1322 * be considered constant and have to be left untouched. |
|
1323 */ |
|
1324 EXPORT_C void |
|
1325 g_signal_query (guint signal_id, |
|
1326 GSignalQuery *query) |
|
1327 { |
|
1328 SignalNode *node; |
|
1329 |
|
1330 g_return_if_fail (query != NULL); |
|
1331 |
|
1332 SIGNAL_LOCK (); |
|
1333 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
1334 if (!node || node->destroyed) |
|
1335 query->signal_id = 0; |
|
1336 else |
|
1337 { |
|
1338 query->signal_id = node->signal_id; |
|
1339 query->signal_name = node->name; |
|
1340 query->itype = node->itype; |
|
1341 query->signal_flags = node->flags; |
|
1342 query->return_type = node->return_type; |
|
1343 query->n_params = node->n_params; |
|
1344 query->param_types = node->param_types; |
|
1345 } |
|
1346 SIGNAL_UNLOCK (); |
|
1347 } |
|
1348 |
|
1349 /** |
|
1350 * g_signal_new: |
|
1351 * @signal_name: the name for the signal |
|
1352 * @itype: the type this signal pertains to. It will also pertain to |
|
1353 * types which are derived from this type. |
|
1354 * @signal_flags: a combination of #GSignalFlags specifying detail of when |
|
1355 * the default handler is to be invoked. You should at least specify |
|
1356 * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST. |
|
1357 * @class_offset: The offset of the function pointer in the class structure |
|
1358 * for this type. Used to invoke a class method generically. Pass 0 to |
|
1359 * not associate a class method with this signal. |
|
1360 * @accumulator: the accumulator for this signal; may be %NULL. |
|
1361 * @accu_data: user data for the @accumulator. |
|
1362 * @c_marshaller: the function to translate arrays of parameter values to |
|
1363 * signal emissions into C language callback invocations. |
|
1364 * @return_type: the type of return value, or #G_TYPE_NONE for a signal |
|
1365 * without a return value. |
|
1366 * @n_params: the number of parameter types to follow. |
|
1367 * @...: a list of types, one for each parameter. |
|
1368 * |
|
1369 * Creates a new signal. (This is usually done in the class initializer.) |
|
1370 * |
|
1371 * A signal name consists of segments consisting of ASCII letters and |
|
1372 * digits, separated by either the '-' or '_' character. The first |
|
1373 * character of a signal name must be a letter. Names which violate these |
|
1374 * rules lead to undefined behaviour of the GSignal system. |
|
1375 * |
|
1376 * When registering a signal and looking up a signal, either separator can |
|
1377 * be used, but they cannot be mixed. |
|
1378 * |
|
1379 * Returns: the signal id |
|
1380 */ |
|
1381 EXPORT_C guint |
|
1382 g_signal_new (const gchar *signal_name, |
|
1383 GType itype, |
|
1384 GSignalFlags signal_flags, |
|
1385 guint class_offset, |
|
1386 GSignalAccumulator accumulator, |
|
1387 gpointer accu_data, |
|
1388 GSignalCMarshaller c_marshaller, |
|
1389 GType return_type, |
|
1390 guint n_params, |
|
1391 ...) |
|
1392 { |
|
1393 va_list args; |
|
1394 guint signal_id; |
|
1395 |
|
1396 g_return_val_if_fail (signal_name != NULL, 0); |
|
1397 |
|
1398 va_start (args, n_params); |
|
1399 |
|
1400 signal_id = g_signal_new_valist (signal_name, itype, signal_flags, |
|
1401 class_offset ? g_signal_type_cclosure_new (itype, class_offset) : NULL, |
|
1402 accumulator, accu_data, c_marshaller, |
|
1403 return_type, n_params, args); |
|
1404 |
|
1405 va_end (args); |
|
1406 |
|
1407 /* optimize NOP emissions with NULL class handlers */ |
|
1408 if (signal_id && G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE && |
|
1409 class_offset && class_offset < MAX_TEST_CLASS_OFFSET) |
|
1410 { |
|
1411 SignalNode *node; |
|
1412 |
|
1413 SIGNAL_LOCK (); |
|
1414 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
1415 node->test_class_offset = class_offset; |
|
1416 SIGNAL_UNLOCK (); |
|
1417 } |
|
1418 |
|
1419 return signal_id; |
|
1420 } |
|
1421 |
|
1422 /** |
|
1423 * g_signal_new_class_handler: |
|
1424 * @signal_name: the name for the signal |
|
1425 * @itype: the type this signal pertains to. It will also pertain to |
|
1426 * types which are derived from this type. |
|
1427 * @signal_flags: a combination of #GSignalFlags specifying detail of when |
|
1428 * the default handler is to be invoked. You should at least specify |
|
1429 * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST. |
|
1430 * @class_handler: a #GCallback which acts as class implementation of |
|
1431 * this signal. Used to invoke a class method generically. Pass %NULL to |
|
1432 * not associate a class method with this signal. |
|
1433 * @accumulator: the accumulator for this signal; may be %NULL. |
|
1434 * @accu_data: user data for the @accumulator. |
|
1435 * @c_marshaller: the function to translate arrays of parameter values to |
|
1436 * signal emissions into C language callback invocations. |
|
1437 * @return_type: the type of return value, or #G_TYPE_NONE for a signal |
|
1438 * without a return value. |
|
1439 * @n_params: the number of parameter types to follow. |
|
1440 * @...: a list of types, one for each parameter. |
|
1441 * |
|
1442 * Creates a new signal. (This is usually done in the class initializer.) |
|
1443 * |
|
1444 * This is a variant of g_signal_new() that takes a C callback instead |
|
1445 * off a class offset for the signal's class handler. This function |
|
1446 * doesn't need a function pointer exposed in the class structure of |
|
1447 * an object definition, instead the function pointer is passed |
|
1448 * directly and can be overriden by derived classes with |
|
1449 * g_signal_override_class_closure() or |
|
1450 * g_signal_override_class_handler()and chained to with |
|
1451 * g_signal_chain_from_overridden() or |
|
1452 * g_signal_chain_from_overridden_handler(). |
|
1453 * |
|
1454 * See g_signal_new() for information about signal names. |
|
1455 * |
|
1456 * Returns: the signal id |
|
1457 * |
|
1458 * Since: 2.18 |
|
1459 */ |
|
1460 EXPORT_C guint |
|
1461 g_signal_new_class_handler (const gchar *signal_name, |
|
1462 GType itype, |
|
1463 GSignalFlags signal_flags, |
|
1464 GCallback class_handler, |
|
1465 GSignalAccumulator accumulator, |
|
1466 gpointer accu_data, |
|
1467 GSignalCMarshaller c_marshaller, |
|
1468 GType return_type, |
|
1469 guint n_params, |
|
1470 ...) |
|
1471 { |
|
1472 va_list args; |
|
1473 guint signal_id; |
|
1474 |
|
1475 g_return_val_if_fail (signal_name != NULL, 0); |
|
1476 |
|
1477 va_start (args, n_params); |
|
1478 |
|
1479 signal_id = g_signal_new_valist (signal_name, itype, signal_flags, |
|
1480 class_handler ? g_cclosure_new (class_handler, NULL, NULL) : NULL, |
|
1481 accumulator, accu_data, c_marshaller, |
|
1482 return_type, n_params, args); |
|
1483 |
|
1484 va_end (args); |
|
1485 |
|
1486 return signal_id; |
|
1487 } |
|
1488 |
|
1489 static inline ClassClosure* |
|
1490 signal_find_class_closure (SignalNode *node, |
|
1491 GType itype) |
|
1492 { |
|
1493 GBSearchArray *bsa = node->class_closure_bsa; |
|
1494 ClassClosure *cc; |
|
1495 |
|
1496 if (bsa) |
|
1497 { |
|
1498 ClassClosure key; |
|
1499 |
|
1500 /* cc->instance_type is 0 for default closure */ |
|
1501 |
|
1502 key.instance_type = itype; |
|
1503 cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key); |
|
1504 while (!cc && key.instance_type) |
|
1505 { |
|
1506 key.instance_type = g_type_parent (key.instance_type); |
|
1507 cc = g_bsearch_array_lookup (bsa, &g_class_closure_bconfig, &key); |
|
1508 } |
|
1509 } |
|
1510 else |
|
1511 cc = NULL; |
|
1512 return cc; |
|
1513 } |
|
1514 |
|
1515 static inline GClosure* |
|
1516 signal_lookup_closure (SignalNode *node, |
|
1517 GTypeInstance *instance) |
|
1518 { |
|
1519 ClassClosure *cc; |
|
1520 |
|
1521 if (node->class_closure_bsa && g_bsearch_array_get_n_nodes (node->class_closure_bsa) == 1) |
|
1522 { |
|
1523 cc = g_bsearch_array_get_nth (node->class_closure_bsa, &g_class_closure_bconfig, 0); |
|
1524 if (cc && cc->instance_type == 0) /* check for default closure */ |
|
1525 return cc->closure; |
|
1526 } |
|
1527 cc = signal_find_class_closure (node, G_TYPE_FROM_INSTANCE (instance)); |
|
1528 return cc ? cc->closure : NULL; |
|
1529 } |
|
1530 |
|
1531 static void |
|
1532 signal_add_class_closure (SignalNode *node, |
|
1533 GType itype, |
|
1534 GClosure *closure) |
|
1535 { |
|
1536 ClassClosure key; |
|
1537 |
|
1538 /* can't optimize NOP emissions with overridden class closures */ |
|
1539 node->test_class_offset = 0; |
|
1540 |
|
1541 if (!node->class_closure_bsa) |
|
1542 node->class_closure_bsa = g_bsearch_array_create (&g_class_closure_bconfig); |
|
1543 key.instance_type = itype; |
|
1544 key.closure = g_closure_ref (closure); |
|
1545 node->class_closure_bsa = g_bsearch_array_insert (node->class_closure_bsa, |
|
1546 &g_class_closure_bconfig, |
|
1547 &key); |
|
1548 g_closure_sink (closure); |
|
1549 if (node->c_marshaller && closure && G_CLOSURE_NEEDS_MARSHAL (closure)) |
|
1550 g_closure_set_marshal (closure, node->c_marshaller); |
|
1551 } |
|
1552 |
|
1553 /** |
|
1554 * g_signal_newv: |
|
1555 * @signal_name: the name for the signal |
|
1556 * @itype: the type this signal pertains to. It will also pertain to |
|
1557 * types which are derived from this type |
|
1558 * @signal_flags: a combination of #GSignalFlags specifying detail of when |
|
1559 * the default handler is to be invoked. You should at least specify |
|
1560 * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST |
|
1561 * @class_closure: The closure to invoke on signal emission; may be %NULL |
|
1562 * @accumulator: the accumulator for this signal; may be %NULL |
|
1563 * @accu_data: user data for the @accumulator |
|
1564 * @c_marshaller: the function to translate arrays of parameter values to |
|
1565 * signal emissions into C language callback invocations |
|
1566 * @return_type: the type of return value, or #G_TYPE_NONE for a signal |
|
1567 * without a return value |
|
1568 * @n_params: the length of @param_types |
|
1569 * @param_types: an array of types, one for each parameter |
|
1570 * |
|
1571 * Creates a new signal. (This is usually done in the class initializer.) |
|
1572 * |
|
1573 * See g_signal_new() for details on allowed signal names. |
|
1574 * |
|
1575 * Returns: the signal id |
|
1576 */ |
|
1577 EXPORT_C guint |
|
1578 g_signal_newv (const gchar *signal_name, |
|
1579 GType itype, |
|
1580 GSignalFlags signal_flags, |
|
1581 GClosure *class_closure, |
|
1582 GSignalAccumulator accumulator, |
|
1583 gpointer accu_data, |
|
1584 GSignalCMarshaller c_marshaller, |
|
1585 GType return_type, |
|
1586 guint n_params, |
|
1587 GType *param_types) |
|
1588 { |
|
1589 gchar *name; |
|
1590 guint signal_id, i; |
|
1591 SignalNode *node; |
|
1592 |
|
1593 g_return_val_if_fail (signal_name != NULL, 0); |
|
1594 g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (itype) || G_TYPE_IS_INTERFACE (itype), 0); |
|
1595 if (n_params) |
|
1596 g_return_val_if_fail (param_types != NULL, 0); |
|
1597 g_return_val_if_fail ((return_type & G_SIGNAL_TYPE_STATIC_SCOPE) == 0, 0); |
|
1598 if (return_type == (G_TYPE_NONE & ~G_SIGNAL_TYPE_STATIC_SCOPE)) |
|
1599 g_return_val_if_fail (accumulator == NULL, 0); |
|
1600 if (!accumulator) |
|
1601 g_return_val_if_fail (accu_data == NULL, 0); |
|
1602 |
|
1603 name = g_strdup (signal_name); |
|
1604 g_strdelimit (name, G_STR_DELIMITERS ":^", '_'); /* FIXME do character checks like for types */ |
|
1605 |
|
1606 SIGNAL_LOCK (); |
|
1607 |
|
1608 signal_id = signal_id_lookup (g_quark_try_string (name), itype); |
|
1609 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
1610 if (node && !node->destroyed) |
|
1611 { |
|
1612 g_warning (G_STRLOC ": signal \"%s\" already exists in the `%s' %s", |
|
1613 name, |
|
1614 type_debug_name (node->itype), |
|
1615 G_TYPE_IS_INTERFACE (node->itype) ? "interface" : "class ancestry"); |
|
1616 g_free (name); |
|
1617 SIGNAL_UNLOCK (); |
|
1618 return 0; |
|
1619 } |
|
1620 if (node && node->itype != itype) |
|
1621 { |
|
1622 g_warning (G_STRLOC ": signal \"%s\" for type `%s' was previously created for type `%s'", |
|
1623 name, |
|
1624 type_debug_name (itype), |
|
1625 type_debug_name (node->itype)); |
|
1626 g_free (name); |
|
1627 SIGNAL_UNLOCK (); |
|
1628 return 0; |
|
1629 } |
|
1630 for (i = 0; i < n_params; i++) |
|
1631 if (!G_TYPE_IS_VALUE (param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) |
|
1632 { |
|
1633 g_warning (G_STRLOC ": parameter %d of type `%s' for signal \"%s::%s\" is not a value type", |
|
1634 i + 1, type_debug_name (param_types[i]), type_debug_name (itype), name); |
|
1635 g_free (name); |
|
1636 SIGNAL_UNLOCK (); |
|
1637 return 0; |
|
1638 } |
|
1639 if (return_type != G_TYPE_NONE && !G_TYPE_IS_VALUE (return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) |
|
1640 { |
|
1641 g_warning (G_STRLOC ": return value of type `%s' for signal \"%s::%s\" is not a value type", |
|
1642 type_debug_name (return_type), type_debug_name (itype), name); |
|
1643 g_free (name); |
|
1644 SIGNAL_UNLOCK (); |
|
1645 return 0; |
|
1646 } |
|
1647 if (return_type != G_TYPE_NONE && |
|
1648 (signal_flags & (G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP)) == G_SIGNAL_RUN_FIRST) |
|
1649 { |
|
1650 g_warning (G_STRLOC ": signal \"%s::%s\" has return type `%s' and is only G_SIGNAL_RUN_FIRST", |
|
1651 type_debug_name (itype), name, type_debug_name (return_type)); |
|
1652 g_free (name); |
|
1653 SIGNAL_UNLOCK (); |
|
1654 return 0; |
|
1655 } |
|
1656 |
|
1657 /* setup permanent portion of signal node */ |
|
1658 if (!node) |
|
1659 { |
|
1660 SignalKey key; |
|
1661 |
|
1662 signal_id = g_n_signal_nodes++; |
|
1663 node = g_new (SignalNode, 1); |
|
1664 node->signal_id = signal_id; |
|
1665 g_signal_nodes = g_renew (SignalNode*, g_signal_nodes, g_n_signal_nodes); |
|
1666 g_signal_nodes[signal_id] = node; |
|
1667 node->itype = itype; |
|
1668 node->name = name; |
|
1669 key.itype = itype; |
|
1670 key.quark = g_quark_from_string (node->name); |
|
1671 key.signal_id = signal_id; |
|
1672 g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key); |
|
1673 g_strdelimit (name, "_", '-'); |
|
1674 node->name = g_intern_string (name); |
|
1675 key.quark = g_quark_from_string (name); |
|
1676 g_signal_key_bsa = g_bsearch_array_insert (g_signal_key_bsa, &g_signal_key_bconfig, &key); |
|
1677 } |
|
1678 node->destroyed = FALSE; |
|
1679 node->test_class_offset = 0; |
|
1680 |
|
1681 /* setup reinitializable portion */ |
|
1682 node->flags = signal_flags & G_SIGNAL_FLAGS_MASK; |
|
1683 node->n_params = n_params; |
|
1684 node->param_types = g_memdup (param_types, sizeof (GType) * n_params); |
|
1685 node->return_type = return_type; |
|
1686 node->class_closure_bsa = NULL; |
|
1687 if (accumulator) |
|
1688 { |
|
1689 node->accumulator = g_new (SignalAccumulator, 1); |
|
1690 node->accumulator->func = accumulator; |
|
1691 node->accumulator->data = accu_data; |
|
1692 } |
|
1693 else |
|
1694 node->accumulator = NULL; |
|
1695 node->c_marshaller = c_marshaller; |
|
1696 node->emission_hooks = NULL; |
|
1697 if (class_closure) |
|
1698 signal_add_class_closure (node, 0, class_closure); |
|
1699 else if (G_TYPE_IS_INSTANTIATABLE (itype) && return_type == G_TYPE_NONE) |
|
1700 { |
|
1701 /* optimize NOP emissions */ |
|
1702 node->test_class_offset = TEST_CLASS_MAGIC; |
|
1703 } |
|
1704 SIGNAL_UNLOCK (); |
|
1705 |
|
1706 g_free (name); |
|
1707 |
|
1708 return signal_id; |
|
1709 } |
|
1710 |
|
1711 /** |
|
1712 * g_signal_new_valist: |
|
1713 * @signal_name: the name for the signal |
|
1714 * @itype: the type this signal pertains to. It will also pertain to |
|
1715 * types which are derived from this type. |
|
1716 * @signal_flags: a combination of #GSignalFlags specifying detail of when |
|
1717 * the default handler is to be invoked. You should at least specify |
|
1718 * %G_SIGNAL_RUN_FIRST or %G_SIGNAL_RUN_LAST. |
|
1719 * @class_closure: The closure to invoke on signal emission; may be %NULL. |
|
1720 * @accumulator: the accumulator for this signal; may be %NULL. |
|
1721 * @accu_data: user data for the @accumulator. |
|
1722 * @c_marshaller: the function to translate arrays of parameter values to |
|
1723 * signal emissions into C language callback invocations. |
|
1724 * @return_type: the type of return value, or #G_TYPE_NONE for a signal |
|
1725 * without a return value. |
|
1726 * @n_params: the number of parameter types in @args. |
|
1727 * @args: va_list of #GType, one for each parameter. |
|
1728 * |
|
1729 * Creates a new signal. (This is usually done in the class initializer.) |
|
1730 * |
|
1731 * See g_signal_new() for details on allowed signal names. |
|
1732 * |
|
1733 * Returns: the signal id |
|
1734 */ |
|
1735 EXPORT_C guint |
|
1736 g_signal_new_valist (const gchar *signal_name, |
|
1737 GType itype, |
|
1738 GSignalFlags signal_flags, |
|
1739 GClosure *class_closure, |
|
1740 GSignalAccumulator accumulator, |
|
1741 gpointer accu_data, |
|
1742 GSignalCMarshaller c_marshaller, |
|
1743 GType return_type, |
|
1744 guint n_params, |
|
1745 va_list args) |
|
1746 { |
|
1747 GType *param_types; |
|
1748 guint i; |
|
1749 guint signal_id; |
|
1750 |
|
1751 if (n_params > 0) |
|
1752 { |
|
1753 param_types = g_new (GType, n_params); |
|
1754 |
|
1755 for (i = 0; i < n_params; i++) |
|
1756 param_types[i] = va_arg (args, GType); |
|
1757 } |
|
1758 else |
|
1759 param_types = NULL; |
|
1760 |
|
1761 signal_id = g_signal_newv (signal_name, itype, signal_flags, |
|
1762 class_closure, accumulator, accu_data, c_marshaller, |
|
1763 return_type, n_params, param_types); |
|
1764 g_free (param_types); |
|
1765 |
|
1766 return signal_id; |
|
1767 } |
|
1768 |
|
1769 static void |
|
1770 signal_destroy_R (SignalNode *signal_node) |
|
1771 { |
|
1772 SignalNode node = *signal_node; |
|
1773 |
|
1774 signal_node->destroyed = TRUE; |
|
1775 |
|
1776 /* reentrancy caution, zero out real contents first */ |
|
1777 signal_node->test_class_offset = 0; |
|
1778 signal_node->n_params = 0; |
|
1779 signal_node->param_types = NULL; |
|
1780 signal_node->return_type = 0; |
|
1781 signal_node->class_closure_bsa = NULL; |
|
1782 signal_node->accumulator = NULL; |
|
1783 signal_node->c_marshaller = NULL; |
|
1784 signal_node->emission_hooks = NULL; |
|
1785 |
|
1786 #ifdef G_ENABLE_DEBUG |
|
1787 /* check current emissions */ |
|
1788 { |
|
1789 Emission *emission; |
|
1790 |
|
1791 for (emission = (node.flags & G_SIGNAL_NO_RECURSE) ? g_restart_emissions : g_recursive_emissions; |
|
1792 emission; emission = emission->next) |
|
1793 if (emission->ihint.signal_id == node.signal_id) |
|
1794 g_critical (G_STRLOC ": signal \"%s\" being destroyed is currently in emission (instance `%p')", |
|
1795 node.name, emission->instance); |
|
1796 } |
|
1797 #endif |
|
1798 |
|
1799 /* free contents that need to |
|
1800 */ |
|
1801 SIGNAL_UNLOCK (); |
|
1802 g_free (node.param_types); |
|
1803 if (node.class_closure_bsa) |
|
1804 { |
|
1805 guint i; |
|
1806 |
|
1807 for (i = 0; i < node.class_closure_bsa->n_nodes; i++) |
|
1808 { |
|
1809 ClassClosure *cc = g_bsearch_array_get_nth (node.class_closure_bsa, &g_class_closure_bconfig, i); |
|
1810 |
|
1811 g_closure_unref (cc->closure); |
|
1812 } |
|
1813 g_bsearch_array_free (node.class_closure_bsa, &g_class_closure_bconfig); |
|
1814 } |
|
1815 g_free (node.accumulator); |
|
1816 if (node.emission_hooks) |
|
1817 { |
|
1818 g_hook_list_clear (node.emission_hooks); |
|
1819 g_free (node.emission_hooks); |
|
1820 } |
|
1821 SIGNAL_LOCK (); |
|
1822 } |
|
1823 |
|
1824 /** |
|
1825 * g_signal_override_class_closure: |
|
1826 * @signal_id: the signal id |
|
1827 * @instance_type: the instance type on which to override the class closure |
|
1828 * for the signal. |
|
1829 * @class_closure: the closure. |
|
1830 * |
|
1831 * Overrides the class closure (i.e. the default handler) for the given signal |
|
1832 * for emissions on instances of @instance_type. @instance_type must be derived |
|
1833 * from the type to which the signal belongs. |
|
1834 * |
|
1835 * See g_signal_chain_from_overridden() and |
|
1836 * g_signal_chain_from_overridden_handler() for how to chain up to the |
|
1837 * parent class closure from inside the overridden one. |
|
1838 */ |
|
1839 EXPORT_C void |
|
1840 g_signal_override_class_closure (guint signal_id, |
|
1841 GType instance_type, |
|
1842 GClosure *class_closure) |
|
1843 { |
|
1844 SignalNode *node; |
|
1845 |
|
1846 g_return_if_fail (signal_id > 0); |
|
1847 g_return_if_fail (class_closure != NULL); |
|
1848 |
|
1849 SIGNAL_LOCK (); |
|
1850 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
1851 if (!g_type_is_a (instance_type, node->itype)) |
|
1852 g_warning ("%s: type `%s' cannot be overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id); |
|
1853 else |
|
1854 { |
|
1855 ClassClosure *cc = signal_find_class_closure (node, instance_type); |
|
1856 |
|
1857 if (cc && cc->instance_type == instance_type) |
|
1858 g_warning ("%s: type `%s' is already overridden for signal id `%u'", G_STRLOC, type_debug_name (instance_type), signal_id); |
|
1859 else |
|
1860 signal_add_class_closure (node, instance_type, class_closure); |
|
1861 } |
|
1862 SIGNAL_UNLOCK (); |
|
1863 } |
|
1864 |
|
1865 /** |
|
1866 * g_signal_override_class_handler: |
|
1867 * @signal_name: the name for the signal |
|
1868 * @instance_type: the instance type on which to override the class handler |
|
1869 * for the signal. |
|
1870 * @class_handler: the handler. |
|
1871 * |
|
1872 * Overrides the class closure (i.e. the default handler) for the |
|
1873 * given signal for emissions on instances of @instance_type with |
|
1874 * callabck @class_handler. @instance_type must be derived from the |
|
1875 * type to which the signal belongs. |
|
1876 * |
|
1877 * See g_signal_chain_from_overridden() and |
|
1878 * g_signal_chain_from_overridden_handler() for how to chain up to the |
|
1879 * parent class closure from inside the overridden one. |
|
1880 * |
|
1881 * Since: 2.18 |
|
1882 */ |
|
1883 EXPORT_C void |
|
1884 g_signal_override_class_handler (const gchar *signal_name, |
|
1885 GType instance_type, |
|
1886 GCallback class_handler) |
|
1887 { |
|
1888 guint signal_id; |
|
1889 |
|
1890 g_return_if_fail (signal_name != NULL); |
|
1891 g_return_if_fail (instance_type != G_TYPE_NONE); |
|
1892 g_return_if_fail (class_handler != NULL); |
|
1893 |
|
1894 signal_id = g_signal_lookup (signal_name, instance_type); |
|
1895 |
|
1896 if (signal_id) |
|
1897 g_signal_override_class_closure (signal_id, instance_type, |
|
1898 g_cclosure_new (class_handler, NULL, NULL)); |
|
1899 else |
|
1900 g_warning ("%s: signal name '%s' is invalid for type id '%"G_GSIZE_FORMAT"'", |
|
1901 G_STRLOC, signal_name, instance_type); |
|
1902 |
|
1903 } |
|
1904 |
|
1905 /** |
|
1906 * g_signal_chain_from_overridden: |
|
1907 * @instance_and_params: the argument list of the signal emission. The first |
|
1908 * element in the array is a #GValue for the instance the signal is being |
|
1909 * emitted on. The rest are any arguments to be passed to the signal. |
|
1910 * @return_value: Location for the return value. |
|
1911 * |
|
1912 * Calls the original class closure of a signal. This function should only |
|
1913 * be called from an overridden class closure; see |
|
1914 * g_signal_override_class_closure() and |
|
1915 * g_signal_override_class_handler(). |
|
1916 */ |
|
1917 EXPORT_C void |
|
1918 g_signal_chain_from_overridden (const GValue *instance_and_params, |
|
1919 GValue *return_value) |
|
1920 { |
|
1921 GType chain_type = 0, restore_type = 0; |
|
1922 Emission *emission = NULL; |
|
1923 GClosure *closure = NULL; |
|
1924 guint n_params = 0; |
|
1925 gpointer instance; |
|
1926 |
|
1927 g_return_if_fail (instance_and_params != NULL); |
|
1928 instance = g_value_peek_pointer (instance_and_params); |
|
1929 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
1930 |
|
1931 SIGNAL_LOCK (); |
|
1932 emission = emission_find_innermost (instance); |
|
1933 if (emission) |
|
1934 { |
|
1935 SignalNode *node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id); |
|
1936 |
|
1937 g_assert (node != NULL); /* paranoid */ |
|
1938 |
|
1939 /* we should probably do the same parameter checks as g_signal_emit() here. |
|
1940 */ |
|
1941 if (emission->chain_type != G_TYPE_NONE) |
|
1942 { |
|
1943 ClassClosure *cc = signal_find_class_closure (node, emission->chain_type); |
|
1944 |
|
1945 g_assert (cc != NULL); /* closure currently in call stack */ |
|
1946 |
|
1947 n_params = node->n_params; |
|
1948 restore_type = cc->instance_type; |
|
1949 cc = signal_find_class_closure (node, g_type_parent (cc->instance_type)); |
|
1950 if (cc && cc->instance_type != restore_type) |
|
1951 { |
|
1952 closure = cc->closure; |
|
1953 chain_type = cc->instance_type; |
|
1954 } |
|
1955 } |
|
1956 else |
|
1957 g_warning ("%s: signal id `%u' cannot be chained from current emission stage for instance `%p'", G_STRLOC, node->signal_id, instance); |
|
1958 } |
|
1959 else |
|
1960 g_warning ("%s: no signal is currently being emitted for instance `%p'", G_STRLOC, instance); |
|
1961 |
|
1962 if (closure) |
|
1963 { |
|
1964 emission->chain_type = chain_type; |
|
1965 SIGNAL_UNLOCK (); |
|
1966 g_closure_invoke (closure, |
|
1967 return_value, |
|
1968 n_params + 1, |
|
1969 instance_and_params, |
|
1970 &emission->ihint); |
|
1971 SIGNAL_LOCK (); |
|
1972 emission->chain_type = restore_type; |
|
1973 } |
|
1974 SIGNAL_UNLOCK (); |
|
1975 } |
|
1976 |
|
1977 /** |
|
1978 * g_signal_chain_from_overridden_handler: |
|
1979 * @instance: the instance the signal is being emitted on. |
|
1980 * @...: parameters to be passed to the parent class closure, followed by a |
|
1981 * location for the return value. If the return type of the signal |
|
1982 * is #G_TYPE_NONE, the return value location can be omitted. |
|
1983 * |
|
1984 * Calls the original class closure of a signal. This function should |
|
1985 * only be called from an overridden class closure; see |
|
1986 * g_signal_override_class_closure() and |
|
1987 * g_signal_override_class_handler(). |
|
1988 * |
|
1989 * Since: 2.18 |
|
1990 */ |
|
1991 EXPORT_C void |
|
1992 g_signal_chain_from_overridden_handler (gpointer instance, |
|
1993 ...) |
|
1994 { |
|
1995 GType chain_type = 0, restore_type = 0; |
|
1996 Emission *emission = NULL; |
|
1997 GClosure *closure = NULL; |
|
1998 SignalNode *node; |
|
1999 guint n_params = 0; |
|
2000 |
|
2001 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
2002 |
|
2003 SIGNAL_LOCK (); |
|
2004 emission = emission_find_innermost (instance); |
|
2005 if (emission) |
|
2006 { |
|
2007 node = LOOKUP_SIGNAL_NODE (emission->ihint.signal_id); |
|
2008 |
|
2009 g_assert (node != NULL); /* paranoid */ |
|
2010 |
|
2011 /* we should probably do the same parameter checks as g_signal_emit() here. |
|
2012 */ |
|
2013 if (emission->chain_type != G_TYPE_NONE) |
|
2014 { |
|
2015 ClassClosure *cc = signal_find_class_closure (node, emission->chain_type); |
|
2016 |
|
2017 g_assert (cc != NULL); /* closure currently in call stack */ |
|
2018 |
|
2019 n_params = node->n_params; |
|
2020 restore_type = cc->instance_type; |
|
2021 cc = signal_find_class_closure (node, g_type_parent (cc->instance_type)); |
|
2022 if (cc && cc->instance_type != restore_type) |
|
2023 { |
|
2024 closure = cc->closure; |
|
2025 chain_type = cc->instance_type; |
|
2026 } |
|
2027 } |
|
2028 else |
|
2029 g_warning ("%s: signal id `%u' cannot be chained from current emission stage for instance `%p'", G_STRLOC, node->signal_id, instance); |
|
2030 } |
|
2031 else |
|
2032 g_warning ("%s: no signal is currently being emitted for instance `%p'", G_STRLOC, instance); |
|
2033 |
|
2034 if (closure) |
|
2035 { |
|
2036 GValue *instance_and_params; |
|
2037 GType signal_return_type; |
|
2038 GValue *param_values; |
|
2039 va_list var_args; |
|
2040 guint i; |
|
2041 |
|
2042 va_start (var_args, instance); |
|
2043 |
|
2044 signal_return_type = node->return_type; |
|
2045 instance_and_params = g_slice_alloc (sizeof (GValue) * (n_params + 1)); |
|
2046 param_values = instance_and_params + 1; |
|
2047 |
|
2048 for (i = 0; i < node->n_params; i++) |
|
2049 { |
|
2050 gchar *error; |
|
2051 GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE; |
|
2052 gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE; |
|
2053 |
|
2054 param_values[i].g_type = 0; |
|
2055 SIGNAL_UNLOCK (); |
|
2056 g_value_init (param_values + i, ptype); |
|
2057 G_VALUE_COLLECT (param_values + i, |
|
2058 var_args, |
|
2059 static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, |
|
2060 &error); |
|
2061 if (error) |
|
2062 { |
|
2063 g_warning ("%s: %s", G_STRLOC, error); |
|
2064 g_free (error); |
|
2065 |
|
2066 /* we purposely leak the value here, it might not be |
|
2067 * in a sane state if an error condition occoured |
|
2068 */ |
|
2069 while (i--) |
|
2070 g_value_unset (param_values + i); |
|
2071 |
|
2072 g_slice_free1 (sizeof (GValue) * (n_params + 1), instance_and_params); |
|
2073 va_end (var_args); |
|
2074 return; |
|
2075 } |
|
2076 SIGNAL_LOCK (); |
|
2077 } |
|
2078 |
|
2079 SIGNAL_UNLOCK (); |
|
2080 instance_and_params->g_type = 0; |
|
2081 g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance)); |
|
2082 g_value_set_instance (instance_and_params, instance); |
|
2083 SIGNAL_LOCK (); |
|
2084 |
|
2085 emission->chain_type = chain_type; |
|
2086 SIGNAL_UNLOCK (); |
|
2087 |
|
2088 if (signal_return_type == G_TYPE_NONE) |
|
2089 { |
|
2090 g_closure_invoke (closure, |
|
2091 NULL, |
|
2092 n_params + 1, |
|
2093 instance_and_params, |
|
2094 &emission->ihint); |
|
2095 } |
|
2096 else |
|
2097 { |
|
2098 GValue return_value = { 0, }; |
|
2099 gchar *error = NULL; |
|
2100 GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE; |
|
2101 gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE; |
|
2102 |
|
2103 g_value_init (&return_value, rtype); |
|
2104 |
|
2105 g_closure_invoke (closure, |
|
2106 &return_value, |
|
2107 n_params + 1, |
|
2108 instance_and_params, |
|
2109 &emission->ihint); |
|
2110 |
|
2111 G_VALUE_LCOPY (&return_value, |
|
2112 var_args, |
|
2113 static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, |
|
2114 &error); |
|
2115 if (!error) |
|
2116 { |
|
2117 g_value_unset (&return_value); |
|
2118 } |
|
2119 else |
|
2120 { |
|
2121 g_warning ("%s: %s", G_STRLOC, error); |
|
2122 g_free (error); |
|
2123 |
|
2124 /* we purposely leak the value here, it might not be |
|
2125 * in a sane state if an error condition occured |
|
2126 */ |
|
2127 } |
|
2128 } |
|
2129 |
|
2130 for (i = 0; i < n_params; i++) |
|
2131 g_value_unset (param_values + i); |
|
2132 g_value_unset (instance_and_params); |
|
2133 g_slice_free1 (sizeof (GValue) * (n_params + 1), instance_and_params); |
|
2134 |
|
2135 va_end (var_args); |
|
2136 |
|
2137 SIGNAL_LOCK (); |
|
2138 emission->chain_type = restore_type; |
|
2139 } |
|
2140 SIGNAL_UNLOCK (); |
|
2141 } |
|
2142 |
|
2143 /** |
|
2144 * g_signal_get_invocation_hint: |
|
2145 * @instance: the instance to query |
|
2146 * |
|
2147 * Returns the invocation hint of the innermost signal emission of instance. |
|
2148 * |
|
2149 * Returns: the invocation hint of the innermost signal emission. |
|
2150 */ |
|
2151 EXPORT_C GSignalInvocationHint* |
|
2152 g_signal_get_invocation_hint (gpointer instance) |
|
2153 { |
|
2154 Emission *emission = NULL; |
|
2155 |
|
2156 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), NULL); |
|
2157 |
|
2158 SIGNAL_LOCK (); |
|
2159 emission = emission_find_innermost (instance); |
|
2160 SIGNAL_UNLOCK (); |
|
2161 |
|
2162 return emission ? &emission->ihint : NULL; |
|
2163 } |
|
2164 |
|
2165 /** |
|
2166 * g_signal_connect_closure_by_id: |
|
2167 * @instance: the instance to connect to. |
|
2168 * @signal_id: the id of the signal. |
|
2169 * @detail: the detail. |
|
2170 * @closure: the closure to connect. |
|
2171 * @after: whether the handler should be called before or after the |
|
2172 * default handler of the signal. |
|
2173 * |
|
2174 * Connects a closure to a signal for a particular object. |
|
2175 * |
|
2176 * Returns: the handler id |
|
2177 */ |
|
2178 EXPORT_C gulong |
|
2179 g_signal_connect_closure_by_id (gpointer instance, |
|
2180 guint signal_id, |
|
2181 GQuark detail, |
|
2182 GClosure *closure, |
|
2183 gboolean after) |
|
2184 { |
|
2185 SignalNode *node; |
|
2186 gulong handler_seq_no = 0; |
|
2187 |
|
2188 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); |
|
2189 g_return_val_if_fail (signal_id > 0, 0); |
|
2190 g_return_val_if_fail (closure != NULL, 0); |
|
2191 |
|
2192 SIGNAL_LOCK (); |
|
2193 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
2194 if (node) |
|
2195 { |
|
2196 if (detail && !(node->flags & G_SIGNAL_DETAILED)) |
|
2197 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); |
|
2198 else if (!g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) |
|
2199 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); |
|
2200 else |
|
2201 { |
|
2202 Handler *handler = handler_new (after); |
|
2203 |
|
2204 handler_seq_no = handler->sequential_number; |
|
2205 handler->detail = detail; |
|
2206 handler->closure = g_closure_ref (closure); |
|
2207 g_closure_sink (closure); |
|
2208 handler_insert (signal_id, instance, handler); |
|
2209 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (closure)) |
|
2210 g_closure_set_marshal (closure, node->c_marshaller); |
|
2211 } |
|
2212 } |
|
2213 else |
|
2214 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); |
|
2215 SIGNAL_UNLOCK (); |
|
2216 |
|
2217 return handler_seq_no; |
|
2218 } |
|
2219 |
|
2220 /** |
|
2221 * g_signal_connect_closure: |
|
2222 * @instance: the instance to connect to. |
|
2223 * @detailed_signal: a string of the form "signal-name::detail". |
|
2224 * @closure: the closure to connect. |
|
2225 * @after: whether the handler should be called before or after the |
|
2226 * default handler of the signal. |
|
2227 * |
|
2228 * Connects a closure to a signal for a particular object. |
|
2229 * |
|
2230 * Returns: the handler id |
|
2231 */ |
|
2232 EXPORT_C gulong |
|
2233 g_signal_connect_closure (gpointer instance, |
|
2234 const gchar *detailed_signal, |
|
2235 GClosure *closure, |
|
2236 gboolean after) |
|
2237 { |
|
2238 guint signal_id; |
|
2239 gulong handler_seq_no = 0; |
|
2240 GQuark detail = 0; |
|
2241 GType itype; |
|
2242 |
|
2243 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); |
|
2244 g_return_val_if_fail (detailed_signal != NULL, 0); |
|
2245 g_return_val_if_fail (closure != NULL, 0); |
|
2246 |
|
2247 SIGNAL_LOCK (); |
|
2248 itype = G_TYPE_FROM_INSTANCE (instance); |
|
2249 signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); |
|
2250 if (signal_id) |
|
2251 { |
|
2252 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); |
|
2253 |
|
2254 if (detail && !(node->flags & G_SIGNAL_DETAILED)) |
|
2255 g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); |
|
2256 else if (!g_type_is_a (itype, node->itype)) |
|
2257 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); |
|
2258 else |
|
2259 { |
|
2260 Handler *handler = handler_new (after); |
|
2261 |
|
2262 handler_seq_no = handler->sequential_number; |
|
2263 handler->detail = detail; |
|
2264 handler->closure = g_closure_ref (closure); |
|
2265 g_closure_sink (closure); |
|
2266 handler_insert (signal_id, instance, handler); |
|
2267 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) |
|
2268 g_closure_set_marshal (handler->closure, node->c_marshaller); |
|
2269 } |
|
2270 } |
|
2271 else |
|
2272 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); |
|
2273 SIGNAL_UNLOCK (); |
|
2274 |
|
2275 return handler_seq_no; |
|
2276 } |
|
2277 |
|
2278 /** |
|
2279 * g_signal_connect_data: |
|
2280 * @instance: the instance to connect to. |
|
2281 * @detailed_signal: a string of the form "signal-name::detail". |
|
2282 * @c_handler: the #GCallback to connect. |
|
2283 * @data: data to pass to @c_handler calls. |
|
2284 * @destroy_data: a #GClosureNotify for @data. |
|
2285 * @connect_flags: a combination of #GConnectFlags. |
|
2286 * |
|
2287 * Connects a #GCallback function to a signal for a particular object. Similar |
|
2288 * to g_signal_connect(), but allows to provide a #GClosureNotify for the data |
|
2289 * which will be called when the signal handler is disconnected and no longer |
|
2290 * used. Specify @connect_flags if you need <literal>..._after()</literal> or |
|
2291 * <literal>..._swapped()</literal> variants of this function. |
|
2292 * |
|
2293 * Returns: the handler id |
|
2294 */ |
|
2295 EXPORT_C gulong |
|
2296 g_signal_connect_data (gpointer instance, |
|
2297 const gchar *detailed_signal, |
|
2298 GCallback c_handler, |
|
2299 gpointer data, |
|
2300 GClosureNotify destroy_data, |
|
2301 GConnectFlags connect_flags) |
|
2302 { |
|
2303 guint signal_id; |
|
2304 gulong handler_seq_no = 0; |
|
2305 GQuark detail = 0; |
|
2306 GType itype; |
|
2307 gboolean swapped, after; |
|
2308 |
|
2309 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); |
|
2310 g_return_val_if_fail (detailed_signal != NULL, 0); |
|
2311 g_return_val_if_fail (c_handler != NULL, 0); |
|
2312 |
|
2313 swapped = (connect_flags & G_CONNECT_SWAPPED) != FALSE; |
|
2314 after = (connect_flags & G_CONNECT_AFTER) != FALSE; |
|
2315 |
|
2316 SIGNAL_LOCK (); |
|
2317 itype = G_TYPE_FROM_INSTANCE (instance); |
|
2318 signal_id = signal_parse_name (detailed_signal, itype, &detail, TRUE); |
|
2319 if (signal_id) |
|
2320 { |
|
2321 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); |
|
2322 |
|
2323 if (detail && !(node->flags & G_SIGNAL_DETAILED)) |
|
2324 g_warning ("%s: signal `%s' does not support details", G_STRLOC, detailed_signal); |
|
2325 else if (!g_type_is_a (itype, node->itype)) |
|
2326 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); |
|
2327 else |
|
2328 { |
|
2329 Handler *handler = handler_new (after); |
|
2330 |
|
2331 handler_seq_no = handler->sequential_number; |
|
2332 handler->detail = detail; |
|
2333 handler->closure = g_closure_ref ((swapped ? g_cclosure_new_swap : g_cclosure_new) (c_handler, data, destroy_data)); |
|
2334 g_closure_sink (handler->closure); |
|
2335 handler_insert (signal_id, instance, handler); |
|
2336 if (node->c_marshaller && G_CLOSURE_NEEDS_MARSHAL (handler->closure)) |
|
2337 g_closure_set_marshal (handler->closure, node->c_marshaller); |
|
2338 } |
|
2339 } |
|
2340 else |
|
2341 g_warning ("%s: signal `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); |
|
2342 SIGNAL_UNLOCK (); |
|
2343 |
|
2344 return handler_seq_no; |
|
2345 } |
|
2346 |
|
2347 /** |
|
2348 * g_signal_handler_block: |
|
2349 * @instance: The instance to block the signal handler of. |
|
2350 * @handler_id: Handler id of the handler to be blocked. |
|
2351 * |
|
2352 * Blocks a handler of an instance so it will not be called during any |
|
2353 * signal emissions unless it is unblocked again. Thus "blocking" a |
|
2354 * signal handler means to temporarily deactive it, a signal handler |
|
2355 * has to be unblocked exactly the same amount of times it has been |
|
2356 * blocked before to become active again. |
|
2357 * |
|
2358 * The @handler_id has to be a valid signal handler id, connected to a |
|
2359 * signal of @instance. |
|
2360 */ |
|
2361 EXPORT_C void |
|
2362 g_signal_handler_block (gpointer instance, |
|
2363 gulong handler_id) |
|
2364 { |
|
2365 Handler *handler; |
|
2366 |
|
2367 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
2368 g_return_if_fail (handler_id > 0); |
|
2369 |
|
2370 SIGNAL_LOCK (); |
|
2371 handler = handler_lookup (instance, handler_id, NULL); |
|
2372 if (handler) |
|
2373 { |
|
2374 #ifndef G_DISABLE_CHECKS |
|
2375 if (handler->block_count >= HANDLER_MAX_BLOCK_COUNT - 1) |
|
2376 g_error (G_STRLOC ": handler block_count overflow, %s", REPORT_BUG); |
|
2377 #endif |
|
2378 handler->block_count += 1; |
|
2379 } |
|
2380 else |
|
2381 g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); |
|
2382 SIGNAL_UNLOCK (); |
|
2383 } |
|
2384 |
|
2385 /** |
|
2386 * g_signal_handler_unblock: |
|
2387 * @instance: The instance to unblock the signal handler of. |
|
2388 * @handler_id: Handler id of the handler to be unblocked. |
|
2389 * |
|
2390 * Undoes the effect of a previous g_signal_handler_block() call. A |
|
2391 * blocked handler is skipped during signal emissions and will not be |
|
2392 * invoked, unblocking it (for exactly the amount of times it has been |
|
2393 * blocked before) reverts its "blocked" state, so the handler will be |
|
2394 * recognized by the signal system and is called upon future or |
|
2395 * currently ongoing signal emissions (since the order in which |
|
2396 * handlers are called during signal emissions is deterministic, |
|
2397 * whether the unblocked handler in question is called as part of a |
|
2398 * currently ongoing emission depends on how far that emission has |
|
2399 * proceeded yet). |
|
2400 * |
|
2401 * The @handler_id has to be a valid id of a signal handler that is |
|
2402 * connected to a signal of @instance and is currently blocked. |
|
2403 */ |
|
2404 EXPORT_C void |
|
2405 g_signal_handler_unblock (gpointer instance, |
|
2406 gulong handler_id) |
|
2407 { |
|
2408 Handler *handler; |
|
2409 |
|
2410 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
2411 g_return_if_fail (handler_id > 0); |
|
2412 |
|
2413 SIGNAL_LOCK (); |
|
2414 handler = handler_lookup (instance, handler_id, NULL); |
|
2415 if (handler) |
|
2416 { |
|
2417 if (handler->block_count) |
|
2418 handler->block_count -= 1; |
|
2419 else |
|
2420 g_warning (G_STRLOC ": handler `%lu' of instance `%p' is not blocked", handler_id, instance); |
|
2421 } |
|
2422 else |
|
2423 g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); |
|
2424 SIGNAL_UNLOCK (); |
|
2425 } |
|
2426 |
|
2427 /** |
|
2428 * g_signal_handler_disconnect: |
|
2429 * @instance: The instance to remove the signal handler from. |
|
2430 * @handler_id: Handler id of the handler to be disconnected. |
|
2431 * |
|
2432 * Disconnects a handler from an instance so it will not be called during |
|
2433 * any future or currently ongoing emissions of the signal it has been |
|
2434 * connected to. The @handler_id becomes invalid and may be reused. |
|
2435 * |
|
2436 * The @handler_id has to be a valid signal handler id, connected to a |
|
2437 * signal of @instance. |
|
2438 */ |
|
2439 EXPORT_C void |
|
2440 g_signal_handler_disconnect (gpointer instance, |
|
2441 gulong handler_id) |
|
2442 { |
|
2443 Handler *handler; |
|
2444 guint signal_id; |
|
2445 |
|
2446 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
2447 g_return_if_fail (handler_id > 0); |
|
2448 |
|
2449 SIGNAL_LOCK (); |
|
2450 handler = handler_lookup (instance, handler_id, &signal_id); |
|
2451 if (handler) |
|
2452 { |
|
2453 handler->sequential_number = 0; |
|
2454 handler->block_count = 1; |
|
2455 handler_unref_R (signal_id, instance, handler); |
|
2456 } |
|
2457 else |
|
2458 g_warning ("%s: instance `%p' has no handler with id `%lu'", G_STRLOC, instance, handler_id); |
|
2459 SIGNAL_UNLOCK (); |
|
2460 } |
|
2461 |
|
2462 /** |
|
2463 * g_signal_handler_is_connected: |
|
2464 * @instance: The instance where a signal handler is sought. |
|
2465 * @handler_id: the handler id. |
|
2466 * |
|
2467 * Returns whether @handler_id is the id of a handler connected to @instance. |
|
2468 * |
|
2469 * Returns: whether @handler_id identifies a handler connected to @instance. |
|
2470 */ |
|
2471 EXPORT_C gboolean |
|
2472 g_signal_handler_is_connected (gpointer instance, |
|
2473 gulong handler_id) |
|
2474 { |
|
2475 Handler *handler; |
|
2476 gboolean connected; |
|
2477 |
|
2478 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); |
|
2479 |
|
2480 SIGNAL_LOCK (); |
|
2481 handler = handler_lookup (instance, handler_id, NULL); |
|
2482 connected = handler != NULL; |
|
2483 SIGNAL_UNLOCK (); |
|
2484 |
|
2485 return connected; |
|
2486 } |
|
2487 |
|
2488 EXPORT_C void |
|
2489 g_signal_handlers_destroy (gpointer instance) |
|
2490 { |
|
2491 GBSearchArray *hlbsa; |
|
2492 |
|
2493 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
2494 |
|
2495 SIGNAL_LOCK (); |
|
2496 hlbsa = g_hash_table_lookup (g_handler_list_bsa_ht, instance); |
|
2497 if (hlbsa) |
|
2498 { |
|
2499 guint i; |
|
2500 |
|
2501 /* reentrancy caution, delete instance trace first */ |
|
2502 g_hash_table_remove (g_handler_list_bsa_ht, instance); |
|
2503 |
|
2504 for (i = 0; i < hlbsa->n_nodes; i++) |
|
2505 { |
|
2506 HandlerList *hlist = g_bsearch_array_get_nth (hlbsa, &g_signal_hlbsa_bconfig, i); |
|
2507 Handler *handler = hlist->handlers; |
|
2508 |
|
2509 while (handler) |
|
2510 { |
|
2511 Handler *tmp = handler; |
|
2512 |
|
2513 handler = tmp->next; |
|
2514 tmp->block_count = 1; |
|
2515 /* cruel unlink, this works because _all_ handlers vanish */ |
|
2516 tmp->next = NULL; |
|
2517 tmp->prev = tmp; |
|
2518 if (tmp->sequential_number) |
|
2519 { |
|
2520 tmp->sequential_number = 0; |
|
2521 handler_unref_R (0, NULL, tmp); |
|
2522 } |
|
2523 } |
|
2524 } |
|
2525 g_bsearch_array_free (hlbsa, &g_signal_hlbsa_bconfig); |
|
2526 } |
|
2527 SIGNAL_UNLOCK (); |
|
2528 } |
|
2529 |
|
2530 /** |
|
2531 * g_signal_handler_find: |
|
2532 * @instance: The instance owning the signal handler to be found. |
|
2533 * @mask: Mask indicating which of @signal_id, @detail, @closure, @func |
|
2534 * and/or @data the handler has to match. |
|
2535 * @signal_id: Signal the handler has to be connected to. |
|
2536 * @detail: Signal detail the handler has to be connected to. |
|
2537 * @closure: The closure the handler will invoke. |
|
2538 * @func: The C closure callback of the handler (useless for non-C closures). |
|
2539 * @data: The closure data of the handler's closure. |
|
2540 * |
|
2541 * Finds the first signal handler that matches certain selection criteria. |
|
2542 * The criteria mask is passed as an OR-ed combination of #GSignalMatchType |
|
2543 * flags, and the criteria values are passed as arguments. |
|
2544 * The match @mask has to be non-0 for successful matches. |
|
2545 * If no handler was found, 0 is returned. |
|
2546 * |
|
2547 * Returns: A valid non-0 signal handler id for a successful match. |
|
2548 */ |
|
2549 EXPORT_C gulong |
|
2550 g_signal_handler_find (gpointer instance, |
|
2551 GSignalMatchType mask, |
|
2552 guint signal_id, |
|
2553 GQuark detail, |
|
2554 GClosure *closure, |
|
2555 gpointer func, |
|
2556 gpointer data) |
|
2557 { |
|
2558 gulong handler_seq_no = 0; |
|
2559 |
|
2560 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); |
|
2561 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); |
|
2562 |
|
2563 if (mask & G_SIGNAL_MATCH_MASK) |
|
2564 { |
|
2565 HandlerMatch *mlist; |
|
2566 |
|
2567 SIGNAL_LOCK (); |
|
2568 mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, TRUE); |
|
2569 if (mlist) |
|
2570 { |
|
2571 handler_seq_no = mlist->handler->sequential_number; |
|
2572 handler_match_free1_R (mlist, instance); |
|
2573 } |
|
2574 SIGNAL_UNLOCK (); |
|
2575 } |
|
2576 |
|
2577 return handler_seq_no; |
|
2578 } |
|
2579 |
|
2580 static guint |
|
2581 signal_handlers_foreach_matched_R (gpointer instance, |
|
2582 GSignalMatchType mask, |
|
2583 guint signal_id, |
|
2584 GQuark detail, |
|
2585 GClosure *closure, |
|
2586 gpointer func, |
|
2587 gpointer data, |
|
2588 void (*callback) (gpointer instance, |
|
2589 gulong handler_seq_no)) |
|
2590 { |
|
2591 HandlerMatch *mlist; |
|
2592 guint n_handlers = 0; |
|
2593 |
|
2594 mlist = handlers_find (instance, mask, signal_id, detail, closure, func, data, FALSE); |
|
2595 while (mlist) |
|
2596 { |
|
2597 n_handlers++; |
|
2598 if (mlist->handler->sequential_number) |
|
2599 { |
|
2600 SIGNAL_UNLOCK (); |
|
2601 callback (instance, mlist->handler->sequential_number); |
|
2602 SIGNAL_LOCK (); |
|
2603 } |
|
2604 mlist = handler_match_free1_R (mlist, instance); |
|
2605 } |
|
2606 |
|
2607 return n_handlers; |
|
2608 } |
|
2609 |
|
2610 /** |
|
2611 * g_signal_handlers_block_matched: |
|
2612 * @instance: The instance to block handlers from. |
|
2613 * @mask: Mask indicating which of @signal_id, @detail, @closure, @func |
|
2614 * and/or @data the handlers have to match. |
|
2615 * @signal_id: Signal the handlers have to be connected to. |
|
2616 * @detail: Signal detail the handlers have to be connected to. |
|
2617 * @closure: The closure the handlers will invoke. |
|
2618 * @func: The C closure callback of the handlers (useless for non-C closures). |
|
2619 * @data: The closure data of the handlers' closures. |
|
2620 * |
|
2621 * Blocks all handlers on an instance that match a certain selection criteria. |
|
2622 * The criteria mask is passed as an OR-ed combination of #GSignalMatchType |
|
2623 * flags, and the criteria values are passed as arguments. |
|
2624 * Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC |
|
2625 * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches. |
|
2626 * If no handlers were found, 0 is returned, the number of blocked handlers |
|
2627 * otherwise. |
|
2628 * |
|
2629 * Returns: The number of handlers that matched. |
|
2630 */ |
|
2631 EXPORT_C guint |
|
2632 g_signal_handlers_block_matched (gpointer instance, |
|
2633 GSignalMatchType mask, |
|
2634 guint signal_id, |
|
2635 GQuark detail, |
|
2636 GClosure *closure, |
|
2637 gpointer func, |
|
2638 gpointer data) |
|
2639 { |
|
2640 guint n_handlers = 0; |
|
2641 |
|
2642 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); |
|
2643 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); |
|
2644 |
|
2645 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) |
|
2646 { |
|
2647 SIGNAL_LOCK (); |
|
2648 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, |
|
2649 closure, func, data, |
|
2650 g_signal_handler_block); |
|
2651 SIGNAL_UNLOCK (); |
|
2652 } |
|
2653 |
|
2654 return n_handlers; |
|
2655 } |
|
2656 |
|
2657 /** |
|
2658 * g_signal_handlers_unblock_matched: |
|
2659 * @instance: The instance to unblock handlers from. |
|
2660 * @mask: Mask indicating which of @signal_id, @detail, @closure, @func |
|
2661 * and/or @data the handlers have to match. |
|
2662 * @signal_id: Signal the handlers have to be connected to. |
|
2663 * @detail: Signal detail the handlers have to be connected to. |
|
2664 * @closure: The closure the handlers will invoke. |
|
2665 * @func: The C closure callback of the handlers (useless for non-C closures). |
|
2666 * @data: The closure data of the handlers' closures. |
|
2667 * |
|
2668 * Unblocks all handlers on an instance that match a certain selection |
|
2669 * criteria. The criteria mask is passed as an OR-ed combination of |
|
2670 * #GSignalMatchType flags, and the criteria values are passed as arguments. |
|
2671 * Passing at least one of the %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC |
|
2672 * or %G_SIGNAL_MATCH_DATA match flags is required for successful matches. |
|
2673 * If no handlers were found, 0 is returned, the number of unblocked handlers |
|
2674 * otherwise. The match criteria should not apply to any handlers that are |
|
2675 * not currently blocked. |
|
2676 * |
|
2677 * Returns: The number of handlers that matched. |
|
2678 */ |
|
2679 EXPORT_C guint |
|
2680 g_signal_handlers_unblock_matched (gpointer instance, |
|
2681 GSignalMatchType mask, |
|
2682 guint signal_id, |
|
2683 GQuark detail, |
|
2684 GClosure *closure, |
|
2685 gpointer func, |
|
2686 gpointer data) |
|
2687 { |
|
2688 guint n_handlers = 0; |
|
2689 |
|
2690 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); |
|
2691 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); |
|
2692 |
|
2693 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) |
|
2694 { |
|
2695 SIGNAL_LOCK (); |
|
2696 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, |
|
2697 closure, func, data, |
|
2698 g_signal_handler_unblock); |
|
2699 SIGNAL_UNLOCK (); |
|
2700 } |
|
2701 |
|
2702 return n_handlers; |
|
2703 } |
|
2704 |
|
2705 /** |
|
2706 * g_signal_handlers_disconnect_matched: |
|
2707 * @instance: The instance to remove handlers from. |
|
2708 * @mask: Mask indicating which of @signal_id, @detail, @closure, @func |
|
2709 * and/or @data the handlers have to match. |
|
2710 * @signal_id: Signal the handlers have to be connected to. |
|
2711 * @detail: Signal detail the handlers have to be connected to. |
|
2712 * @closure: The closure the handlers will invoke. |
|
2713 * @func: The C closure callback of the handlers (useless for non-C closures). |
|
2714 * @data: The closure data of the handlers' closures. |
|
2715 * |
|
2716 * Disconnects all handlers on an instance that match a certain |
|
2717 * selection criteria. The criteria mask is passed as an OR-ed |
|
2718 * combination of #GSignalMatchType flags, and the criteria values are |
|
2719 * passed as arguments. Passing at least one of the |
|
2720 * %G_SIGNAL_MATCH_CLOSURE, %G_SIGNAL_MATCH_FUNC or |
|
2721 * %G_SIGNAL_MATCH_DATA match flags is required for successful |
|
2722 * matches. If no handlers were found, 0 is returned, the number of |
|
2723 * disconnected handlers otherwise. |
|
2724 * |
|
2725 * Returns: The number of handlers that matched. |
|
2726 */ |
|
2727 EXPORT_C guint |
|
2728 g_signal_handlers_disconnect_matched (gpointer instance, |
|
2729 GSignalMatchType mask, |
|
2730 guint signal_id, |
|
2731 GQuark detail, |
|
2732 GClosure *closure, |
|
2733 gpointer func, |
|
2734 gpointer data) |
|
2735 { |
|
2736 guint n_handlers = 0; |
|
2737 |
|
2738 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), 0); |
|
2739 g_return_val_if_fail ((mask & ~G_SIGNAL_MATCH_MASK) == 0, 0); |
|
2740 |
|
2741 if (mask & (G_SIGNAL_MATCH_CLOSURE | G_SIGNAL_MATCH_FUNC | G_SIGNAL_MATCH_DATA)) |
|
2742 { |
|
2743 SIGNAL_LOCK (); |
|
2744 n_handlers = signal_handlers_foreach_matched_R (instance, mask, signal_id, detail, |
|
2745 closure, func, data, |
|
2746 g_signal_handler_disconnect); |
|
2747 SIGNAL_UNLOCK (); |
|
2748 } |
|
2749 |
|
2750 return n_handlers; |
|
2751 } |
|
2752 |
|
2753 /** |
|
2754 * g_signal_has_handler_pending: |
|
2755 * @instance: the object whose signal handlers are sought. |
|
2756 * @signal_id: the signal id. |
|
2757 * @detail: the detail. |
|
2758 * @may_be_blocked: whether blocked handlers should count as match. |
|
2759 * |
|
2760 * Returns whether there are any handlers connected to @instance for the |
|
2761 * given signal id and detail. |
|
2762 * |
|
2763 * One example of when you might use this is when the arguments to the |
|
2764 * signal are difficult to compute. A class implementor may opt to not |
|
2765 * emit the signal if no one is attached anyway, thus saving the cost |
|
2766 * of building the arguments. |
|
2767 * |
|
2768 * Returns: %TRUE if a handler is connected to the signal, %FALSE |
|
2769 * otherwise. |
|
2770 */ |
|
2771 EXPORT_C gboolean |
|
2772 g_signal_has_handler_pending (gpointer instance, |
|
2773 guint signal_id, |
|
2774 GQuark detail, |
|
2775 gboolean may_be_blocked) |
|
2776 { |
|
2777 HandlerMatch *mlist; |
|
2778 gboolean has_pending; |
|
2779 |
|
2780 g_return_val_if_fail (G_TYPE_CHECK_INSTANCE (instance), FALSE); |
|
2781 g_return_val_if_fail (signal_id > 0, FALSE); |
|
2782 |
|
2783 SIGNAL_LOCK (); |
|
2784 if (detail) |
|
2785 { |
|
2786 SignalNode *node = LOOKUP_SIGNAL_NODE (signal_id); |
|
2787 |
|
2788 if (!(node->flags & G_SIGNAL_DETAILED)) |
|
2789 { |
|
2790 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); |
|
2791 SIGNAL_UNLOCK (); |
|
2792 return FALSE; |
|
2793 } |
|
2794 } |
|
2795 mlist = handlers_find (instance, |
|
2796 (G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DETAIL | (may_be_blocked ? 0 : G_SIGNAL_MATCH_UNBLOCKED)), |
|
2797 signal_id, detail, NULL, NULL, NULL, TRUE); |
|
2798 if (mlist) |
|
2799 { |
|
2800 has_pending = TRUE; |
|
2801 handler_match_free1_R (mlist, instance); |
|
2802 } |
|
2803 else |
|
2804 has_pending = FALSE; |
|
2805 SIGNAL_UNLOCK (); |
|
2806 |
|
2807 return has_pending; |
|
2808 } |
|
2809 |
|
2810 static inline gboolean |
|
2811 signal_check_skip_emission (SignalNode *node, |
|
2812 gpointer instance, |
|
2813 GQuark detail) |
|
2814 { |
|
2815 HandlerList *hlist; |
|
2816 |
|
2817 /* are we able to check for NULL class handlers? */ |
|
2818 if (!node->test_class_offset) |
|
2819 return FALSE; |
|
2820 |
|
2821 /* are there emission hooks pending? */ |
|
2822 if (node->emission_hooks && node->emission_hooks->hooks) |
|
2823 return FALSE; |
|
2824 |
|
2825 /* is there a non-NULL class handler? */ |
|
2826 if (node->test_class_offset != TEST_CLASS_MAGIC) |
|
2827 { |
|
2828 GTypeClass *class = G_TYPE_INSTANCE_GET_CLASS (instance, G_TYPE_FROM_INSTANCE (instance), GTypeClass); |
|
2829 |
|
2830 if (G_STRUCT_MEMBER (gpointer, class, node->test_class_offset)) |
|
2831 return FALSE; |
|
2832 } |
|
2833 |
|
2834 /* are signals being debugged? */ |
|
2835 #ifdef G_ENABLE_DEBUG |
|
2836 IF_DEBUG (SIGNALS, g_trace_instance_signals || g_trap_instance_signals) |
|
2837 return FALSE; |
|
2838 #endif /* G_ENABLE_DEBUG */ |
|
2839 |
|
2840 /* is this a no-recurse signal already in emission? */ |
|
2841 if (node->flags & G_SIGNAL_NO_RECURSE && |
|
2842 emission_find (g_restart_emissions, node->signal_id, detail, instance)) |
|
2843 return FALSE; |
|
2844 |
|
2845 /* do we have pending handlers? */ |
|
2846 hlist = handler_list_lookup (node->signal_id, instance); |
|
2847 if (hlist && hlist->handlers) |
|
2848 return FALSE; |
|
2849 |
|
2850 /* none of the above, no emission required */ |
|
2851 return TRUE; |
|
2852 } |
|
2853 |
|
2854 /** |
|
2855 * g_signal_emitv: |
|
2856 * @instance_and_params: argument list for the signal emission. The first |
|
2857 * element in the array is a #GValue for the instance the signal is |
|
2858 * being emitted on. The rest are any arguments to be passed to the |
|
2859 * signal. |
|
2860 * @signal_id: the signal id |
|
2861 * @detail: the detail |
|
2862 * @return_value: Location to store the return value of the signal emission. |
|
2863 * |
|
2864 * Emits a signal. |
|
2865 * |
|
2866 * Note that g_signal_emitv() doesn't change @return_value if no handlers are |
|
2867 * connected, in contrast to g_signal_emit() and g_signal_emit_valist(). |
|
2868 */ |
|
2869 EXPORT_C void |
|
2870 g_signal_emitv (const GValue *instance_and_params, |
|
2871 guint signal_id, |
|
2872 GQuark detail, |
|
2873 GValue *return_value) |
|
2874 { |
|
2875 gpointer instance; |
|
2876 SignalNode *node; |
|
2877 #ifdef G_ENABLE_DEBUG |
|
2878 const GValue *param_values; |
|
2879 guint i; |
|
2880 #endif |
|
2881 |
|
2882 g_return_if_fail (instance_and_params != NULL); |
|
2883 instance = g_value_peek_pointer (instance_and_params); |
|
2884 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
2885 g_return_if_fail (signal_id > 0); |
|
2886 |
|
2887 #ifdef G_ENABLE_DEBUG |
|
2888 param_values = instance_and_params + 1; |
|
2889 #endif |
|
2890 |
|
2891 SIGNAL_LOCK (); |
|
2892 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
2893 if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) |
|
2894 { |
|
2895 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); |
|
2896 SIGNAL_UNLOCK (); |
|
2897 return; |
|
2898 } |
|
2899 #ifdef G_ENABLE_DEBUG |
|
2900 if (detail && !(node->flags & G_SIGNAL_DETAILED)) |
|
2901 { |
|
2902 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); |
|
2903 SIGNAL_UNLOCK (); |
|
2904 return; |
|
2905 } |
|
2906 for (i = 0; i < node->n_params; i++) |
|
2907 if (!G_TYPE_CHECK_VALUE_TYPE (param_values + i, node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE)) |
|
2908 { |
|
2909 g_critical ("%s: value for `%s' parameter %u for signal \"%s\" is of type `%s'", |
|
2910 G_STRLOC, |
|
2911 type_debug_name (node->param_types[i]), |
|
2912 i, |
|
2913 node->name, |
|
2914 G_VALUE_TYPE_NAME (param_values + i)); |
|
2915 SIGNAL_UNLOCK (); |
|
2916 return; |
|
2917 } |
|
2918 if (node->return_type != G_TYPE_NONE) |
|
2919 { |
|
2920 if (!return_value) |
|
2921 { |
|
2922 g_critical ("%s: return value `%s' for signal \"%s\" is (NULL)", |
|
2923 G_STRLOC, |
|
2924 type_debug_name (node->return_type), |
|
2925 node->name); |
|
2926 SIGNAL_UNLOCK (); |
|
2927 return; |
|
2928 } |
|
2929 else if (!node->accumulator && !G_TYPE_CHECK_VALUE_TYPE (return_value, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE)) |
|
2930 { |
|
2931 g_critical ("%s: return value `%s' for signal \"%s\" is of type `%s'", |
|
2932 G_STRLOC, |
|
2933 type_debug_name (node->return_type), |
|
2934 node->name, |
|
2935 G_VALUE_TYPE_NAME (return_value)); |
|
2936 SIGNAL_UNLOCK (); |
|
2937 return; |
|
2938 } |
|
2939 } |
|
2940 else |
|
2941 return_value = NULL; |
|
2942 #endif /* G_ENABLE_DEBUG */ |
|
2943 |
|
2944 /* optimize NOP emissions */ |
|
2945 if (signal_check_skip_emission (node, instance, detail)) |
|
2946 { |
|
2947 /* nothing to do to emit this signal */ |
|
2948 SIGNAL_UNLOCK (); |
|
2949 /* g_printerr ("omitting emission of \"%s\"\n", node->name); */ |
|
2950 return; |
|
2951 } |
|
2952 |
|
2953 SIGNAL_UNLOCK (); |
|
2954 signal_emit_unlocked_R (node, detail, instance, return_value, instance_and_params); |
|
2955 } |
|
2956 |
|
2957 /** |
|
2958 * g_signal_emit_valist: |
|
2959 * @instance: the instance the signal is being emitted on. |
|
2960 * @signal_id: the signal id |
|
2961 * @detail: the detail |
|
2962 * @var_args: a list of parameters to be passed to the signal, followed by a |
|
2963 * location for the return value. If the return type of the signal |
|
2964 * is #G_TYPE_NONE, the return value location can be omitted. |
|
2965 * |
|
2966 * Emits a signal. |
|
2967 * |
|
2968 * Note that g_signal_emit_valist() resets the return value to the default |
|
2969 * if no handlers are connected, in contrast to g_signal_emitv(). |
|
2970 */ |
|
2971 EXPORT_C void |
|
2972 g_signal_emit_valist (gpointer instance, |
|
2973 guint signal_id, |
|
2974 GQuark detail, |
|
2975 va_list var_args) |
|
2976 { |
|
2977 GValue *instance_and_params; |
|
2978 GType signal_return_type; |
|
2979 GValue *param_values; |
|
2980 SignalNode *node; |
|
2981 guint i, n_params; |
|
2982 |
|
2983 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
2984 g_return_if_fail (signal_id > 0); |
|
2985 |
|
2986 SIGNAL_LOCK (); |
|
2987 node = LOOKUP_SIGNAL_NODE (signal_id); |
|
2988 if (!node || !g_type_is_a (G_TYPE_FROM_INSTANCE (instance), node->itype)) |
|
2989 { |
|
2990 g_warning ("%s: signal id `%u' is invalid for instance `%p'", G_STRLOC, signal_id, instance); |
|
2991 SIGNAL_UNLOCK (); |
|
2992 return; |
|
2993 } |
|
2994 #ifndef G_DISABLE_CHECKS |
|
2995 if (detail && !(node->flags & G_SIGNAL_DETAILED)) |
|
2996 { |
|
2997 g_warning ("%s: signal id `%u' does not support detail (%u)", G_STRLOC, signal_id, detail); |
|
2998 SIGNAL_UNLOCK (); |
|
2999 return; |
|
3000 } |
|
3001 #endif /* !G_DISABLE_CHECKS */ |
|
3002 |
|
3003 /* optimize NOP emissions */ |
|
3004 if (signal_check_skip_emission (node, instance, detail)) |
|
3005 { |
|
3006 /* nothing to do to emit this signal */ |
|
3007 SIGNAL_UNLOCK (); |
|
3008 /* g_printerr ("omitting emission of \"%s\"\n", node->name); */ |
|
3009 return; |
|
3010 } |
|
3011 |
|
3012 n_params = node->n_params; |
|
3013 signal_return_type = node->return_type; |
|
3014 instance_and_params = g_slice_alloc (sizeof (GValue) * (n_params + 1)); |
|
3015 param_values = instance_and_params + 1; |
|
3016 |
|
3017 for (i = 0; i < node->n_params; i++) |
|
3018 { |
|
3019 gchar *error; |
|
3020 GType ptype = node->param_types[i] & ~G_SIGNAL_TYPE_STATIC_SCOPE; |
|
3021 gboolean static_scope = node->param_types[i] & G_SIGNAL_TYPE_STATIC_SCOPE; |
|
3022 |
|
3023 param_values[i].g_type = 0; |
|
3024 SIGNAL_UNLOCK (); |
|
3025 g_value_init (param_values + i, ptype); |
|
3026 G_VALUE_COLLECT (param_values + i, |
|
3027 var_args, |
|
3028 static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, |
|
3029 &error); |
|
3030 if (error) |
|
3031 { |
|
3032 g_warning ("%s: %s", G_STRLOC, error); |
|
3033 g_free (error); |
|
3034 |
|
3035 /* we purposely leak the value here, it might not be |
|
3036 * in a sane state if an error condition occoured |
|
3037 */ |
|
3038 while (i--) |
|
3039 g_value_unset (param_values + i); |
|
3040 |
|
3041 g_slice_free1 (sizeof (GValue) * (n_params + 1), instance_and_params); |
|
3042 return; |
|
3043 } |
|
3044 SIGNAL_LOCK (); |
|
3045 } |
|
3046 SIGNAL_UNLOCK (); |
|
3047 instance_and_params->g_type = 0; |
|
3048 g_value_init (instance_and_params, G_TYPE_FROM_INSTANCE (instance)); |
|
3049 g_value_set_instance (instance_and_params, instance); |
|
3050 if (signal_return_type == G_TYPE_NONE) |
|
3051 signal_emit_unlocked_R (node, detail, instance, NULL, instance_and_params); |
|
3052 else |
|
3053 { |
|
3054 GValue return_value = { 0, }; |
|
3055 gchar *error = NULL; |
|
3056 GType rtype = signal_return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE; |
|
3057 gboolean static_scope = signal_return_type & G_SIGNAL_TYPE_STATIC_SCOPE; |
|
3058 |
|
3059 g_value_init (&return_value, rtype); |
|
3060 |
|
3061 signal_emit_unlocked_R (node, detail, instance, &return_value, instance_and_params); |
|
3062 |
|
3063 G_VALUE_LCOPY (&return_value, |
|
3064 var_args, |
|
3065 static_scope ? G_VALUE_NOCOPY_CONTENTS : 0, |
|
3066 &error); |
|
3067 if (!error) |
|
3068 g_value_unset (&return_value); |
|
3069 else |
|
3070 { |
|
3071 g_warning ("%s: %s", G_STRLOC, error); |
|
3072 g_free (error); |
|
3073 |
|
3074 /* we purposely leak the value here, it might not be |
|
3075 * in a sane state if an error condition occured |
|
3076 */ |
|
3077 } |
|
3078 } |
|
3079 for (i = 0; i < n_params; i++) |
|
3080 g_value_unset (param_values + i); |
|
3081 g_value_unset (instance_and_params); |
|
3082 g_slice_free1 (sizeof (GValue) * (n_params + 1), instance_and_params); |
|
3083 } |
|
3084 |
|
3085 /** |
|
3086 * g_signal_emit: |
|
3087 * @instance: the instance the signal is being emitted on. |
|
3088 * @signal_id: the signal id |
|
3089 * @detail: the detail |
|
3090 * @...: parameters to be passed to the signal, followed by a |
|
3091 * location for the return value. If the return type of the signal |
|
3092 * is #G_TYPE_NONE, the return value location can be omitted. |
|
3093 * |
|
3094 * Emits a signal. |
|
3095 * |
|
3096 * Note that g_signal_emit() resets the return value to the default |
|
3097 * if no handlers are connected, in contrast to g_signal_emitv(). |
|
3098 */ |
|
3099 EXPORT_C void |
|
3100 g_signal_emit (gpointer instance, |
|
3101 guint signal_id, |
|
3102 GQuark detail, |
|
3103 ...) |
|
3104 { |
|
3105 va_list var_args; |
|
3106 |
|
3107 va_start (var_args, detail); |
|
3108 g_signal_emit_valist (instance, signal_id, detail, var_args); |
|
3109 va_end (var_args); |
|
3110 } |
|
3111 |
|
3112 /** |
|
3113 * g_signal_emit_by_name: |
|
3114 * @instance: the instance the signal is being emitted on. |
|
3115 * @detailed_signal: a string of the form "signal-name::detail". |
|
3116 * @...: parameters to be passed to the signal, followed by a |
|
3117 * location for the return value. If the return type of the signal |
|
3118 * is #G_TYPE_NONE, the return value location can be omitted. |
|
3119 * |
|
3120 * Emits a signal. |
|
3121 * |
|
3122 * Note that g_signal_emit_by_name() resets the return value to the default |
|
3123 * if no handlers are connected, in contrast to g_signal_emitv(). |
|
3124 */ |
|
3125 EXPORT_C void |
|
3126 g_signal_emit_by_name (gpointer instance, |
|
3127 const gchar *detailed_signal, |
|
3128 ...) |
|
3129 { |
|
3130 GQuark detail = 0; |
|
3131 guint signal_id; |
|
3132 |
|
3133 g_return_if_fail (G_TYPE_CHECK_INSTANCE (instance)); |
|
3134 g_return_if_fail (detailed_signal != NULL); |
|
3135 |
|
3136 SIGNAL_LOCK (); |
|
3137 signal_id = signal_parse_name (detailed_signal, G_TYPE_FROM_INSTANCE (instance), &detail, TRUE); |
|
3138 SIGNAL_UNLOCK (); |
|
3139 |
|
3140 if (signal_id) |
|
3141 { |
|
3142 va_list var_args; |
|
3143 |
|
3144 va_start (var_args, detailed_signal); |
|
3145 g_signal_emit_valist (instance, signal_id, detail, var_args); |
|
3146 va_end (var_args); |
|
3147 } |
|
3148 else |
|
3149 g_warning ("%s: signal name `%s' is invalid for instance `%p'", G_STRLOC, detailed_signal, instance); |
|
3150 } |
|
3151 |
|
3152 static inline gboolean |
|
3153 accumulate (GSignalInvocationHint *ihint, |
|
3154 GValue *return_accu, |
|
3155 GValue *handler_return, |
|
3156 SignalAccumulator *accumulator) |
|
3157 { |
|
3158 gboolean continue_emission; |
|
3159 |
|
3160 if (!accumulator) |
|
3161 return TRUE; |
|
3162 |
|
3163 continue_emission = accumulator->func (ihint, return_accu, handler_return, accumulator->data); |
|
3164 g_value_reset (handler_return); |
|
3165 |
|
3166 return continue_emission; |
|
3167 } |
|
3168 |
|
3169 static gboolean |
|
3170 signal_emit_unlocked_R (SignalNode *node, |
|
3171 GQuark detail, |
|
3172 gpointer instance, |
|
3173 GValue *emission_return, |
|
3174 const GValue *instance_and_params) |
|
3175 { |
|
3176 SignalAccumulator *accumulator; |
|
3177 Emission emission; |
|
3178 GClosure *class_closure; |
|
3179 HandlerList *hlist; |
|
3180 Handler *handler_list = NULL; |
|
3181 GValue *return_accu, accu = { 0, }; |
|
3182 guint signal_id; |
|
3183 gulong max_sequential_handler_number; |
|
3184 gboolean return_value_altered = FALSE; |
|
3185 |
|
3186 #ifdef G_ENABLE_DEBUG |
|
3187 IF_DEBUG (SIGNALS, g_trace_instance_signals == instance || g_trap_instance_signals == instance) |
|
3188 { |
|
3189 g_message ("%s::%s(%u) emitted (instance=%p, signal-node=%p)", |
|
3190 g_type_name (G_TYPE_FROM_INSTANCE (instance)), |
|
3191 node->name, detail, |
|
3192 instance, node); |
|
3193 if (g_trap_instance_signals == instance) |
|
3194 G_BREAKPOINT (); |
|
3195 } |
|
3196 #endif /* G_ENABLE_DEBUG */ |
|
3197 |
|
3198 SIGNAL_LOCK (); |
|
3199 signal_id = node->signal_id; |
|
3200 if (node->flags & G_SIGNAL_NO_RECURSE) |
|
3201 { |
|
3202 Emission *node = emission_find (g_restart_emissions, signal_id, detail, instance); |
|
3203 |
|
3204 if (node) |
|
3205 { |
|
3206 node->state = EMISSION_RESTART; |
|
3207 SIGNAL_UNLOCK (); |
|
3208 return return_value_altered; |
|
3209 } |
|
3210 } |
|
3211 accumulator = node->accumulator; |
|
3212 if (accumulator) |
|
3213 { |
|
3214 SIGNAL_UNLOCK (); |
|
3215 g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); |
|
3216 return_accu = &accu; |
|
3217 SIGNAL_LOCK (); |
|
3218 } |
|
3219 else |
|
3220 return_accu = emission_return; |
|
3221 emission.instance = instance; |
|
3222 emission.ihint.signal_id = node->signal_id; |
|
3223 emission.ihint.detail = detail; |
|
3224 emission.ihint.run_type = 0; |
|
3225 emission.state = 0; |
|
3226 emission.chain_type = G_TYPE_NONE; |
|
3227 emission_push ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission); |
|
3228 class_closure = signal_lookup_closure (node, instance); |
|
3229 |
|
3230 EMIT_RESTART: |
|
3231 |
|
3232 if (handler_list) |
|
3233 handler_unref_R (signal_id, instance, handler_list); |
|
3234 max_sequential_handler_number = g_handler_sequential_number; |
|
3235 hlist = handler_list_lookup (signal_id, instance); |
|
3236 handler_list = hlist ? hlist->handlers : NULL; |
|
3237 if (handler_list) |
|
3238 handler_ref (handler_list); |
|
3239 |
|
3240 emission.ihint.run_type = G_SIGNAL_RUN_FIRST; |
|
3241 |
|
3242 if ((node->flags & G_SIGNAL_RUN_FIRST) && class_closure) |
|
3243 { |
|
3244 emission.state = EMISSION_RUN; |
|
3245 |
|
3246 emission.chain_type = G_TYPE_FROM_INSTANCE (instance); |
|
3247 SIGNAL_UNLOCK (); |
|
3248 g_closure_invoke (class_closure, |
|
3249 return_accu, |
|
3250 node->n_params + 1, |
|
3251 instance_and_params, |
|
3252 &emission.ihint); |
|
3253 if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && |
|
3254 emission.state == EMISSION_RUN) |
|
3255 emission.state = EMISSION_STOP; |
|
3256 SIGNAL_LOCK (); |
|
3257 emission.chain_type = G_TYPE_NONE; |
|
3258 return_value_altered = TRUE; |
|
3259 |
|
3260 if (emission.state == EMISSION_STOP) |
|
3261 goto EMIT_CLEANUP; |
|
3262 else if (emission.state == EMISSION_RESTART) |
|
3263 goto EMIT_RESTART; |
|
3264 } |
|
3265 |
|
3266 if (node->emission_hooks) |
|
3267 { |
|
3268 gboolean need_destroy, was_in_call, may_recurse = TRUE; |
|
3269 GHook *hook; |
|
3270 |
|
3271 emission.state = EMISSION_HOOK; |
|
3272 hook = g_hook_first_valid (node->emission_hooks, may_recurse); |
|
3273 while (hook) |
|
3274 { |
|
3275 SignalHook *signal_hook = SIGNAL_HOOK (hook); |
|
3276 |
|
3277 if (!signal_hook->detail || signal_hook->detail == detail) |
|
3278 { |
|
3279 GSignalEmissionHook hook_func = (GSignalEmissionHook) hook->func; |
|
3280 |
|
3281 was_in_call = G_HOOK_IN_CALL (hook); |
|
3282 hook->flags |= G_HOOK_FLAG_IN_CALL; |
|
3283 SIGNAL_UNLOCK (); |
|
3284 need_destroy = !hook_func (&emission.ihint, node->n_params + 1, instance_and_params, hook->data); |
|
3285 SIGNAL_LOCK (); |
|
3286 if (!was_in_call) |
|
3287 hook->flags &= ~G_HOOK_FLAG_IN_CALL; |
|
3288 if (need_destroy) |
|
3289 g_hook_destroy_link (node->emission_hooks, hook); |
|
3290 } |
|
3291 hook = g_hook_next_valid (node->emission_hooks, hook, may_recurse); |
|
3292 } |
|
3293 |
|
3294 if (emission.state == EMISSION_RESTART) |
|
3295 goto EMIT_RESTART; |
|
3296 } |
|
3297 |
|
3298 if (handler_list) |
|
3299 { |
|
3300 Handler *handler = handler_list; |
|
3301 |
|
3302 emission.state = EMISSION_RUN; |
|
3303 handler_ref (handler); |
|
3304 do |
|
3305 { |
|
3306 Handler *tmp; |
|
3307 |
|
3308 if (handler->after) |
|
3309 { |
|
3310 handler_unref_R (signal_id, instance, handler_list); |
|
3311 handler_list = handler; |
|
3312 break; |
|
3313 } |
|
3314 else if (!handler->block_count && (!handler->detail || handler->detail == detail) && |
|
3315 handler->sequential_number < max_sequential_handler_number) |
|
3316 { |
|
3317 SIGNAL_UNLOCK (); |
|
3318 g_closure_invoke (handler->closure, |
|
3319 return_accu, |
|
3320 node->n_params + 1, |
|
3321 instance_and_params, |
|
3322 &emission.ihint); |
|
3323 if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && |
|
3324 emission.state == EMISSION_RUN) |
|
3325 emission.state = EMISSION_STOP; |
|
3326 SIGNAL_LOCK (); |
|
3327 return_value_altered = TRUE; |
|
3328 |
|
3329 tmp = emission.state == EMISSION_RUN ? handler->next : NULL; |
|
3330 } |
|
3331 else |
|
3332 tmp = handler->next; |
|
3333 |
|
3334 if (tmp) |
|
3335 handler_ref (tmp); |
|
3336 handler_unref_R (signal_id, instance, handler_list); |
|
3337 handler_list = handler; |
|
3338 handler = tmp; |
|
3339 } |
|
3340 while (handler); |
|
3341 |
|
3342 if (emission.state == EMISSION_STOP) |
|
3343 goto EMIT_CLEANUP; |
|
3344 else if (emission.state == EMISSION_RESTART) |
|
3345 goto EMIT_RESTART; |
|
3346 } |
|
3347 |
|
3348 emission.ihint.run_type = G_SIGNAL_RUN_LAST; |
|
3349 |
|
3350 if ((node->flags & G_SIGNAL_RUN_LAST) && class_closure) |
|
3351 { |
|
3352 emission.state = EMISSION_RUN; |
|
3353 |
|
3354 emission.chain_type = G_TYPE_FROM_INSTANCE (instance); |
|
3355 SIGNAL_UNLOCK (); |
|
3356 g_closure_invoke (class_closure, |
|
3357 return_accu, |
|
3358 node->n_params + 1, |
|
3359 instance_and_params, |
|
3360 &emission.ihint); |
|
3361 if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && |
|
3362 emission.state == EMISSION_RUN) |
|
3363 emission.state = EMISSION_STOP; |
|
3364 SIGNAL_LOCK (); |
|
3365 emission.chain_type = G_TYPE_NONE; |
|
3366 return_value_altered = TRUE; |
|
3367 |
|
3368 if (emission.state == EMISSION_STOP) |
|
3369 goto EMIT_CLEANUP; |
|
3370 else if (emission.state == EMISSION_RESTART) |
|
3371 goto EMIT_RESTART; |
|
3372 } |
|
3373 |
|
3374 if (handler_list) |
|
3375 { |
|
3376 Handler *handler = handler_list; |
|
3377 |
|
3378 emission.state = EMISSION_RUN; |
|
3379 handler_ref (handler); |
|
3380 do |
|
3381 { |
|
3382 Handler *tmp; |
|
3383 |
|
3384 if (handler->after && !handler->block_count && (!handler->detail || handler->detail == detail) && |
|
3385 handler->sequential_number < max_sequential_handler_number) |
|
3386 { |
|
3387 SIGNAL_UNLOCK (); |
|
3388 g_closure_invoke (handler->closure, |
|
3389 return_accu, |
|
3390 node->n_params + 1, |
|
3391 instance_and_params, |
|
3392 &emission.ihint); |
|
3393 if (!accumulate (&emission.ihint, emission_return, &accu, accumulator) && |
|
3394 emission.state == EMISSION_RUN) |
|
3395 emission.state = EMISSION_STOP; |
|
3396 SIGNAL_LOCK (); |
|
3397 return_value_altered = TRUE; |
|
3398 |
|
3399 tmp = emission.state == EMISSION_RUN ? handler->next : NULL; |
|
3400 } |
|
3401 else |
|
3402 tmp = handler->next; |
|
3403 |
|
3404 if (tmp) |
|
3405 handler_ref (tmp); |
|
3406 handler_unref_R (signal_id, instance, handler); |
|
3407 handler = tmp; |
|
3408 } |
|
3409 while (handler); |
|
3410 |
|
3411 if (emission.state == EMISSION_STOP) |
|
3412 goto EMIT_CLEANUP; |
|
3413 else if (emission.state == EMISSION_RESTART) |
|
3414 goto EMIT_RESTART; |
|
3415 } |
|
3416 |
|
3417 EMIT_CLEANUP: |
|
3418 |
|
3419 emission.ihint.run_type = G_SIGNAL_RUN_CLEANUP; |
|
3420 |
|
3421 if ((node->flags & G_SIGNAL_RUN_CLEANUP) && class_closure) |
|
3422 { |
|
3423 gboolean need_unset = FALSE; |
|
3424 |
|
3425 emission.state = EMISSION_STOP; |
|
3426 |
|
3427 emission.chain_type = G_TYPE_FROM_INSTANCE (instance); |
|
3428 SIGNAL_UNLOCK (); |
|
3429 if (node->return_type != G_TYPE_NONE && !accumulator) |
|
3430 { |
|
3431 g_value_init (&accu, node->return_type & ~G_SIGNAL_TYPE_STATIC_SCOPE); |
|
3432 need_unset = TRUE; |
|
3433 } |
|
3434 g_closure_invoke (class_closure, |
|
3435 node->return_type != G_TYPE_NONE ? &accu : NULL, |
|
3436 node->n_params + 1, |
|
3437 instance_and_params, |
|
3438 &emission.ihint); |
|
3439 if (need_unset) |
|
3440 g_value_unset (&accu); |
|
3441 SIGNAL_LOCK (); |
|
3442 emission.chain_type = G_TYPE_NONE; |
|
3443 |
|
3444 if (emission.state == EMISSION_RESTART) |
|
3445 goto EMIT_RESTART; |
|
3446 } |
|
3447 |
|
3448 if (handler_list) |
|
3449 handler_unref_R (signal_id, instance, handler_list); |
|
3450 |
|
3451 emission_pop ((node->flags & G_SIGNAL_NO_RECURSE) ? &g_restart_emissions : &g_recursive_emissions, &emission); |
|
3452 SIGNAL_UNLOCK (); |
|
3453 if (accumulator) |
|
3454 g_value_unset (&accu); |
|
3455 |
|
3456 return return_value_altered; |
|
3457 } |
|
3458 |
|
3459 static const gchar* |
|
3460 type_debug_name (GType type) |
|
3461 { |
|
3462 if (type) |
|
3463 { |
|
3464 const char *name = g_type_name (type & ~G_SIGNAL_TYPE_STATIC_SCOPE); |
|
3465 return name ? name : "<unknown>"; |
|
3466 } |
|
3467 else |
|
3468 return "<invalid>"; |
|
3469 } |
|
3470 |
|
3471 /** |
|
3472 * g_signal_accumulator_true_handled: |
|
3473 * @ihint: standard #GSignalAccumulator parameter |
|
3474 * @return_accu: standard #GSignalAccumulator parameter |
|
3475 * @handler_return: standard #GSignalAccumulator parameter |
|
3476 * @dummy: standard #GSignalAccumulator parameter |
|
3477 * |
|
3478 * A predefined #GSignalAccumulator for signals that return a |
|
3479 * boolean values. The behavior that this accumulator gives is |
|
3480 * that a return of %TRUE stops the signal emission: no further |
|
3481 * callbacks will be invoked, while a return of %FALSE allows |
|
3482 * the emission to coninue. The idea here is that a %TRUE return |
|
3483 * indicates that the callback <emphasis>handled</emphasis> the signal, |
|
3484 * and no further handling is needed. |
|
3485 * |
|
3486 * Since: 2.4 |
|
3487 * |
|
3488 * Returns: standard #GSignalAccumulator result |
|
3489 */ |
|
3490 EXPORT_C gboolean |
|
3491 g_signal_accumulator_true_handled (GSignalInvocationHint *ihint, |
|
3492 GValue *return_accu, |
|
3493 const GValue *handler_return, |
|
3494 gpointer dummy) |
|
3495 { |
|
3496 gboolean continue_emission; |
|
3497 gboolean signal_handled; |
|
3498 |
|
3499 signal_handled = g_value_get_boolean (handler_return); |
|
3500 g_value_set_boolean (return_accu, signal_handled); |
|
3501 continue_emission = !signal_handled; |
|
3502 |
|
3503 return continue_emission; |
|
3504 } |
|
3505 |
|
3506 /* --- compile standard marshallers --- */ |
|
3507 #include "gmarshal.c" |
|
3508 |
|
3509 #define __G_SIGNAL_C__ |
|
3510 #include "gobjectaliasdef.c" |