]> Pileus Git - ~andy/gtk/blob - gtk/gtklayout.c
Add gdk_rgb_find_color() to get a pixel value using GdkRGB functionality
[~andy/gtk] / gtk / gtklayout.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
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  *
19  * GtkLayout: Widget for scrolling of arbitrary-sized areas.
20  *
21  * Copyright Owen Taylor, 1998
22  */
23
24 /*
25  * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
26  * file for a list of people on the GTK+ Team.  See the ChangeLog
27  * files for a list of changes.  These files are distributed with
28  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
29  */
30
31 #include "gdkconfig.h"
32
33 #include "gtklayout.h"
34 #include "gtksignal.h"
35 #include "gtkprivate.h"
36
37 typedef struct _GtkLayoutChild   GtkLayoutChild;
38
39 struct _GtkLayoutChild {
40   GtkWidget *widget;
41   gint x;
42   gint y;
43 };
44
45 static void     gtk_layout_class_init         (GtkLayoutClass *class);
46 static void     gtk_layout_init               (GtkLayout      *layout);
47
48 static void     gtk_layout_finalize           (GObject        *object);
49 static void     gtk_layout_realize            (GtkWidget      *widget);
50 static void     gtk_layout_unrealize          (GtkWidget      *widget);
51 static void     gtk_layout_map                (GtkWidget      *widget);
52 static void     gtk_layout_size_request       (GtkWidget      *widget,
53                                                GtkRequisition *requisition);
54 static void     gtk_layout_size_allocate      (GtkWidget      *widget,
55                                                GtkAllocation  *allocation);
56 static void     gtk_layout_draw               (GtkWidget      *widget, 
57                                                GdkRectangle   *area);
58 static gint     gtk_layout_expose             (GtkWidget      *widget, 
59                                                GdkEventExpose *event);
60
61 static void     gtk_layout_remove             (GtkContainer *container, 
62                                                GtkWidget    *widget);
63 static void     gtk_layout_forall             (GtkContainer *container,
64                                                gboolean      include_internals,
65                                                GtkCallback   callback,
66                                                gpointer      callback_data);
67 static void     gtk_layout_set_adjustments    (GtkLayout     *layout,
68                                                GtkAdjustment *hadj,
69                                                GtkAdjustment *vadj);
70
71 static void     gtk_layout_allocate_child     (GtkLayout      *layout,
72                                                GtkLayoutChild *child);
73
74
75 static void     gtk_layout_adjustment_changed (GtkAdjustment  *adjustment,
76                                                GtkLayout      *layout);
77
78 static GtkWidgetClass *parent_class = NULL;
79
80 /* Public interface
81  */
82   
83 GtkWidget*    
84 gtk_layout_new (GtkAdjustment *hadjustment,
85                 GtkAdjustment *vadjustment)
86 {
87   GtkLayout *layout;
88
89   layout = gtk_type_new (GTK_TYPE_LAYOUT);
90
91   gtk_layout_set_adjustments (layout, hadjustment, vadjustment);
92
93   return GTK_WIDGET (layout);
94 }
95
96 GtkAdjustment* 
97 gtk_layout_get_hadjustment (GtkLayout     *layout)
98 {
99   g_return_val_if_fail (layout != NULL, NULL);
100   g_return_val_if_fail (GTK_IS_LAYOUT (layout), NULL);
101
102   return layout->hadjustment;
103 }
104 GtkAdjustment* 
105 gtk_layout_get_vadjustment (GtkLayout     *layout)
106 {
107   g_return_val_if_fail (layout != NULL, NULL);
108   g_return_val_if_fail (GTK_IS_LAYOUT (layout), NULL);
109
110   return layout->vadjustment;
111 }
112
113 static void           
114 gtk_layout_set_adjustments (GtkLayout     *layout,
115                             GtkAdjustment *hadj,
116                             GtkAdjustment *vadj)
117 {
118   gboolean need_adjust = FALSE;
119
120   g_return_if_fail (layout != NULL);
121   g_return_if_fail (GTK_IS_LAYOUT (layout));
122
123   if (hadj)
124     g_return_if_fail (GTK_IS_ADJUSTMENT (hadj));
125   else
126     hadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
127   if (vadj)
128     g_return_if_fail (GTK_IS_ADJUSTMENT (vadj));
129   else
130     vadj = GTK_ADJUSTMENT (gtk_adjustment_new (0.0, 0.0, 0.0, 0.0, 0.0, 0.0));
131   
132   if (layout->hadjustment && (layout->hadjustment != hadj))
133     {
134       gtk_signal_disconnect_by_data (GTK_OBJECT (layout->hadjustment), layout);
135       gtk_object_unref (GTK_OBJECT (layout->hadjustment));
136     }
137   
138   if (layout->vadjustment && (layout->vadjustment != vadj))
139     {
140       gtk_signal_disconnect_by_data (GTK_OBJECT (layout->vadjustment), layout);
141       gtk_object_unref (GTK_OBJECT (layout->vadjustment));
142     }
143   
144   if (layout->hadjustment != hadj)
145     {
146       layout->hadjustment = hadj;
147       gtk_object_ref (GTK_OBJECT (layout->hadjustment));
148       gtk_object_sink (GTK_OBJECT (layout->hadjustment));
149       
150       gtk_signal_connect (GTK_OBJECT (layout->hadjustment), "value_changed",
151                           (GtkSignalFunc) gtk_layout_adjustment_changed,
152                           layout);
153       need_adjust = TRUE;
154     }
155   
156   if (layout->vadjustment != vadj)
157     {
158       layout->vadjustment = vadj;
159       gtk_object_ref (GTK_OBJECT (layout->vadjustment));
160       gtk_object_sink (GTK_OBJECT (layout->vadjustment));
161       
162       gtk_signal_connect (GTK_OBJECT (layout->vadjustment), "value_changed",
163                           (GtkSignalFunc) gtk_layout_adjustment_changed,
164                           layout);
165       need_adjust = TRUE;
166     }
167
168   if (need_adjust)
169     gtk_layout_adjustment_changed (NULL, layout);
170 }
171
172 static void
173 gtk_layout_finalize (GObject *object)
174 {
175   GtkLayout *layout = GTK_LAYOUT (object);
176
177   gtk_object_unref (GTK_OBJECT (layout->hadjustment));
178   gtk_object_unref (GTK_OBJECT (layout->vadjustment));
179
180   G_OBJECT_CLASS (parent_class)->finalize (object);
181 }
182
183 void           
184 gtk_layout_set_hadjustment (GtkLayout     *layout,
185                             GtkAdjustment *adjustment)
186 {
187   g_return_if_fail (layout != NULL);
188   g_return_if_fail (GTK_IS_LAYOUT (layout));
189
190   gtk_layout_set_adjustments (layout, adjustment, layout->vadjustment);
191 }
192  
193
194 void           
195 gtk_layout_set_vadjustment (GtkLayout     *layout,
196                             GtkAdjustment *adjustment)
197 {
198   g_return_if_fail (layout != NULL);
199   g_return_if_fail (GTK_IS_LAYOUT (layout));
200   
201   gtk_layout_set_adjustments (layout, layout->hadjustment, adjustment);
202 }
203
204
205 void           
206 gtk_layout_put (GtkLayout     *layout, 
207                 GtkWidget     *child_widget, 
208                 gint           x, 
209                 gint           y)
210 {
211   GtkLayoutChild *child;
212
213   g_return_if_fail (layout != NULL);
214   g_return_if_fail (GTK_IS_LAYOUT (layout));
215   g_return_if_fail (child_widget != NULL);
216   g_return_if_fail (GTK_IS_WIDGET (child_widget));
217   
218   child = g_new (GtkLayoutChild, 1);
219
220   child->widget = child_widget;
221   child->x = x;
222   child->y = y;
223
224   layout->children = g_list_append (layout->children, child);
225   
226   gtk_widget_set_parent (child_widget, GTK_WIDGET (layout));
227   if (GTK_WIDGET_REALIZED (layout))
228     gtk_widget_set_parent_window (child->widget, layout->bin_window);
229
230   if (GTK_WIDGET_REALIZED (layout))
231     gtk_widget_realize (child_widget);
232     
233   if (GTK_WIDGET_VISIBLE (layout) && GTK_WIDGET_VISIBLE (child_widget))
234     {
235       if (GTK_WIDGET_MAPPED (layout))
236         gtk_widget_map (child_widget);
237
238       gtk_widget_queue_resize (child_widget);
239     }
240 }
241
242 void           
243 gtk_layout_move (GtkLayout     *layout, 
244                  GtkWidget     *child_widget, 
245                  gint           x, 
246                  gint           y)
247 {
248   GList *tmp_list;
249   GtkLayoutChild *child;
250   
251   g_return_if_fail (layout != NULL);
252   g_return_if_fail (GTK_IS_LAYOUT (layout));
253
254   tmp_list = layout->children;
255   while (tmp_list)
256     {
257       child = tmp_list->data;
258       tmp_list = tmp_list->next;
259
260       if (child->widget == child_widget)
261         {
262           child->x = x;
263           child->y = y;
264
265           if (GTK_WIDGET_VISIBLE (child_widget) && GTK_WIDGET_VISIBLE (layout))
266             gtk_widget_queue_resize (child_widget);
267
268           return;
269         }
270     }
271 }
272
273 static void
274 gtk_layout_set_adjustment_upper (GtkAdjustment *adj, gfloat upper)
275 {
276   if (upper != adj->upper)
277     {
278       gfloat min = MAX (0., upper - adj->page_size);
279       gboolean value_changed = FALSE;
280       
281       adj->upper = upper;
282       
283       if (adj->value > min)
284         {
285           adj->value = min;
286           value_changed = TRUE;
287         }
288       
289       gtk_signal_emit_by_name (GTK_OBJECT (adj), "changed");
290       if (value_changed)
291         gtk_signal_emit_by_name (GTK_OBJECT (adj), "value_changed");
292     }
293 }
294
295 void
296 gtk_layout_set_size (GtkLayout     *layout, 
297                      guint          width,
298                      guint          height)
299 {
300   GtkWidget *widget;
301   
302   g_return_if_fail (layout != NULL);
303   g_return_if_fail (GTK_IS_LAYOUT (layout));
304
305   widget = GTK_WIDGET (layout);
306   
307   layout->width = width;
308   layout->height = height;
309
310   gtk_layout_set_adjustment_upper (layout->hadjustment, layout->width);
311   gtk_layout_set_adjustment_upper (layout->vadjustment, layout->height);
312
313   if (GTK_WIDGET_REALIZED (layout))
314     {
315       width = MAX (width, widget->allocation.width);
316       height = MAX (height, widget->allocation.height);
317       gdk_window_resize (layout->bin_window, width, height);
318     }
319 }
320
321 void
322 gtk_layout_freeze (GtkLayout *layout)
323 {
324   g_return_if_fail (layout != NULL);
325   g_return_if_fail (GTK_IS_LAYOUT (layout));
326
327   layout->freeze_count++;
328 }
329
330 void
331 gtk_layout_thaw (GtkLayout *layout)
332 {
333   g_return_if_fail (layout != NULL);
334   g_return_if_fail (GTK_IS_LAYOUT (layout));
335
336   if (layout->freeze_count)
337     if (!(--layout->freeze_count))
338       gtk_widget_draw (GTK_WIDGET (layout), NULL);
339 }
340
341 /* Basic Object handling procedures
342  */
343 GtkType
344 gtk_layout_get_type (void)
345 {
346   static GtkType layout_type = 0;
347
348   if (!layout_type)
349     {
350       static const GTypeInfo layout_info =
351       {
352         sizeof (GtkLayoutClass),
353         NULL,           /* base_init */
354         NULL,           /* base_finalize */
355         (GClassInitFunc) gtk_layout_class_init,
356         NULL,           /* class_finalize */
357         NULL,           /* class_data */
358         sizeof (GtkLayout),
359         16,             /* n_preallocs */
360         (GInstanceInitFunc) gtk_layout_init,
361       };
362
363       layout_type = g_type_register_static (GTK_TYPE_CONTAINER, "GtkLayout", &layout_info);
364     }
365
366   return layout_type;
367 }
368
369 static void
370 gtk_layout_class_init (GtkLayoutClass *class)
371 {
372   GObjectClass *gobject_class = G_OBJECT_CLASS (class);
373   GtkObjectClass *object_class;
374   GtkWidgetClass *widget_class;
375   GtkContainerClass *container_class;
376
377   object_class = (GtkObjectClass*) class;
378   widget_class = (GtkWidgetClass*) class;
379   container_class = (GtkContainerClass*) class;
380
381   parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
382
383   gobject_class->finalize = gtk_layout_finalize;
384
385   widget_class->realize = gtk_layout_realize;
386   widget_class->unrealize = gtk_layout_unrealize;
387   widget_class->map = gtk_layout_map;
388   widget_class->size_request = gtk_layout_size_request;
389   widget_class->size_allocate = gtk_layout_size_allocate;
390   widget_class->draw = gtk_layout_draw;
391   widget_class->expose_event = gtk_layout_expose;
392
393   container_class->remove = gtk_layout_remove;
394   container_class->forall = gtk_layout_forall;
395
396   class->set_scroll_adjustments = gtk_layout_set_adjustments;
397
398   widget_class->set_scroll_adjustments_signal =
399     gtk_signal_new ("set_scroll_adjustments",
400                     GTK_RUN_LAST,
401                     GTK_CLASS_TYPE (object_class),
402                     GTK_SIGNAL_OFFSET (GtkLayoutClass, set_scroll_adjustments),
403                     gtk_marshal_NONE__POINTER_POINTER,
404                     GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
405 }
406
407 static void
408 gtk_layout_init (GtkLayout *layout)
409 {
410   layout->children = NULL;
411
412   layout->width = 100;
413   layout->height = 100;
414
415   layout->hadjustment = NULL;
416   layout->vadjustment = NULL;
417
418   layout->bin_window = NULL;
419
420   layout->scroll_x = 0;
421   layout->scroll_y = 0;
422   layout->visibility = GDK_VISIBILITY_PARTIAL;
423
424   layout->freeze_count = 0;
425 }
426
427 /* Widget methods
428  */
429
430 static void 
431 gtk_layout_realize (GtkWidget *widget)
432 {
433   GList *tmp_list;
434   GtkLayout *layout;
435   GdkWindowAttr attributes;
436   gint attributes_mask;
437
438   g_return_if_fail (widget != NULL);
439   g_return_if_fail (GTK_IS_LAYOUT (widget));
440
441   layout = GTK_LAYOUT (widget);
442   GTK_WIDGET_SET_FLAGS (layout, GTK_REALIZED);
443
444   attributes.window_type = GDK_WINDOW_CHILD;
445   attributes.x = widget->allocation.x;
446   attributes.y = widget->allocation.y;
447   attributes.width = widget->allocation.width;
448   attributes.height = widget->allocation.height;
449   attributes.wclass = GDK_INPUT_OUTPUT;
450   attributes.visual = gtk_widget_get_visual (widget);
451   attributes.colormap = gtk_widget_get_colormap (widget);
452   attributes.event_mask = GDK_VISIBILITY_NOTIFY_MASK;
453
454   attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
455
456   widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
457                                    &attributes, attributes_mask);
458   gdk_window_set_user_data (widget->window, widget);
459
460   attributes.x = 0;
461   attributes.y = 0;
462   attributes.width = MAX (layout->width, widget->allocation.width);
463   attributes.height = MAX (layout->height, widget->allocation.height);
464   attributes.event_mask = GDK_EXPOSURE_MASK | GDK_SCROLL_MASK | 
465                           gtk_widget_get_events (widget);
466
467   layout->bin_window = gdk_window_new (widget->window,
468                                         &attributes, attributes_mask);
469   gdk_window_set_user_data (layout->bin_window, widget);
470
471   widget->style = gtk_style_attach (widget->style, widget->window);
472   gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
473   gtk_style_set_background (widget->style, layout->bin_window, GTK_STATE_NORMAL);
474
475   tmp_list = layout->children;
476   while (tmp_list)
477     {
478       GtkLayoutChild *child = tmp_list->data;
479       tmp_list = tmp_list->next;
480
481       gtk_widget_set_parent_window (child->widget, layout->bin_window);
482     }
483 }
484
485 static void 
486 gtk_layout_map (GtkWidget *widget)
487 {
488   GList *tmp_list;
489   GtkLayout *layout;
490
491   g_return_if_fail (widget != NULL);
492   g_return_if_fail (GTK_IS_LAYOUT (widget));
493
494   layout = GTK_LAYOUT (widget);
495
496   GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
497
498   tmp_list = layout->children;
499   while (tmp_list)
500     {
501       GtkLayoutChild *child = tmp_list->data;
502       tmp_list = tmp_list->next;
503
504       if (GTK_WIDGET_VISIBLE (child->widget))
505         {
506           if (!GTK_WIDGET_MAPPED (child->widget))
507             gtk_widget_map (child->widget);
508         }
509     }
510
511   gdk_window_show (layout->bin_window);
512   gdk_window_show (widget->window);
513 }
514
515 static void 
516 gtk_layout_unrealize (GtkWidget *widget)
517 {
518   GtkLayout *layout;
519
520   g_return_if_fail (widget != NULL);
521   g_return_if_fail (GTK_IS_LAYOUT (widget));
522
523   layout = GTK_LAYOUT (widget);
524
525   gdk_window_set_user_data (layout->bin_window, NULL);
526   gdk_window_destroy (layout->bin_window);
527   layout->bin_window = NULL;
528
529   if (GTK_WIDGET_CLASS (parent_class)->unrealize)
530     (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
531 }
532
533 static void     
534 gtk_layout_size_request (GtkWidget     *widget,
535                          GtkRequisition *requisition)
536 {
537   GList *tmp_list;
538   GtkLayout *layout;
539
540   g_return_if_fail (widget != NULL);
541   g_return_if_fail (GTK_IS_LAYOUT (widget));
542
543   layout = GTK_LAYOUT (widget);
544
545   requisition->width = 0;
546   requisition->height = 0;
547
548   tmp_list = layout->children;
549
550   while (tmp_list)
551     {
552       GtkLayoutChild *child = tmp_list->data;
553       GtkRequisition child_requisition;
554       
555       tmp_list = tmp_list->next;
556
557       gtk_widget_size_request (child->widget, &child_requisition);
558     }
559 }
560
561 static void     
562 gtk_layout_size_allocate (GtkWidget     *widget,
563                           GtkAllocation *allocation)
564 {
565   GList *tmp_list;
566   GtkLayout *layout;
567
568   g_return_if_fail (widget != NULL);
569   g_return_if_fail (GTK_IS_LAYOUT (widget));
570
571   widget->allocation = *allocation;
572   
573   layout = GTK_LAYOUT (widget);
574
575   tmp_list = layout->children;
576
577   while (tmp_list)
578     {
579       GtkLayoutChild *child = tmp_list->data;
580       tmp_list = tmp_list->next;
581
582       gtk_layout_allocate_child (layout, child);
583     }
584
585   if (GTK_WIDGET_REALIZED (widget))
586     {
587       gdk_window_move_resize (widget->window,
588                               allocation->x, allocation->y,
589                               allocation->width, allocation->height);
590
591       gdk_window_resize (layout->bin_window,
592                          MAX (layout->width, allocation->width),
593                          MAX (layout->height, allocation->height));
594     }
595
596   layout->hadjustment->page_size = allocation->width;
597   layout->hadjustment->page_increment = allocation->width / 2;
598   layout->hadjustment->lower = 0;
599   layout->hadjustment->upper = MAX (allocation->width, layout->width);
600   gtk_signal_emit_by_name (GTK_OBJECT (layout->hadjustment), "changed");
601
602   layout->vadjustment->page_size = allocation->height;
603   layout->vadjustment->page_increment = allocation->height / 2;
604   layout->vadjustment->lower = 0;
605   layout->vadjustment->upper = MAX (allocation->height, layout->height);
606   gtk_signal_emit_by_name (GTK_OBJECT (layout->vadjustment), "changed");
607 }
608
609 static void 
610 gtk_layout_draw (GtkWidget *widget, GdkRectangle *area)
611 {
612   GList *tmp_list;
613   GtkLayout *layout;
614   GdkRectangle child_area;
615
616   g_return_if_fail (widget != NULL);
617   g_return_if_fail (GTK_IS_LAYOUT (widget));
618
619   layout = GTK_LAYOUT (widget);
620
621   /* We don't have any way of telling themes about this properly,
622    * so we just assume a background pixmap
623    */
624   if (!GTK_WIDGET_APP_PAINTABLE (widget))
625     gdk_window_clear_area (layout->bin_window,
626                            area->x, area->y, area->width, area->height);
627   
628   tmp_list = layout->children;
629   while (tmp_list)
630     {
631       GtkLayoutChild *child = tmp_list->data;
632       tmp_list = tmp_list->next;
633
634       if (gtk_widget_intersect (child->widget, area, &child_area))
635         gtk_widget_draw (child->widget, &child_area);
636     }
637 }
638
639 static gint 
640 gtk_layout_expose (GtkWidget *widget, GdkEventExpose *event)
641 {
642   GList *tmp_list;
643   GtkLayout *layout;
644   GdkEventExpose child_event;
645
646   g_return_val_if_fail (widget != NULL, FALSE);
647   g_return_val_if_fail (GTK_IS_LAYOUT (widget), FALSE);
648
649   layout = GTK_LAYOUT (widget);
650
651   if (event->window != layout->bin_window)
652     return FALSE;
653   
654   tmp_list = layout->children;
655   while (tmp_list)
656     {
657       GtkLayoutChild *child = tmp_list->data;
658       tmp_list = tmp_list->next;
659
660       child_event = *event;
661       if (GTK_WIDGET_DRAWABLE (child->widget) &&
662           GTK_WIDGET_NO_WINDOW (child->widget) &&
663           gtk_widget_intersect (child->widget, &event->area, &child_event.area))
664         gtk_widget_event (child->widget, (GdkEvent*) &child_event);
665     }
666
667   return FALSE;
668 }
669
670 /* Container method
671  */
672 static void
673 gtk_layout_remove (GtkContainer *container, 
674                    GtkWidget    *widget)
675 {
676   GList *tmp_list;
677   GtkLayout *layout;
678   GtkLayoutChild *child = NULL;
679   
680   g_return_if_fail (container != NULL);
681   g_return_if_fail (GTK_IS_LAYOUT (container));
682   
683   layout = GTK_LAYOUT (container);
684
685   tmp_list = layout->children;
686   while (tmp_list)
687     {
688       child = tmp_list->data;
689       if (child->widget == widget)
690         break;
691       tmp_list = tmp_list->next;
692     }
693
694   if (tmp_list)
695     {
696       gtk_widget_unparent (widget);
697
698       layout->children = g_list_remove_link (layout->children, tmp_list);
699       g_list_free_1 (tmp_list);
700       g_free (child);
701     }
702 }
703
704 static void
705 gtk_layout_forall (GtkContainer *container,
706                    gboolean      include_internals,
707                    GtkCallback   callback,
708                    gpointer      callback_data)
709 {
710   GtkLayout *layout;
711   GtkLayoutChild *child;
712   GList *tmp_list;
713
714   g_return_if_fail (container != NULL);
715   g_return_if_fail (GTK_IS_LAYOUT (container));
716   g_return_if_fail (callback != NULL);
717
718   layout = GTK_LAYOUT (container);
719
720   tmp_list = layout->children;
721   while (tmp_list)
722     {
723       child = tmp_list->data;
724       tmp_list = tmp_list->next;
725
726       (* callback) (child->widget, callback_data);
727     }
728 }
729
730 /* Operations on children
731  */
732
733 static void
734 gtk_layout_allocate_child (GtkLayout      *layout,
735                            GtkLayoutChild *child)
736 {
737   GtkAllocation allocation;
738   GtkRequisition requisition;
739
740   allocation.x = child->x - layout->xoffset;
741   allocation.y = child->y - layout->yoffset;
742   gtk_widget_get_child_requisition (child->widget, &requisition);
743   allocation.width = requisition.width;
744   allocation.height = requisition.height;
745   
746   gtk_widget_size_allocate (child->widget, &allocation);
747 }
748
749 /* Callbacks */
750
751 static void
752 gtk_layout_adjustment_changed (GtkAdjustment *adjustment,
753                                GtkLayout     *layout)
754 {
755   GtkWidget *widget;
756
757   widget = GTK_WIDGET (layout);
758
759   if (layout->freeze_count)
760     return;
761
762   if (GTK_WIDGET_REALIZED (layout))
763     {
764       gdk_window_move (layout->bin_window,
765                        - layout->hadjustment->value,
766                        - layout->vadjustment->value);
767       
768       gdk_window_process_updates (layout->bin_window, TRUE);
769     }
770 }