]> Pileus Git - ~andy/gtk/blob - gtk/gtkoverlay.c
stylecontext: Do invalidation on first resize container
[~andy/gtk] / gtk / gtkoverlay.c
1 /*
2  * gtkoverlay.c
3  * This file is part of gtk
4  *
5  * Copyright (C) 2011 - Ignacio Casal Quinteiro, Mike Krüger
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with this library. If not, see <http://www.gnu.org/licenses/>.
19  */
20
21 #include "config.h"
22
23 #include "gtkoverlay.h"
24 #include "gtkbuildable.h"
25 #include "gtkscrolledwindow.h"
26 #include "gtkmarshalers.h"
27
28 #include "gtkprivate.h"
29 #include "gtkintl.h"
30
31 /**
32  * SECTION:gtkoverlay
33  * @short_description: A container which overlays widgets on top of each other
34  * @title: GtkOverlay
35  *
36  * GtkOverlay is a container which contains a single main child, on top
37  * of which it can place <firstterm>overlay</firstterm> widgets. The
38  * position of each overlay widget is determined by its #GtkWidget:halign
39  * and #GtkWidget:valign properties. E.g. a widget with both alignments
40  * set to %GTK_ALIGN_START will be placed at the top left corner of the
41  * main widget, whereas an overlay with halign set to %GTK_ALIGN_CENTER
42  * and valign set to %GTK_ALIGN_END will be placed a the bottom edge of
43  * the main widget, horizontally centered. The position can be adjusted
44  * by setting the margin properties of the child to non-zero values.
45  *
46  * More complicated placement of overlays is possible by connecting
47  * to the #GtkOverlay::get-child-position signal.
48  *
49  * <refsect2 id="GtkOverlay-BUILDER-UI">
50  * <title>GtkOverlay as GtkBuildable</title>
51  * <para>
52  * The GtkOverlay implementation of the GtkBuildable interface
53  * supports placing a child as an overlay by specifying "overlay" as
54  * the "type" attribute of a <tag class="starttag">child</tag> element.
55  * </para>
56  * </refsect2>
57  */
58
59 struct _GtkOverlayPrivate
60 {
61   GSList *children;
62 };
63
64 typedef struct _GtkOverlayChild GtkOverlayChild;
65
66 struct _GtkOverlayChild
67 {
68   GtkWidget *widget;
69   GdkWindow *window;
70 };
71
72 enum {
73   GET_CHILD_POSITION,
74   LAST_SIGNAL
75 };
76
77 static guint signals[LAST_SIGNAL] = { 0 };
78
79 static void gtk_overlay_buildable_init (GtkBuildableIface *iface);
80
81 G_DEFINE_TYPE_WITH_CODE (GtkOverlay, gtk_overlay, GTK_TYPE_BIN,
82                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
83                                                 gtk_overlay_buildable_init))
84
85 static GdkWindow *
86 gtk_overlay_create_child_window (GtkOverlay *overlay,
87                                  GtkWidget  *child)
88 {
89   GtkWidget *widget = GTK_WIDGET (overlay);
90   GtkAllocation allocation;
91   GdkWindow *window;
92   GdkWindowAttr attributes;
93   gint attributes_mask;
94
95   gtk_widget_get_allocation (child, &allocation);
96
97   attributes.window_type = GDK_WINDOW_CHILD;
98   attributes.wclass = GDK_INPUT_OUTPUT;
99   attributes.width = allocation.width;
100   attributes.height = allocation.height;
101   attributes.x = allocation.x;
102   attributes.y = allocation.y;
103   attributes_mask = GDK_WA_X | GDK_WA_Y;
104   attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK;
105
106   window = gdk_window_new (gtk_widget_get_window (widget),
107                            &attributes, attributes_mask);
108   gtk_widget_register_window (widget, window);
109   gtk_style_context_set_background (gtk_widget_get_style_context (widget), window);
110
111   gtk_widget_set_parent_window (child, window);
112
113   return window;
114 }
115
116 static GtkAlign
117 effective_align (GtkAlign         align,
118                  GtkTextDirection direction)
119 {
120   switch (align)
121     {
122     case GTK_ALIGN_START:
123       return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_END : GTK_ALIGN_START;
124     case GTK_ALIGN_END:
125       return direction == GTK_TEXT_DIR_RTL ? GTK_ALIGN_START : GTK_ALIGN_END;
126     default:
127       return align;
128     }
129 }
130
131 static void
132 gtk_overlay_get_main_widget_allocation (GtkOverlay *overlay,
133                                         GtkAllocation *main_alloc_out)
134 {
135   GtkWidget *main_widget;
136   GtkAllocation main_alloc;
137
138   main_widget = gtk_bin_get_child (GTK_BIN (overlay));
139
140   /* special-case scrolled windows */
141   if (GTK_IS_SCROLLED_WINDOW (main_widget))
142     {
143       GtkWidget *grandchild;
144       gint x, y;
145       gboolean res;
146
147       grandchild = gtk_bin_get_child (GTK_BIN (main_widget));
148       res = gtk_widget_translate_coordinates (grandchild, main_widget, 0, 0, &x, &y);
149
150       if (res)
151         {
152           main_alloc.x = x;
153           main_alloc.y = y;
154         }
155       else
156         {
157           main_alloc.x = 0;
158           main_alloc.y = 0;
159         }
160
161       main_alloc.width = gtk_widget_get_allocated_width (grandchild);
162       main_alloc.height = gtk_widget_get_allocated_height (grandchild);
163     }
164   else
165     {
166       main_alloc.x = 0;
167       main_alloc.y = 0;
168       main_alloc.width = gtk_widget_get_allocated_width (main_widget);
169       main_alloc.height = gtk_widget_get_allocated_height (main_widget);
170     }
171
172   if (main_alloc_out)
173     *main_alloc_out = main_alloc;
174 }
175
176 static void
177 gtk_overlay_child_update_style_classes (GtkOverlay *overlay,
178                                         GtkWidget *child,
179                                         GtkAllocation *child_allocation)
180 {
181   GtkAllocation overlay_allocation, main_allocation;
182   GtkAlign valign, halign;
183   gboolean is_left, is_right, is_top, is_bottom;
184   gboolean has_left, has_right, has_top, has_bottom;
185   GtkStyleContext *context;
186
187   context = gtk_widget_get_style_context (child);
188   has_left = gtk_style_context_has_class (context, GTK_STYLE_CLASS_LEFT);
189   has_right = gtk_style_context_has_class (context, GTK_STYLE_CLASS_RIGHT);
190   has_top = gtk_style_context_has_class (context, GTK_STYLE_CLASS_TOP);
191   has_bottom = gtk_style_context_has_class (context, GTK_STYLE_CLASS_BOTTOM);
192
193   is_left = is_right = is_top = is_bottom = FALSE;
194
195   gtk_overlay_get_main_widget_allocation (overlay, &main_allocation);
196   gtk_widget_get_allocation (GTK_WIDGET (overlay), &overlay_allocation);
197
198   main_allocation.x += overlay_allocation.x;
199   main_allocation.y += overlay_allocation.y;
200
201   halign = effective_align (gtk_widget_get_halign (child),
202                             gtk_widget_get_direction (child));
203
204   if (halign == GTK_ALIGN_START)
205     is_left = (child_allocation->x == main_allocation.x);
206   else if (halign == GTK_ALIGN_END)
207     is_right = (child_allocation->x + child_allocation->width ==
208                 main_allocation.x + main_allocation.width);
209
210   valign = gtk_widget_get_valign (child);
211
212   if (valign == GTK_ALIGN_START)
213     is_top = (child_allocation->y == main_allocation.y);
214   else if (valign == GTK_ALIGN_END)
215     is_bottom = (child_allocation->y + child_allocation->height ==
216                  main_allocation.y + main_allocation.height);
217
218   if (has_left && !is_left)
219     gtk_style_context_remove_class (context, GTK_STYLE_CLASS_LEFT);
220   else if (!has_left && is_left)
221     gtk_style_context_add_class (context, GTK_STYLE_CLASS_LEFT);
222
223   if (has_right && !is_right)
224     gtk_style_context_remove_class (context, GTK_STYLE_CLASS_RIGHT);
225   else if (!has_right && is_right)
226     gtk_style_context_add_class (context, GTK_STYLE_CLASS_RIGHT);
227
228   if (has_top && !is_top)
229     gtk_style_context_remove_class (context, GTK_STYLE_CLASS_TOP);
230   else if (!has_top && is_top)
231     gtk_style_context_add_class (context, GTK_STYLE_CLASS_TOP);
232
233   if (has_bottom && !is_bottom)
234     gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BOTTOM);
235   else if (!has_bottom && is_bottom)
236     gtk_style_context_add_class (context, GTK_STYLE_CLASS_BOTTOM);
237 }
238
239 static void
240 gtk_overlay_child_allocate (GtkOverlay      *overlay,
241                             GtkOverlayChild *child)
242 {
243   gint left, right, top, bottom;
244   GtkAllocation allocation, child_allocation, overlay_allocation;
245   gboolean result;
246
247   if (gtk_widget_get_mapped (GTK_WIDGET (overlay)))
248     {
249       if (gtk_widget_get_visible (child->widget))
250         gdk_window_show (child->window);
251       else if (gdk_window_is_visible (child->window))
252         gdk_window_hide (child->window);
253     }
254
255   if (!gtk_widget_get_visible (child->widget))
256     return;
257
258   g_signal_emit (overlay, signals[GET_CHILD_POSITION],
259                  0, child->widget, &allocation, &result);
260
261   gtk_widget_get_allocation (GTK_WIDGET (overlay), &overlay_allocation);
262
263   allocation.x += overlay_allocation.x;
264   allocation.y += overlay_allocation.y;
265
266   /* put the margins outside the window; also arrange things
267    * so that the adjusted child allocation still ends up at 0, 0
268    */
269   left = gtk_widget_get_margin_left (child->widget);
270   right = gtk_widget_get_margin_right (child->widget);
271   top = gtk_widget_get_margin_top (child->widget);
272   bottom = gtk_widget_get_margin_bottom (child->widget);
273
274   child_allocation.x = - left;
275   child_allocation.y = - top;
276   child_allocation.width = allocation.width;
277   child_allocation.height = allocation.height;
278
279   allocation.x += left;
280   allocation.y += top;
281   allocation.width -= left + right;
282   allocation.height -= top + bottom;
283
284   if (child->window)
285     gdk_window_move_resize (child->window,
286                             allocation.x, allocation.y,
287                             allocation.width, allocation.height);
288
289   gtk_overlay_child_update_style_classes (overlay, child->widget, &allocation);
290   gtk_widget_size_allocate (child->widget, &child_allocation);
291 }
292
293 static void
294 gtk_overlay_get_preferred_width (GtkWidget *widget,
295                                  gint      *minimum,
296                                  gint      *natural)
297 {
298   GtkBin *bin = GTK_BIN (widget);
299   GtkWidget *child;
300
301   if (minimum)
302     *minimum = 0;
303
304   if (natural)
305     *natural = 0;
306
307   child = gtk_bin_get_child (bin);
308   if (child && gtk_widget_get_visible (child))
309     gtk_widget_get_preferred_width (child, minimum, natural);
310 }
311
312 static void
313 gtk_overlay_get_preferred_height (GtkWidget *widget,
314                                   gint      *minimum,
315                                   gint      *natural)
316 {
317   GtkBin *bin = GTK_BIN (widget);
318   GtkWidget *child;
319
320   if (minimum)
321     *minimum = 0;
322
323   if (natural)
324     *natural = 0;
325
326   child = gtk_bin_get_child (bin);
327   if (child && gtk_widget_get_visible (child))
328     gtk_widget_get_preferred_height (child, minimum, natural);
329 }
330
331 static void
332 gtk_overlay_size_allocate (GtkWidget     *widget,
333                            GtkAllocation *allocation)
334 {
335   GtkOverlay *overlay = GTK_OVERLAY (widget);
336   GtkOverlayPrivate *priv = overlay->priv;
337   GSList *children;
338   GtkWidget *main_widget;
339
340   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->size_allocate (widget, allocation);
341
342   main_widget = gtk_bin_get_child (GTK_BIN (overlay));
343   if (!main_widget || !gtk_widget_get_visible (main_widget))
344     return;
345
346   gtk_widget_size_allocate (main_widget, allocation);
347
348   for (children = priv->children; children; children = children->next)
349     {
350       gtk_overlay_child_allocate (overlay, children->data);
351     }
352 }
353
354 static gboolean
355 gtk_overlay_get_child_position (GtkOverlay    *overlay,
356                                 GtkWidget     *widget,
357                                 GtkAllocation *alloc)
358 {
359   GtkAllocation main_alloc;
360   GtkRequisition req;
361   GtkAlign halign;
362   GtkTextDirection direction;
363
364   gtk_overlay_get_main_widget_allocation (overlay, &main_alloc);
365   gtk_widget_get_preferred_size (widget, NULL, &req);
366
367   alloc->x = main_alloc.x;
368   alloc->width = MIN (main_alloc.width, req.width);
369
370   direction = gtk_widget_get_direction (widget);
371
372   halign = gtk_widget_get_halign (widget);
373   switch (effective_align (halign, direction))
374     {
375     case GTK_ALIGN_START:
376       /* nothing to do */
377       break;
378     case GTK_ALIGN_FILL:
379       alloc->width = main_alloc.width;
380       break;
381     case GTK_ALIGN_CENTER:
382       alloc->x += main_alloc.width / 2 - req.width / 2;
383       break;
384     case GTK_ALIGN_END:
385       alloc->x += main_alloc.width - req.width;
386       break;
387     }
388
389   alloc->y = main_alloc.y;
390   alloc->height = MIN (main_alloc.height, req.height);
391
392   switch (gtk_widget_get_valign (widget))
393     {
394     case GTK_ALIGN_START:
395       /* nothing to do */
396       break;
397     case GTK_ALIGN_FILL:
398       alloc->height = main_alloc.height;
399       break;
400     case GTK_ALIGN_CENTER:
401       alloc->y += main_alloc.height / 2 - req.height / 2;
402       break;
403     case GTK_ALIGN_END:
404       alloc->y += main_alloc.height - req.height;
405       break;
406     }
407
408   return TRUE;
409 }
410
411 static void
412 gtk_overlay_realize (GtkWidget *widget)
413 {
414   GtkOverlay *overlay = GTK_OVERLAY (widget);
415   GtkOverlayPrivate *priv = overlay->priv;
416   GtkOverlayChild *child;
417   GSList *children;
418
419   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->realize (widget);
420
421   for (children = priv->children; children; children = children->next)
422     {
423       child = children->data;
424
425       if (child->window == NULL)
426         {
427           child->window = gtk_overlay_create_child_window (overlay, child->widget);
428           gtk_overlay_child_allocate (overlay, child);
429         }
430     }
431 }
432
433 static void
434 gtk_overlay_unrealize (GtkWidget *widget)
435 {
436   GtkOverlay *overlay = GTK_OVERLAY (widget);
437   GtkOverlayPrivate *priv = overlay->priv;
438   GtkOverlayChild *child;
439   GSList *children;
440
441   for (children = priv->children; children; children = children->next)
442     {
443       child = children->data;
444
445       gtk_widget_set_parent_window (child->widget, NULL);
446       gtk_widget_unregister_window (widget, child->window);
447       gdk_window_destroy (child->window);
448       child->window = NULL;
449     }
450
451   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->unrealize (widget);
452 }
453
454 static void
455 gtk_overlay_map (GtkWidget *widget)
456 {
457   GtkOverlay *overlay = GTK_OVERLAY (widget);
458   GtkOverlayPrivate *priv = overlay->priv;
459   GtkOverlayChild *child;
460   GSList *children;
461
462   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->map (widget);
463
464   for (children = priv->children; children; children = children->next)
465     {
466       child = children->data;
467
468       if (child->window != NULL &&
469           gtk_widget_get_visible (child->widget) &&
470           gtk_widget_get_child_visible (child->widget))
471         gdk_window_show (child->window);
472     }
473 }
474
475 static void
476 gtk_overlay_unmap (GtkWidget *widget)
477 {
478   GtkOverlay *overlay = GTK_OVERLAY (widget);
479   GtkOverlayPrivate *priv = overlay->priv;
480   GtkOverlayChild *child;
481   GSList *children;
482
483   for (children = priv->children; children; children = children->next)
484     {
485       child = children->data;
486
487       if (child->window != NULL &&
488           gdk_window_is_visible (child->window))
489         gdk_window_hide (child->window);
490     }
491
492   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->unmap (widget);
493 }
494
495 static gboolean
496 gtk_overlay_draw (GtkWidget *widget,
497                   cairo_t   *cr)
498 {
499   GtkOverlay *overlay = GTK_OVERLAY (widget);
500   GtkOverlayPrivate *priv = overlay->priv;
501   GtkOverlayChild *child;
502   GSList *children;
503
504   for (children = priv->children; children; children = children->next)
505     {
506       child = children->data;
507
508       if (gtk_cairo_should_draw_window (cr, child->window))
509         {
510           cairo_save (cr);
511           gtk_cairo_transform_to_window (cr, widget, child->window);
512           gtk_render_background (gtk_widget_get_style_context (widget),
513                                  cr,
514                                  0, 0,
515                                  gdk_window_get_width (child->window),
516                                  gdk_window_get_height (child->window));
517           cairo_restore (cr);
518         }
519     }
520
521   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->draw (widget, cr);
522
523   return FALSE;
524 }
525
526 static void
527 gtk_overlay_remove (GtkContainer *container,
528                     GtkWidget    *widget)
529 {
530   GtkOverlayPrivate *priv = GTK_OVERLAY (container)->priv;
531   GtkOverlayChild *child;
532   GSList *children;
533
534   for (children = priv->children; children; children = children->next)
535     {
536       child = children->data;
537
538       if (child->widget == widget)
539         {
540           if (child->window != NULL)
541             {
542               gtk_widget_unregister_window (GTK_WIDGET (container), child->window);
543               gdk_window_destroy (child->window);
544             }
545
546           gtk_widget_unparent (widget);
547
548           priv->children = g_slist_delete_link (priv->children, children);
549           g_slice_free (GtkOverlayChild, child);
550
551           return;
552         }
553     }
554
555   GTK_CONTAINER_CLASS (gtk_overlay_parent_class)->remove (container, widget);
556 }
557
558 static void
559 gtk_overlay_forall (GtkContainer *overlay,
560                     gboolean      include_internals,
561                     GtkCallback   callback,
562                     gpointer      callback_data)
563 {
564   GtkOverlayPrivate *priv = GTK_OVERLAY (overlay)->priv;
565   GtkOverlayChild *child;
566   GSList *children;
567   GtkWidget *main_widget;
568
569   main_widget = gtk_bin_get_child (GTK_BIN (overlay));
570   if (main_widget)
571     (* callback) (main_widget, callback_data);
572
573   children = priv->children;
574   while (children)
575     {
576       child = children->data;
577       children = children->next;
578
579       (* callback) (child->widget, callback_data);
580     }
581 }
582
583 static void
584 gtk_overlay_class_init (GtkOverlayClass *klass)
585 {
586   GObjectClass *object_class = G_OBJECT_CLASS (klass);
587   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
588   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
589
590   widget_class->get_preferred_width = gtk_overlay_get_preferred_width;
591   widget_class->get_preferred_height = gtk_overlay_get_preferred_height;
592   widget_class->size_allocate = gtk_overlay_size_allocate;
593   widget_class->realize = gtk_overlay_realize;
594   widget_class->unrealize = gtk_overlay_unrealize;
595   widget_class->map = gtk_overlay_map;
596   widget_class->unmap = gtk_overlay_unmap;
597   widget_class->draw = gtk_overlay_draw;
598
599   container_class->remove = gtk_overlay_remove;
600   container_class->forall = gtk_overlay_forall;
601
602   klass->get_child_position = gtk_overlay_get_child_position;
603
604   /**
605    * GtkOverlay::get-child-position:
606    * @overlay: the #GtkOverlay
607    * @widget: the child widget to position
608    * @allocation: (out caller-allocates): return location for the allocation
609    *
610    * The ::get-child-position signal is emitted to determine
611    * the position and size of any overlay child widgets. A
612    * handler for this signal should fill @allocation with
613    * the desired position and size for @widget, relative to
614    * the 'main' child of @overlay.
615    *
616    * The default handler for this signal uses the @widget's
617    * halign and valign properties to determine the position
618    * and gives the widget its natural size (except that an
619    * alignment of %GTK_ALIGN_FILL will cause the overlay to
620    * be full-width/height). If the main child is a
621    * #GtkScrolledWindow, the overlays are placed relative
622    * to its contents.
623    *
624    * Return: %TRUE if the @allocation has been filled
625    */
626   signals[GET_CHILD_POSITION] =
627     g_signal_new (I_("get-child-position"),
628                   G_TYPE_FROM_CLASS (object_class),
629                   G_SIGNAL_RUN_LAST,
630                   G_STRUCT_OFFSET (GtkOverlayClass, get_child_position),
631                   _gtk_boolean_handled_accumulator, NULL,
632                   _gtk_marshal_BOOLEAN__OBJECT_BOXED,
633                   G_TYPE_BOOLEAN, 2,
634                   GTK_TYPE_WIDGET,
635                   GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
636
637   g_type_class_add_private (object_class, sizeof (GtkOverlayPrivate));
638 }
639
640 static void
641 gtk_overlay_init (GtkOverlay *overlay)
642 {
643   overlay->priv = G_TYPE_INSTANCE_GET_PRIVATE (overlay, GTK_TYPE_OVERLAY, GtkOverlayPrivate);
644
645   gtk_widget_set_has_window (GTK_WIDGET (overlay), FALSE);
646 }
647
648 static void
649 gtk_overlay_buildable_add_child (GtkBuildable *buildable,
650                                  GtkBuilder   *builder,
651                                  GObject      *child,
652                                  const gchar  *type)
653 {
654   if (type && strcmp (type, "overlay") == 0)
655     gtk_overlay_add_overlay (GTK_OVERLAY (buildable), GTK_WIDGET (child));
656   else if (!type)
657     gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
658   else
659     GTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type);
660 }
661
662 static void
663 gtk_overlay_buildable_init (GtkBuildableIface *iface)
664 {
665   iface->add_child = gtk_overlay_buildable_add_child;
666 }
667
668 /**
669  * gtk_overlay_new:
670  *
671  * Creates a new #GtkOverlay.
672  *
673  * Returns: a new #GtkOverlay object.
674  *
675  * Since: 3.2
676  */
677 GtkWidget *
678 gtk_overlay_new (void)
679 {
680   return g_object_new (GTK_TYPE_OVERLAY, NULL);
681 }
682
683 /**
684  * gtk_overlay_add_overlay:
685  * @overlay: a #GtkOverlay
686  * @widget: a #GtkWidget to be added to the container
687  *
688  * Adds @widget to @overlay.
689  *
690  * The widget will be stacked on top of the main widget
691  * added with gtk_container_add().
692  *
693  * The position at which @widget is placed is determined
694  * from its #GtkWidget:halign and #GtkWidget:valign properties.
695  *
696  * Since: 3.2
697  */
698 void
699 gtk_overlay_add_overlay (GtkOverlay *overlay,
700                          GtkWidget  *widget)
701 {
702   GtkOverlayPrivate *priv = overlay->priv;
703   GtkOverlayChild *child;
704
705   g_return_if_fail (GTK_IS_OVERLAY (overlay));
706   g_return_if_fail (GTK_IS_WIDGET (widget));
707
708   child = g_slice_new0 (GtkOverlayChild);
709   child->widget = widget;
710
711   priv->children = g_slist_append (priv->children, child);
712
713   if (gtk_widget_get_realized (GTK_WIDGET (overlay)))
714     {
715       child->window = gtk_overlay_create_child_window (overlay, widget);
716       gtk_widget_set_parent (widget, GTK_WIDGET (overlay));
717       gtk_overlay_child_allocate (overlay, child);
718     }
719   else
720     gtk_widget_set_parent (widget, GTK_WIDGET (overlay));
721
722 }