]> Pileus Git - ~andy/gtk/blob - gtk/gtkcontainer.c
Initial revision
[~andy/gtk] / gtk / gtkcontainer.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the Free
16  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17  */
18 #include <string.h>
19 #include "gtkcontainer.h"
20 #include "gtksignal.h"
21
22
23 enum {
24   ADD,
25   REMOVE,
26   NEED_RESIZE,
27   FOREACH,
28   FOCUS,
29   LAST_SIGNAL
30 };
31
32
33 typedef void (*GtkContainerSignal1) (GtkObject *object,
34                                      gpointer   arg1,
35                                      gpointer   data);
36 typedef void (*GtkContainerSignal2) (GtkObject *object,
37                                      gpointer   arg1,
38                                      gpointer   arg2,
39                                      gpointer   data);
40 typedef gint (*GtkContainerSignal3) (GtkObject *object,
41                                      gint       arg1,
42                                      gpointer   data);
43 typedef gint (*GtkContainerSignal4) (GtkObject *object,
44                                      gpointer   data);
45
46
47 static void gtk_container_marshal_signal_1 (GtkObject      *object,
48                                             GtkSignalFunc   func,
49                                             gpointer        func_data,
50                                             GtkArg         *args);
51 static void gtk_container_marshal_signal_2 (GtkObject      *object,
52                                             GtkSignalFunc   func,
53                                             gpointer        func_data,
54                                             GtkArg         *args);
55 static void gtk_container_marshal_signal_3 (GtkObject      *object,
56                                             GtkSignalFunc   func,
57                                             gpointer        func_data,
58                                             GtkArg         *args);
59 static void gtk_container_marshal_signal_4 (GtkObject      *object,
60                                             GtkSignalFunc   func,
61                                             gpointer        func_data,
62                                             GtkArg         *args);
63
64
65 static void gtk_container_class_init        (GtkContainerClass *klass);
66 static void gtk_container_init              (GtkContainer      *container);
67 static void gtk_container_arg               (GtkContainer      *container,
68                                              GtkArg            *arg);
69 static gint gtk_real_container_need_resize  (GtkContainer      *container);
70 static gint gtk_real_container_focus        (GtkContainer      *container,
71                                              GtkDirectionType   direction);
72 static gint gtk_container_focus_tab         (GtkContainer      *container,
73                                              GList             *children,
74                                              GtkDirectionType   direction);
75 static gint gtk_container_focus_up_down     (GtkContainer      *container,
76                                              GList             *children,
77                                              GtkDirectionType   direction);
78 static gint gtk_container_focus_left_right  (GtkContainer      *container,
79                                              GList             *children,
80                                              GtkDirectionType   direction);
81 static gint gtk_container_focus_move        (GtkContainer      *container,
82                                              GList             *children,
83                                              GtkDirectionType   direction);
84 static void gtk_container_children_callback (GtkWidget         *widget,
85                                              gpointer           client_data);
86
87
88 static gint container_signals[LAST_SIGNAL] = { 0 };
89
90
91 guint
92 gtk_container_get_type ()
93 {
94   static guint container_type = 0;
95
96   if (!container_type)
97     {
98       GtkTypeInfo container_info =
99       {
100         "GtkContainer",
101         sizeof (GtkContainer),
102         sizeof (GtkContainerClass),
103         (GtkClassInitFunc) gtk_container_class_init,
104         (GtkObjectInitFunc) gtk_container_init,
105         (GtkArgFunc) gtk_container_arg,
106       };
107
108       container_type = gtk_type_unique (gtk_widget_get_type (), &container_info);
109     }
110
111   return container_type;
112 }
113
114 static void
115 gtk_container_class_init (GtkContainerClass *class)
116 {
117   GtkObjectClass *object_class;
118   GtkWidgetClass *widget_class;
119
120   object_class = (GtkObjectClass*) class;
121   widget_class = (GtkWidgetClass*) class;
122
123   gtk_object_add_arg_type ("GtkContainer::border_width", GTK_TYPE_LONG);
124   gtk_object_add_arg_type ("GtkContainer::auto_resize", GTK_TYPE_BOOL);
125   gtk_object_add_arg_type ("GtkContainer::block_resize", GTK_TYPE_BOOL);
126   gtk_object_add_arg_type ("GtkContainer::child", GTK_TYPE_WIDGET);
127
128   container_signals[ADD] =
129     gtk_signal_new ("add",
130                     GTK_RUN_FIRST,
131                     object_class->type,
132                     GTK_SIGNAL_OFFSET (GtkContainerClass, add),
133                     gtk_container_marshal_signal_1,
134                     GTK_TYPE_NONE, 1,
135                     GTK_TYPE_WIDGET);
136   container_signals[REMOVE] =
137     gtk_signal_new ("remove",
138                     GTK_RUN_FIRST,
139                     object_class->type,
140                     GTK_SIGNAL_OFFSET (GtkContainerClass, remove),
141                     gtk_container_marshal_signal_1,
142                     GTK_TYPE_NONE, 1,
143                     GTK_TYPE_WIDGET);
144   container_signals[NEED_RESIZE] =
145     gtk_signal_new ("need_resize",
146                     GTK_RUN_FIRST,
147                     object_class->type,
148                     GTK_SIGNAL_OFFSET (GtkContainerClass, need_resize),
149                     gtk_container_marshal_signal_4,
150                     GTK_TYPE_BOOL, 0,
151                     GTK_TYPE_WIDGET);
152   container_signals[FOREACH] =
153     gtk_signal_new ("foreach",
154                     GTK_RUN_FIRST,
155                     object_class->type,
156                     GTK_SIGNAL_OFFSET (GtkContainerClass, foreach),
157                     gtk_container_marshal_signal_2,
158                     GTK_TYPE_NONE, 1,
159                     GTK_TYPE_C_CALLBACK);
160   container_signals[FOCUS] =
161     gtk_signal_new ("focus",
162                     GTK_RUN_FIRST,
163                     object_class->type,
164                     GTK_SIGNAL_OFFSET (GtkContainerClass, focus),
165                     gtk_container_marshal_signal_3,
166                     GTK_TYPE_DIRECTION_TYPE, 1,
167                     GTK_TYPE_DIRECTION_TYPE);
168
169   gtk_object_class_add_signals (object_class, container_signals, LAST_SIGNAL);
170
171   class->need_resize = gtk_real_container_need_resize;
172   class->focus = gtk_real_container_focus;
173 }
174
175 static void
176 gtk_container_init (GtkContainer *container)
177 {
178   container->focus_child = NULL;
179   container->border_width = 0;
180   container->auto_resize = TRUE;
181   container->need_resize = FALSE;
182   container->block_resize = FALSE;
183 }
184
185 static void
186 gtk_container_arg (GtkContainer *container,
187                    GtkArg       *arg)
188 {
189   if (strcmp (arg->name, "border_width") == 0)
190     {
191       gtk_container_border_width (container, GTK_VALUE_LONG (*arg));
192     }
193   else if (strcmp (arg->name, "auto_resize") == 0)
194     {
195       if (GTK_VALUE_BOOL (*arg))
196         gtk_container_enable_resize (container);
197       else
198         gtk_container_disable_resize (container);
199     }
200   else if (strcmp (arg->name, "block_resize") == 0)
201     {
202       if (GTK_VALUE_BOOL (*arg))
203         gtk_container_block_resize (container);
204       else
205         gtk_container_unblock_resize (container);
206     }
207   else if (strcmp (arg->name, "child") == 0)
208     {
209       gtk_container_add (container, GTK_WIDGET (GTK_VALUE_OBJECT (*arg)));
210     }
211 }
212
213 void
214 gtk_container_border_width (GtkContainer *container,
215                             gint          border_width)
216 {
217   g_return_if_fail (container != NULL);
218   g_return_if_fail (GTK_IS_CONTAINER (container));
219
220   if (container->border_width != border_width)
221     {
222       container->border_width = border_width;
223
224       if (container->widget.parent && GTK_WIDGET_VISIBLE (container))
225         gtk_container_need_resize (GTK_CONTAINER (container->widget.parent));
226     }
227 }
228
229 void
230 gtk_container_add (GtkContainer *container,
231                    GtkWidget    *widget)
232 {
233   gtk_signal_emit (GTK_OBJECT (container), container_signals[ADD], widget);
234 }
235
236 void
237 gtk_container_remove (GtkContainer *container,
238                       GtkWidget    *widget)
239 {
240   g_return_if_fail (container != NULL);
241   g_return_if_fail (GTK_IS_CONTAINER (container));
242
243   if (container->focus_child == widget)
244     container->focus_child = NULL;
245
246   gtk_signal_emit (GTK_OBJECT (container), container_signals[REMOVE], widget);
247 }
248
249 void
250 gtk_container_disable_resize (GtkContainer *container)
251 {
252   g_return_if_fail (container != NULL);
253   g_return_if_fail (GTK_IS_CONTAINER (container));
254
255   container->auto_resize = FALSE;
256 }
257
258 void
259 gtk_container_enable_resize (GtkContainer *container)
260 {
261   g_return_if_fail (container != NULL);
262   g_return_if_fail (GTK_IS_CONTAINER (container));
263
264   container->auto_resize = TRUE;
265   if (container->need_resize)
266     {
267       container->need_resize = FALSE;
268       gtk_widget_queue_resize (GTK_WIDGET (container));
269     }
270 }
271
272 void
273 gtk_container_block_resize (GtkContainer *container)
274 {
275   g_return_if_fail (container != NULL);
276   g_return_if_fail (GTK_IS_CONTAINER (container));
277
278   container->block_resize = TRUE;
279 }
280
281 void
282 gtk_container_unblock_resize (GtkContainer *container)
283 {
284   g_return_if_fail (container != NULL);
285   g_return_if_fail (GTK_IS_CONTAINER (container));
286
287   container->block_resize = FALSE;
288 }
289
290 gint
291 gtk_container_need_resize (GtkContainer *container)
292 {
293   gint return_val;
294
295   g_return_val_if_fail (container != NULL, FALSE);
296   g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
297
298   return_val = FALSE;
299
300   if (!container->block_resize)
301     {
302       if (container->auto_resize)
303         gtk_signal_emit (GTK_OBJECT (container),
304                          container_signals[NEED_RESIZE],
305                          &return_val);
306       else
307         container->need_resize = TRUE;
308     }
309
310   return return_val;
311 }
312
313 void
314 gtk_container_foreach (GtkContainer *container,
315                        GtkCallback   callback,
316                        gpointer      callback_data)
317 {
318   gtk_signal_emit (GTK_OBJECT (container),
319                    container_signals[FOREACH],
320                    callback, callback_data);
321 }
322
323 gint
324 gtk_container_focus (GtkContainer     *container,
325                      GtkDirectionType  direction)
326 {
327   gint return_val;
328
329   gtk_signal_emit (GTK_OBJECT (container),
330                    container_signals[FOCUS],
331                    direction, &return_val);
332
333   return return_val;
334 }
335
336 GList*
337 gtk_container_children (GtkContainer *container)
338 {
339   GList *children;
340
341   children = NULL;
342
343   gtk_container_foreach (container,
344                          gtk_container_children_callback,
345                          &children);
346
347   return g_list_reverse (children);
348 }
349
350
351 static void
352 gtk_container_marshal_signal_1 (GtkObject      *object,
353                                 GtkSignalFunc   func,
354                                 gpointer        func_data,
355                                 GtkArg         *args)
356 {
357   GtkContainerSignal1 rfunc;
358
359   rfunc = (GtkContainerSignal1) func;
360
361   (* rfunc) (object, GTK_VALUE_OBJECT (args[0]), func_data);
362 }
363
364 static void
365 gtk_container_marshal_signal_2 (GtkObject      *object,
366                                 GtkSignalFunc   func,
367                                 gpointer        func_data,
368                                 GtkArg         *args)
369 {
370   GtkContainerSignal2 rfunc;
371
372   rfunc = (GtkContainerSignal2) func;
373
374   (* rfunc) (object,
375              GTK_VALUE_C_CALLBACK(args[0]).func,
376              GTK_VALUE_C_CALLBACK(args[0]).func_data,
377              func_data);
378 }
379
380 static void
381 gtk_container_marshal_signal_3 (GtkObject      *object,
382                                 GtkSignalFunc   func,
383                                 gpointer        func_data,
384                                 GtkArg         *args)
385 {
386   GtkContainerSignal3 rfunc;
387   gint *return_val;
388
389   rfunc = (GtkContainerSignal3) func;
390   return_val = GTK_RETLOC_ENUM (args[1]);
391
392   *return_val = (* rfunc) (object, GTK_VALUE_ENUM(args[0]), func_data);
393 }
394
395 static void
396 gtk_container_marshal_signal_4 (GtkObject      *object,
397                                 GtkSignalFunc   func,
398                                 gpointer        func_data,
399                                 GtkArg         *args)
400 {
401   GtkContainerSignal4 rfunc;
402   gint *return_val;
403
404   rfunc = (GtkContainerSignal4) func;
405   return_val = GTK_RETLOC_BOOL (args[0]);
406
407   *return_val = (* rfunc) (object, func_data);
408 }
409
410 static gint
411 gtk_real_container_need_resize (GtkContainer *container)
412 {
413   g_return_val_if_fail (container != NULL, FALSE);
414   g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
415
416   if (GTK_WIDGET_VISIBLE (container) && container->widget.parent)
417     return gtk_container_need_resize (GTK_CONTAINER (container->widget.parent));
418
419   return FALSE;
420 }
421
422 static gint
423 gtk_real_container_focus (GtkContainer     *container,
424                           GtkDirectionType  direction)
425 {
426   GList *children;
427   GList *tmp_list;
428   GList *tmp_list2;
429   gint return_val;
430
431   g_return_val_if_fail (container != NULL, FALSE);
432   g_return_val_if_fail (GTK_IS_CONTAINER (container), FALSE);
433
434   /* Fail if the container is insensitive
435    */
436   if (!GTK_WIDGET_SENSITIVE (container))
437     return FALSE;
438
439   return_val = FALSE;
440
441   if (GTK_WIDGET_CAN_FOCUS (container))
442     {
443       gtk_widget_grab_focus (GTK_WIDGET (container));
444       return_val = TRUE;
445     }
446   else
447     {
448       /* Get a list of the containers children
449        */
450       children = gtk_container_children (container);
451
452       if (children)
453         {
454           /* Remove any children which are insensitive
455            */
456           tmp_list = children;
457           while (tmp_list)
458             {
459               if (!GTK_WIDGET_SENSITIVE (tmp_list->data))
460                 {
461                   tmp_list2 = tmp_list;
462                   tmp_list = tmp_list->next;
463
464                   children = g_list_remove_link (children, tmp_list2);
465                   g_list_free_1 (tmp_list2);
466                 }
467               else
468                 tmp_list = tmp_list->next;
469             }
470
471           switch (direction)
472             {
473             case GTK_DIR_TAB_FORWARD:
474             case GTK_DIR_TAB_BACKWARD:
475               return_val = gtk_container_focus_tab (container, children, direction);
476               break;
477             case GTK_DIR_UP:
478             case GTK_DIR_DOWN:
479               return_val = gtk_container_focus_up_down (container, children, direction);
480               break;
481             case GTK_DIR_LEFT:
482             case GTK_DIR_RIGHT:
483               return_val = gtk_container_focus_left_right (container, children, direction);
484               break;
485             }
486
487           g_list_free (children);
488         }
489     }
490
491   return return_val;
492 }
493
494 static gint
495 gtk_container_focus_tab (GtkContainer     *container,
496                          GList            *children,
497                          GtkDirectionType  direction)
498 {
499   GtkWidget *child;
500   GtkWidget *child2;
501   GList *tmp_list;
502   gint length;
503   gint i, j;
504
505   length = g_list_length (children);
506
507   /* sort the children in the y direction */
508   for (i = 1; i < length; i++)
509     {
510       j = i;
511       tmp_list = g_list_nth (children, j);
512       child = tmp_list->data;
513
514       while (j > 0)
515         {
516           child2 = tmp_list->prev->data;
517           if (child->allocation.y < child2->allocation.y)
518             {
519               tmp_list->data = tmp_list->prev->data;
520               tmp_list = tmp_list->prev;
521               j--;
522             }
523           else
524             break;
525         }
526
527       tmp_list->data = child;
528     }
529
530   /* sort the children in the x direction while
531    *  maintaining the y direction sort.
532    */
533   for (i = 1; i < length; i++)
534     {
535       j = i;
536       tmp_list = g_list_nth (children, j);
537       child = tmp_list->data;
538
539       while (j > 0)
540         {
541           child2 = tmp_list->prev->data;
542           if ((child->allocation.x < child2->allocation.x) &&
543               (child->allocation.y >= child2->allocation.y))
544             {
545               tmp_list->data = tmp_list->prev->data;
546               tmp_list = tmp_list->prev;
547               j--;
548             }
549           else
550             break;
551         }
552
553       tmp_list->data = child;
554     }
555
556   /* if we are going backwards then reverse the order
557    *  of the children.
558    */
559   if (direction == GTK_DIR_TAB_BACKWARD)
560     children = g_list_reverse (children);
561
562   return gtk_container_focus_move (container, children, direction);
563 }
564
565 static gint
566 gtk_container_focus_up_down (GtkContainer     *container,
567                              GList            *children,
568                              GtkDirectionType  direction)
569 {
570   GtkWidget *child;
571   GtkWidget *child2;
572   GList *tmp_list;
573   gint dist1, dist2;
574   gint focus_x;
575   gint focus_width;
576   gint length;
577   gint i, j;
578
579   /* return failure if there isn't a focus child */
580   if (container->focus_child)
581     {
582       focus_width = container->focus_child->allocation.width / 2;
583       focus_x = container->focus_child->allocation.x + focus_width;
584     }
585   else
586     {
587       focus_width = GTK_WIDGET (container)->allocation.width;
588       if (GTK_WIDGET_NO_WINDOW (container))
589         focus_x = GTK_WIDGET (container)->allocation.x;
590       else
591         focus_x = 0;
592     }
593
594   length = g_list_length (children);
595
596   /* sort the children in the y direction */
597   for (i = 1; i < length; i++)
598     {
599       j = i;
600       tmp_list = g_list_nth (children, j);
601       child = tmp_list->data;
602
603       while (j > 0)
604         {
605           child2 = tmp_list->prev->data;
606           if (child->allocation.y < child2->allocation.y)
607             {
608               tmp_list->data = tmp_list->prev->data;
609               tmp_list = tmp_list->prev;
610               j--;
611             }
612           else
613             break;
614         }
615
616       tmp_list->data = child;
617     }
618
619   /* sort the children in distance in the x direction
620    *  in distance from the current focus child while maintaining the
621    *  sort in the y direction
622    */
623   for (i = 1; i < length; i++)
624     {
625       j = i;
626       tmp_list = g_list_nth (children, j);
627       child = tmp_list->data;
628       dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x;
629
630       while (j > 0)
631         {
632           child2 = tmp_list->prev->data;
633           dist2 = (child2->allocation.x + child2->allocation.width / 2) - focus_x;
634
635           if ((dist1 < dist2) &&
636               (child->allocation.y >= child2->allocation.y))
637             {
638               tmp_list->data = tmp_list->prev->data;
639               tmp_list = tmp_list->prev;
640               j--;
641             }
642           else
643             break;
644         }
645
646       tmp_list->data = child;
647     }
648
649   /* go and invalidate any widget which is too
650    *  far from the focus widget.
651    */
652   if (!container->focus_child &&
653       (direction == GTK_DIR_UP))
654     focus_x += focus_width;
655
656   tmp_list = children;
657   while (tmp_list)
658     {
659       child = tmp_list->data;
660
661       dist1 = (child->allocation.x + child->allocation.width / 2) - focus_x;
662       if (((direction == GTK_DIR_DOWN) && (dist1 < 0)) ||
663           ((direction == GTK_DIR_UP) && (dist1 > 0)))
664         tmp_list->data = NULL;
665
666       tmp_list = tmp_list->next;
667     }
668
669   if (direction == GTK_DIR_UP)
670     children = g_list_reverse (children);
671
672   return gtk_container_focus_move (container, children, direction);
673 }
674
675 static gint
676 gtk_container_focus_left_right (GtkContainer     *container,
677                                 GList            *children,
678                                 GtkDirectionType  direction)
679 {
680   GtkWidget *child;
681   GtkWidget *child2;
682   GList *tmp_list;
683   gint dist1, dist2;
684   gint focus_y;
685   gint focus_height;
686   gint length;
687   gint i, j;
688
689   /* return failure if there isn't a focus child */
690   if (container->focus_child)
691     {
692       focus_height = container->focus_child->allocation.height / 2;
693       focus_y = container->focus_child->allocation.y + focus_height;
694     }
695   else
696     {
697       focus_height = GTK_WIDGET (container)->allocation.height;
698       if (GTK_WIDGET_NO_WINDOW (container))
699         focus_y = GTK_WIDGET (container)->allocation.y;
700       else
701         focus_y = 0;
702     }
703
704   length = g_list_length (children);
705
706   /* sort the children in the x direction */
707   for (i = 1; i < length; i++)
708     {
709       j = i;
710       tmp_list = g_list_nth (children, j);
711       child = tmp_list->data;
712
713       while (j > 0)
714         {
715           child2 = tmp_list->prev->data;
716           if (child->allocation.x < child2->allocation.x)
717             {
718               tmp_list->data = tmp_list->prev->data;
719               tmp_list = tmp_list->prev;
720               j--;
721             }
722           else
723             break;
724         }
725
726       tmp_list->data = child;
727     }
728
729   /* sort the children in distance in the y direction
730    *  in distance from the current focus child while maintaining the
731    *  sort in the x direction
732    */
733   for (i = 1; i < length; i++)
734     {
735       j = i;
736       tmp_list = g_list_nth (children, j);
737       child = tmp_list->data;
738       dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y;
739
740       while (j > 0)
741         {
742           child2 = tmp_list->prev->data;
743           dist2 = (child2->allocation.y + child2->allocation.height / 2) - focus_y;
744
745           if ((dist1 < dist2) &&
746               (child->allocation.x >= child2->allocation.x))
747             {
748               tmp_list->data = tmp_list->prev->data;
749               tmp_list = tmp_list->prev;
750               j--;
751             }
752           else
753             break;
754         }
755
756       tmp_list->data = child;
757     }
758
759   /* go and invalidate any widget which is too
760    *  far from the focus widget.
761    */
762   if (!container->focus_child &&
763       (direction == GTK_DIR_LEFT))
764     focus_y += focus_height;
765
766   tmp_list = children;
767   while (tmp_list)
768     {
769       child = tmp_list->data;
770
771       dist1 = (child->allocation.y + child->allocation.height / 2) - focus_y;
772       if (((direction == GTK_DIR_RIGHT) && (dist1 < 0)) ||
773           ((direction == GTK_DIR_LEFT) && (dist1 > 0)))
774         tmp_list->data = NULL;
775
776       tmp_list = tmp_list->next;
777     }
778
779   if (direction == GTK_DIR_LEFT)
780     children = g_list_reverse (children);
781
782   return gtk_container_focus_move (container, children, direction);
783 }
784
785 static gint
786 gtk_container_focus_move (GtkContainer     *container,
787                           GList            *children,
788                           GtkDirectionType  direction)
789 {
790   GtkWidget *focus_child;
791   GtkWidget *child;
792
793   focus_child = container->focus_child;
794   container->focus_child = NULL;
795
796   while (children)
797     {
798       child = children->data;
799       children = children->next;
800
801       if (!child)
802         continue;
803
804       if (focus_child)
805         {
806           if (focus_child == child)
807             {
808               focus_child = NULL;
809
810               if (GTK_WIDGET_VISIBLE (child) &&
811                   GTK_IS_CONTAINER (child) &&
812                   !GTK_WIDGET_HAS_FOCUS (child))
813                 if (gtk_container_focus (GTK_CONTAINER (child), direction))
814                   return TRUE;
815             }
816         }
817       else if (GTK_WIDGET_VISIBLE (child))
818         {
819           if (GTK_WIDGET_CAN_FOCUS (child))
820             {
821               gtk_widget_grab_focus (child);
822               return TRUE;
823             }
824           else if (GTK_IS_CONTAINER (child))
825             {
826               if (gtk_container_focus (GTK_CONTAINER (child), direction))
827                 return TRUE;
828             }
829         }
830     }
831
832   return FALSE;
833 }
834
835
836 static void
837 gtk_container_children_callback (GtkWidget *widget,
838                                  gpointer   client_data)
839 {
840   GList **children;
841
842   children = (GList**) client_data;
843   *children = g_list_prepend (*children, widget);
844 }