added some assertions to test g_signal_get_invocation_hint().
[platform/upstream/glib.git] / tests / gobject / override.c
1 /* -*- mode: C; c-basic-offset: 4 -*- */
2 #include <glib.h>
3 #include <glib-object.h>
4
5 static guint foo_signal_id = 0;
6 static guint bar_signal_id = 0;
7
8
9 static GType test_i_get_type (void);
10 static GType test_a_get_type (void);
11 static GType test_b_get_type (void);
12 static GType test_c_get_type (void);
13
14 #define TEST_TYPE_I (test_i_get_type ())
15 #define TEST_I(object) (G_TYPE_CHECK_INSTANCE_CAST((object), TEST_TYPE_I, TestI))
16 #define TEST_I_CLASS(vtable) (G_TYPE_CHECK_CLASS_CAST((vtable), TEST_TYPE_I, TestIClass))
17 #define TEST_IS_I(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), TEST_TYPE_I))
18 #define TEST_IS_I_CLASS(vtable) (G_TYPE_CHECK_CLASS_TYPE((vtable), TEST_TYPE_I))
19 #define TEST_I_GET_CLASS(object) (G_TYPE_INSTANCE_GET_INTERFACE((object), TEST_TYPE_I, TestIClass))
20
21 typedef struct _TestI TestI;
22 typedef struct _TestIClass TestIClass;
23
24 struct _TestIClass {
25     GTypeInterface base_iface;
26 };
27
28 static void
29 test_i_foo (TestI *self)
30 {
31     g_print("TestI::foo called.\n");
32 }
33
34
35 static void
36 test_i_base_init (gpointer g_class)
37 {
38     static gboolean initialised = FALSE;
39
40     if (!initialised) {
41         foo_signal_id = g_signal_newv("foo",
42                                       TEST_TYPE_I,
43                                       G_SIGNAL_RUN_LAST,
44                                       g_cclosure_new(G_CALLBACK(test_i_foo),
45                                                      NULL, NULL),
46                                       NULL, NULL,
47                                       g_cclosure_marshal_VOID__VOID,
48                                       G_TYPE_NONE, 0, NULL);
49     }
50     initialised = TRUE;
51 }
52
53 static GType
54 test_i_get_type (void)
55 {
56     static GType type = 0;
57   
58     if (!type) {
59         static const GTypeInfo type_info = {
60             sizeof (TestIClass),
61             (GBaseInitFunc) test_i_base_init, /* base_init */
62             NULL,             /* base_finalize */
63         };
64       
65         type = g_type_register_static (G_TYPE_INTERFACE, "TestI",
66                                        &type_info, 0);
67     }
68   
69     return type;
70 }
71
72
73
74 #define TEST_TYPE_A (test_a_get_type())
75 #define TEST_A(object) (G_TYPE_CHECK_INSTANCE_CAST((object), TEST_TYPE_A, TestA))
76 #define TEST_A_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_A, TestAClass))
77 #define TEST_IS_A(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), TEST_TYPE_A))
78 #define TEST_IS_A_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_A))
79 #define TEST_A_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TEST_TYPE_A, TestAClass))
80
81 typedef struct _TestA TestA;
82 typedef struct _TestAClass TestAClass;
83
84 struct _TestA {
85     GObject parent;
86 };
87 struct _TestAClass {
88     GObjectClass parent_class;
89
90     void (* bar) (TestA *self);
91 };
92
93 static void
94 test_a_foo (TestI *self)
95 {
96     GValue args[1] = { { 0, } };
97
98     g_print("TestA::foo called.  Chaining up.\n");
99
100     g_value_init (&args[0], TEST_TYPE_A);
101     g_value_set_object (&args[0], self);
102
103     g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
104     g_signal_chain_from_overridden (args, NULL);
105
106     g_value_unset (&args[0]);
107 }
108
109 static void
110 test_a_bar (TestA *self)
111 {
112     g_print("TestA::bar called.\n");
113 }
114
115 static void
116 test_a_class_init (TestAClass *class)
117 {
118     class->bar = test_a_bar;
119
120     bar_signal_id = g_signal_new("bar",
121                                  TEST_TYPE_A,
122                                  G_SIGNAL_RUN_LAST,
123                                  G_STRUCT_OFFSET (TestAClass, bar),
124                                  NULL, NULL,
125                                  g_cclosure_marshal_VOID__VOID,
126                                  G_TYPE_NONE, 0);
127 }
128
129 static void
130 test_a_interface_init (TestIClass *iface)
131 {
132     g_signal_override_class_closure (foo_signal_id,
133                                      TEST_TYPE_A,
134                                      g_cclosure_new (G_CALLBACK (test_a_foo),
135                                                      NULL, NULL));
136 }
137
138 static GType
139 test_a_get_type (void)
140 {
141     static GType type = 0;
142   
143     if (!type) {
144         static const GTypeInfo type_info = {
145             sizeof(TestAClass),
146             (GBaseInitFunc) NULL,
147             (GBaseFinalizeFunc) NULL,
148             (GClassInitFunc) test_a_class_init,
149             NULL, /* class_finalize */
150             NULL, /* class_data */
151             sizeof(TestAClass),
152             0, /* n_preallocs */
153             (GInstanceInitFunc) NULL,
154         };
155         static const GInterfaceInfo interface_info = {
156             (GInterfaceInitFunc) test_a_interface_init,
157             NULL,
158             NULL
159         };
160
161         type = g_type_register_static (G_TYPE_OBJECT, "TestA",
162                                        &type_info, 0);
163         g_type_add_interface_static (type, TEST_TYPE_I, &interface_info);
164     }
165   
166   return type;
167 }
168
169
170 #define TEST_TYPE_B (test_b_get_type())
171 #define TEST_B(object) (G_TYPE_CHECK_INSTANCE_CAST((object), TEST_TYPE_B, TestB))
172 #define TEST_B_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_B, TestBClass))
173 #define TEST_IS_B(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), TEST_TYPE_B))
174 #define TEST_IS_B_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_B))
175 #define TEST_B_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TEST_TYPE_B, TestBClass))
176
177 typedef struct _TestB TestB;
178 typedef struct _TestBClass TestBClass;
179
180 struct _TestB {
181     TestA parent;
182 };
183 struct _TestBClass {
184     TestAClass parent_class;
185 };
186
187 static void
188 test_b_foo (TestA *self)
189 {
190     GValue args[1] = { { 0, } };
191
192     g_print("TestB::foo called.  Chaining up.\n");
193
194     g_value_init (&args[0], TEST_TYPE_A);
195     g_value_set_object (&args[0], self);
196
197     g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
198     g_signal_chain_from_overridden (args, NULL);
199
200     g_value_unset (&args[0]);
201 }
202
203 static void
204 test_b_bar (TestI *self)
205 {
206     GValue args[1] = { { 0, } };
207
208     g_print("TestB::bar called.  Chaining up.\n");
209
210     g_value_init (&args[0], TEST_TYPE_A);
211     g_value_set_object (&args[0], self);
212
213     g_assert (g_signal_get_invocation_hint (self)->signal_id == bar_signal_id);
214     g_signal_chain_from_overridden (args, NULL);
215
216     g_value_unset (&args[0]);
217 }
218
219 static void
220 test_b_class_init (TestBClass *class)
221 {
222     g_signal_override_class_closure (foo_signal_id,
223                                      TEST_TYPE_B,
224                                      g_cclosure_new (G_CALLBACK (test_b_foo),
225                                                      NULL, NULL));
226     g_signal_override_class_closure (bar_signal_id,
227                                      TEST_TYPE_B,
228                                      g_cclosure_new (G_CALLBACK (test_b_bar),
229                                                      NULL, NULL));
230 }
231
232 static GType
233 test_b_get_type (void)
234 {
235     static GType type = 0;
236   
237     if (!type) {
238         static const GTypeInfo type_info = {
239             sizeof(TestBClass),
240             (GBaseInitFunc) NULL,
241             (GBaseFinalizeFunc) NULL,
242             (GClassInitFunc) test_b_class_init,
243             NULL, /* class_finalize */
244             NULL, /* class_data */
245             sizeof(TestBClass),
246             0, /* n_preallocs */
247             (GInstanceInitFunc) NULL,
248         };
249
250         type = g_type_register_static (TEST_TYPE_A, "TestB",
251                                        &type_info, 0);
252     }
253   
254   return type;
255 }
256
257
258 #define TEST_TYPE_C (test_c_get_type())
259 #define TEST_C(object) (G_TYPE_CHECK_INSTANCE_CAST((object), TEST_TYPE_C, TestC))
260 #define TEST_C_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TEST_TYPE_C, TestCClass))
261 #define TEST_IS_C(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), TEST_TYPE_C))
262 #define TEST_IS_C_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), TEST_TYPE_C))
263 #define TEST_C_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), TEST_TYPE_C, TestCClass))
264
265 typedef struct _TestC TestC;
266 typedef struct _TestCClass TestCClass;
267
268 struct _TestC {
269     TestB parent;
270 };
271 struct _TestCClass {
272     TestBClass parent_class;
273 };
274
275 static void
276 test_c_foo (TestA *self)
277 {
278     GValue args[1] = { { 0, } };
279
280     g_print("TestC::foo called.  Chaining up.\n");
281
282     g_value_init (&args[0], TEST_TYPE_A);
283     g_value_set_object (&args[0], self);
284
285     g_assert (g_signal_get_invocation_hint (self)->signal_id == foo_signal_id);
286     g_signal_chain_from_overridden (args, NULL);
287
288     g_value_unset (&args[0]);
289 }
290
291 static void
292 test_c_bar (TestI *self)
293 {
294     GValue args[1] = { { 0, } };
295
296     g_print("TestC::bar called.  Chaining up.\n");
297
298     g_value_init (&args[0], TEST_TYPE_A);
299     g_value_set_object (&args[0], self);
300
301     g_assert (g_signal_get_invocation_hint (self)->signal_id == bar_signal_id);
302     g_signal_chain_from_overridden (args, NULL);
303
304     g_value_unset (&args[0]);
305 }
306
307 static void
308 test_c_class_init (TestBClass *class)
309 {
310     g_signal_override_class_closure (foo_signal_id,
311                                      TEST_TYPE_C,
312                                      g_cclosure_new (G_CALLBACK (test_c_foo),
313                                                      NULL, NULL));
314     g_signal_override_class_closure (bar_signal_id,
315                                      TEST_TYPE_C,
316                                      g_cclosure_new (G_CALLBACK (test_c_bar),
317                                                      NULL, NULL));
318 }
319
320 static GType
321 test_c_get_type (void)
322 {
323     static GType type = 0;
324   
325     if (!type) {
326         static const GTypeInfo type_info = {
327             sizeof(TestCClass),
328             (GBaseInitFunc) NULL,
329             (GBaseFinalizeFunc) NULL,
330             (GClassInitFunc) test_c_class_init,
331             NULL, /* class_finalize */
332             NULL, /* class_data */
333             sizeof(TestCClass),
334             0, /* n_preallocs */
335             (GInstanceInitFunc) NULL,
336         };
337
338         type = g_type_register_static (TEST_TYPE_B, "TestC",
339                                        &type_info, 0);
340     }
341   
342   return type;
343 }
344
345
346 int
347 main (int argc, char **argv)
348 {
349     GObject *self;
350
351     g_type_init();
352
353     self = g_object_new(TEST_TYPE_A, NULL);
354     g_print("*** emiting foo on a TestA instance (expect chain A->I)\n");
355     g_signal_emit(self, foo_signal_id, 0);
356     g_print("*** emiting bar on a TestA instance\n");
357     g_signal_emit(self, bar_signal_id, 0);
358     g_object_unref(self);
359
360     g_print("\n");
361
362     self = g_object_new(TEST_TYPE_B, NULL);
363     g_print("*** emiting foo on a TestB instance (expect chain B->A->I)\n");
364     g_signal_emit(self, foo_signal_id, 0);
365     g_print("*** emiting bar on a TestB instance (expect chain B->A)\n");
366     g_signal_emit(self, bar_signal_id, 0);
367     g_object_unref(self);
368
369     g_print("\n");
370
371     self = g_object_new(TEST_TYPE_C, NULL);
372     g_print("*** emiting foo on a TestC instance (expect chain C->B->A->I)\n");
373     g_signal_emit(self, foo_signal_id, 0);
374     g_print("*** emiting bar on a TestC instance (expect chain C->B->A)\n");
375     g_signal_emit(self, bar_signal_id, 0);
376     g_object_unref(self);
377
378     return 0;
379 }