1 #include <clutter/clutter.h>
2 
3 #include "tests/clutter-test-utils.h"
4 
5 static void
actor_add_child(void)6 actor_add_child (void)
7 {
8   ClutterActor *actor = clutter_actor_new ();
9   ClutterActor *iter;
10 
11   g_object_ref_sink (actor);
12   g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
13 
14   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
15                                                 "name", "foo",
16                                                 NULL));
17   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
18                                                 "name", "bar",
19                                                 NULL));
20   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
21                                                 "name", "baz",
22                                                 NULL));
23 
24   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3);
25 
26   iter = clutter_actor_get_first_child (actor);
27   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
28 
29   iter = clutter_actor_get_next_sibling (iter);
30   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
31 
32   iter = clutter_actor_get_next_sibling (iter);
33   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
34   g_assert (iter == clutter_actor_get_last_child (actor));
35   g_assert (clutter_actor_get_next_sibling (iter) == NULL);
36 
37   iter = clutter_actor_get_last_child (actor);
38   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
39 
40   iter = clutter_actor_get_previous_sibling (iter);
41   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
42 
43   iter = clutter_actor_get_previous_sibling (iter);
44   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
45   g_assert (iter == clutter_actor_get_first_child (actor));
46   g_assert (clutter_actor_get_previous_sibling (iter) == NULL);
47 
48   clutter_actor_destroy (actor);
49   g_assert (actor == NULL);
50 }
51 
52 static void
actor_insert_child(void)53 actor_insert_child (void)
54 {
55   ClutterActor *actor = clutter_actor_new ();
56   ClutterActor *iter;
57 
58   g_object_ref_sink (actor);
59   g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
60 
61   clutter_actor_insert_child_at_index (actor,
62                                        g_object_new (CLUTTER_TYPE_ACTOR,
63                                                      "name", "foo",
64                                                      NULL),
65                                        0);
66 
67   iter = clutter_actor_get_first_child (actor);
68   g_assert (iter != NULL);
69   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
70   g_assert (iter == clutter_actor_get_child_at_index (actor, 0));
71 
72   clutter_actor_insert_child_below (actor,
73                                     g_object_new (CLUTTER_TYPE_ACTOR,
74                                                   "name", "bar",
75                                                   NULL),
76                                     iter);
77 
78   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 2);
79 
80   iter = clutter_actor_get_first_child (actor);
81   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
82   iter = clutter_actor_get_next_sibling (iter);
83   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
84   g_assert (iter == clutter_actor_get_child_at_index (actor, 1));
85 
86   iter = clutter_actor_get_first_child (actor);
87   clutter_actor_insert_child_above (actor,
88                                     g_object_new (CLUTTER_TYPE_ACTOR,
89                                                   "name", "baz",
90                                                   NULL),
91                                     iter);
92 
93   iter = clutter_actor_get_last_child (actor);
94   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
95 
96   iter = clutter_actor_get_previous_sibling (iter);
97   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
98 
99   iter = clutter_actor_get_previous_sibling (iter);
100   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
101 
102   clutter_actor_remove_all_children (actor);
103 
104   clutter_actor_insert_child_at_index (actor,
105                                        g_object_new (CLUTTER_TYPE_ACTOR,
106                                                      "name", "1",
107                                                      NULL),
108                                        0);
109   iter = clutter_actor_get_child_at_index (actor, 0);
110   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "1");
111   g_assert (clutter_actor_get_first_child (actor) == iter);
112   g_assert (clutter_actor_get_last_child (actor) == iter);
113 
114   clutter_actor_insert_child_at_index (actor,
115                                        g_object_new (CLUTTER_TYPE_ACTOR,
116                                                      "name", "2",
117                                                      NULL),
118                                        0);
119   iter = clutter_actor_get_child_at_index (actor, 0);
120   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "2");
121   g_assert (clutter_actor_get_first_child (actor) == iter);
122   iter = clutter_actor_get_child_at_index (actor, 1);
123   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "1");
124   g_assert (clutter_actor_get_last_child (actor) == iter);
125 
126   clutter_actor_insert_child_at_index (actor,
127                                        g_object_new (CLUTTER_TYPE_ACTOR,
128                                                      "name", "3",
129                                                      NULL),
130                                        -1);
131   iter = clutter_actor_get_child_at_index (actor, 2);
132   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "3");
133   g_assert (clutter_actor_get_last_child (actor) == iter);
134 
135   clutter_actor_destroy (actor);
136   g_assert (actor == NULL);
137 }
138 
139 static void
actor_remove_child(void)140 actor_remove_child (void)
141 {
142   ClutterActor *actor = clutter_actor_new ();
143   ClutterActor *iter;
144 
145   g_object_ref_sink (actor);
146   g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
147 
148   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
149                                                 "name", "foo",
150                                                 NULL));
151   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
152                                                 "name", "bar",
153                                                 NULL));
154 
155   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 2);
156 
157   g_assert (clutter_actor_get_first_child (actor) != clutter_actor_get_last_child (actor));
158 
159   iter = clutter_actor_get_first_child (actor);
160   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
161 
162   iter = clutter_actor_get_last_child (actor);
163   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
164 
165   clutter_actor_remove_child (actor, clutter_actor_get_first_child (actor));
166 
167   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1);
168 
169   iter = clutter_actor_get_first_child (actor);
170   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
171   g_assert (clutter_actor_get_first_child (actor) == clutter_actor_get_last_child (actor));
172 
173   clutter_actor_remove_child (actor, clutter_actor_get_first_child (actor));
174 
175   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 0);
176   g_assert (clutter_actor_get_first_child (actor) == NULL);
177   g_assert (clutter_actor_get_last_child (actor) == NULL);
178 
179   clutter_actor_destroy (actor);
180   g_assert (actor == NULL);
181 }
182 
183 static void
actor_raise_child(void)184 actor_raise_child (void)
185 {
186   ClutterActor *actor = clutter_actor_new ();
187   ClutterActor *iter;
188   gboolean show_on_set_parent;
189 
190   g_object_ref_sink (actor);
191   g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
192 
193   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
194                                                 "name", "foo",
195                                                 "visible", FALSE,
196                                                 NULL));
197   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
198                                                 "name", "bar",
199                                                 "visible", FALSE,
200                                                 NULL));
201   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
202                                                 "name", "baz",
203                                                 "visible", FALSE,
204                                                 NULL));
205 
206   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3);
207 
208   iter = clutter_actor_get_child_at_index (actor, 1);
209   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
210 
211   clutter_actor_set_child_above_sibling (actor, iter,
212                                          clutter_actor_get_child_at_index (actor, 2));
213 
214   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)),
215                    ==,
216                    "foo");
217   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)),
218                    ==,
219                    "baz");
220   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)),
221                    ==,
222                    "bar");
223   g_assert (!clutter_actor_is_visible (iter));
224   g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL);
225   g_assert (!show_on_set_parent);
226 
227   iter = clutter_actor_get_child_at_index (actor, 0);
228   clutter_actor_set_child_above_sibling (actor, iter, NULL);
229   g_object_add_weak_pointer (G_OBJECT (iter), (gpointer *) &iter);
230 
231   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)),
232                    ==,
233                    "baz");
234   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)),
235                    ==,
236                    "bar");
237   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)),
238                    ==,
239                    "foo");
240   g_assert (!clutter_actor_is_visible (iter));
241   g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL);
242   g_assert (!show_on_set_parent);
243 
244   clutter_actor_destroy (actor);
245   g_assert (actor == NULL);
246   g_assert (iter == NULL);
247 }
248 
249 static void
actor_lower_child(void)250 actor_lower_child (void)
251 {
252   ClutterActor *actor = clutter_actor_new ();
253   ClutterActor *iter;
254   gboolean show_on_set_parent;
255 
256   g_object_ref_sink (actor);
257   g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
258 
259   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
260                                                 "name", "foo",
261                                                 "visible", FALSE,
262                                                 NULL));
263   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
264                                                 "name", "bar",
265                                                 "visible", FALSE,
266                                                 NULL));
267   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
268                                                 "name", "baz",
269                                                 "visible", FALSE,
270                                                 NULL));
271 
272   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3);
273 
274   iter = clutter_actor_get_child_at_index (actor, 1);
275   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
276 
277   clutter_actor_set_child_below_sibling (actor, iter,
278                                          clutter_actor_get_child_at_index (actor, 0));
279 
280   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)),
281                    ==,
282                    "bar");
283   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)),
284                    ==,
285                    "foo");
286   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)),
287                    ==,
288                    "baz");
289   g_assert (!clutter_actor_is_visible (iter));
290   g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL);
291   g_assert (!show_on_set_parent);
292 
293   iter = clutter_actor_get_child_at_index (actor, 2);
294   clutter_actor_set_child_below_sibling (actor, iter, NULL);
295 
296   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 0)),
297                    ==,
298                    "baz");
299   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 1)),
300                    ==,
301                    "bar");
302   g_assert_cmpstr (clutter_actor_get_name (clutter_actor_get_child_at_index (actor, 2)),
303                    ==,
304                    "foo");
305   g_assert (!clutter_actor_is_visible (iter));
306   g_object_get (iter, "show-on-set-parent", &show_on_set_parent, NULL);
307   g_assert (!show_on_set_parent);
308 
309   clutter_actor_destroy (actor);
310   g_assert (actor == NULL);
311 }
312 
313 static void
actor_replace_child(void)314 actor_replace_child (void)
315 {
316   ClutterActor *actor = clutter_actor_new ();
317   ClutterActor *iter;
318 
319   g_object_ref_sink (actor);
320   g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
321 
322   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
323                                                 "name", "foo",
324                                                 NULL));
325   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
326                                                 "name", "bar",
327                                                 NULL));
328 
329   iter = clutter_actor_get_child_at_index (actor, 0);
330   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
331 
332   clutter_actor_replace_child (actor, iter,
333                                g_object_new (CLUTTER_TYPE_ACTOR,
334                                              "name", "baz",
335                                              NULL));
336 
337   iter = clutter_actor_get_child_at_index (actor, 0);
338   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
339 
340   iter = clutter_actor_get_child_at_index (actor, 1);
341   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
342 
343   clutter_actor_replace_child (actor, iter,
344                                g_object_new (CLUTTER_TYPE_ACTOR,
345                                              "name", "qux",
346                                              NULL));
347 
348   iter = clutter_actor_get_child_at_index (actor, 0);
349   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
350 
351   iter = clutter_actor_get_child_at_index (actor, 1);
352   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "qux");
353 
354   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
355                                                 "name", "foo",
356                                                 NULL));
357 
358   clutter_actor_replace_child (actor, iter,
359                                g_object_new (CLUTTER_TYPE_ACTOR,
360                                              "name", "bar",
361                                              NULL));
362 
363   iter = clutter_actor_get_last_child (actor);
364   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "foo");
365   iter = clutter_actor_get_previous_sibling (iter);
366   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "bar");
367   iter = clutter_actor_get_previous_sibling (iter);
368   g_assert_cmpstr (clutter_actor_get_name (iter), ==, "baz");
369 
370   clutter_actor_destroy (actor);
371   g_assert (actor == NULL);
372 }
373 
374 static void
actor_remove_all(void)375 actor_remove_all (void)
376 {
377   ClutterActor *actor = clutter_actor_new ();
378 
379   g_object_ref_sink (actor);
380   g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
381 
382   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
383                                                 "name", "foo",
384                                                 NULL));
385   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
386                                                 "name", "bar",
387                                                 NULL));
388   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
389                                                 "name", "baz",
390                                                 NULL));
391 
392   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 3);
393 
394   clutter_actor_remove_all_children (actor);
395 
396   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 0);
397 
398   clutter_actor_destroy (actor);
399   g_assert (actor == NULL);
400 }
401 
402 static void
actor_added(ClutterContainer * container,ClutterActor * child,gpointer data)403 actor_added (ClutterContainer *container,
404              ClutterActor     *child,
405              gpointer          data)
406 {
407   ClutterActor *actor = CLUTTER_ACTOR (container);
408   int *counter = data;
409   ClutterActor *old_child;
410 
411   if (!g_test_quiet ())
412     g_print ("Adding actor '%s'\n", clutter_actor_get_name (child));
413 
414   old_child = clutter_actor_get_child_at_index (actor, 0);
415   if (old_child != child)
416     clutter_actor_remove_child (actor, old_child);
417 
418   *counter += 1;
419 }
420 
421 static void
actor_removed(ClutterContainer * container,ClutterActor * child,gpointer data)422 actor_removed (ClutterContainer *container,
423                ClutterActor     *child,
424                gpointer          data)
425 {
426   int *counter = data;
427 
428   if (!g_test_quiet ())
429     g_print ("Removing actor '%s'\n", clutter_actor_get_name (child));
430 
431   *counter += 1;
432 }
433 
434 static void
actor_container_signals(void)435 actor_container_signals (void)
436 {
437   ClutterActor *actor = clutter_actor_new ();
438   int add_count, remove_count;
439 
440   g_object_ref_sink (actor);
441   g_object_add_weak_pointer (G_OBJECT (actor), (gpointer *) &actor);
442 
443   add_count = remove_count = 0;
444   g_signal_connect (actor,
445                     "actor-added", G_CALLBACK (actor_added),
446                     &add_count);
447   g_signal_connect (actor,
448                     "actor-removed", G_CALLBACK (actor_removed),
449                     &remove_count);
450 
451   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
452                                                 "name", "foo",
453                                                 NULL));
454 
455   g_assert_cmpint (add_count, ==, 1);
456   g_assert_cmpint (remove_count, ==, 0);
457   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1);
458 
459   clutter_actor_add_child (actor, g_object_new (CLUTTER_TYPE_ACTOR,
460                                                 "name", "bar",
461                                                 NULL));
462 
463   g_assert_cmpint (add_count, ==, 2);
464   g_assert_cmpint (remove_count, ==, 1);
465   g_assert_cmpint (clutter_actor_get_n_children (actor), ==, 1);
466 
467   g_signal_handlers_disconnect_by_func (actor, G_CALLBACK (actor_added),
468                                         &add_count);
469   g_signal_handlers_disconnect_by_func (actor, G_CALLBACK (actor_removed),
470                                         &remove_count);
471 
472   clutter_actor_destroy (actor);
473   g_assert (actor == NULL);
474 }
475 
476 static void
actor_contains(void)477 actor_contains (void)
478 {
479   /* This build up the following tree:
480    *
481    *              a
482    *          ╱   │   ╲
483    *         ╱    │    ╲
484    *        b     c     d
485    *       ╱ ╲   ╱ ╲   ╱ ╲
486    *      e   f g   h i   j
487    */
488   struct {
489     ClutterActor *actor_a, *actor_b, *actor_c, *actor_d, *actor_e;
490     ClutterActor *actor_f, *actor_g, *actor_h, *actor_i, *actor_j;
491   } d;
492   int x, y;
493   ClutterActor **actor_array = &d.actor_a;
494 
495   /* Matrix of expected results */
496   static const gboolean expected_results[] =
497     {         /* a, b, c, d, e, f, g, h, i, j */
498       /* a */    1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
499       /* b */    0, 1, 0, 0, 1, 1, 0, 0, 0, 0,
500       /* c */    0, 0, 1, 0, 0, 0, 1, 1, 0, 0,
501       /* d */    0, 0, 0, 1, 0, 0, 0, 0, 1, 1,
502       /* e */    0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
503       /* f */    0, 0, 0, 0, 0, 1, 0, 0, 0, 0,
504       /* g */    0, 0, 0, 0, 0, 0, 1, 0, 0, 0,
505       /* h */    0, 0, 0, 0, 0, 0, 0, 1, 0, 0,
506       /* i */    0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
507       /* j */    0, 0, 0, 0, 0, 0, 0, 0, 0, 1
508     };
509 
510   d.actor_a = clutter_actor_new ();
511   d.actor_b = clutter_actor_new ();
512   d.actor_c = clutter_actor_new ();
513   d.actor_d = clutter_actor_new ();
514   d.actor_e = clutter_actor_new ();
515   d.actor_f = clutter_actor_new ();
516   d.actor_g = clutter_actor_new ();
517   d.actor_h = clutter_actor_new ();
518   d.actor_i = clutter_actor_new ();
519   d.actor_j = clutter_actor_new ();
520 
521   clutter_actor_add_child (d.actor_a, d.actor_b);
522   clutter_actor_add_child (d.actor_a, d.actor_c);
523   clutter_actor_add_child (d.actor_a, d.actor_d);
524 
525   clutter_actor_add_child (d.actor_b, d.actor_e);
526   clutter_actor_add_child (d.actor_b, d.actor_f);
527 
528   clutter_actor_add_child (d.actor_c, d.actor_g);
529   clutter_actor_add_child (d.actor_c, d.actor_h);
530 
531   clutter_actor_add_child (d.actor_d, d.actor_i);
532   clutter_actor_add_child (d.actor_d, d.actor_j);
533 
534   for (y = 0; y < 10; y++)
535     for (x = 0; x < 10; x++)
536       g_assert_cmpint (clutter_actor_contains (actor_array[x],
537                                                actor_array[y]),
538                        ==,
539                        expected_results[x * 10 + y]);
540 }
541 
542 CLUTTER_TEST_SUITE (
543   CLUTTER_TEST_UNIT ("/actor/graph/add-child", actor_add_child)
544   CLUTTER_TEST_UNIT ("/actor/graph/insert-child", actor_insert_child)
545   CLUTTER_TEST_UNIT ("/actor/graph/remove-child", actor_remove_child)
546   CLUTTER_TEST_UNIT ("/actor/graph/raise-child", actor_raise_child)
547   CLUTTER_TEST_UNIT ("/actor/graph/lower-child", actor_lower_child)
548   CLUTTER_TEST_UNIT ("/actor/graph/replace-child", actor_replace_child)
549   CLUTTER_TEST_UNIT ("/actor/graph/remove-all", actor_remove_all)
550   CLUTTER_TEST_UNIT ("/actor/graph/container-signals", actor_container_signals)
551   CLUTTER_TEST_UNIT ("/actor/graph/contains", actor_contains)
552 )
553