]> Pileus Git - ~andy/gtk/blob - gtk/gtkoverlay.c
gtk: Make widget only invalidate widget positions
[~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   gdk_window_set_user_data (window, overlay);
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         child->window = gtk_overlay_create_child_window (overlay, child->widget);
427     }
428 }
429
430 static void
431 gtk_overlay_unrealize (GtkWidget *widget)
432 {
433   GtkOverlay *overlay = GTK_OVERLAY (widget);
434   GtkOverlayPrivate *priv = overlay->priv;
435   GtkOverlayChild *child;
436   GSList *children;
437
438   for (children = priv->children; children; children = children->next)
439     {
440       child = children->data;
441
442       gtk_widget_set_parent_window (child->widget, NULL);
443       gdk_window_set_user_data (child->window, NULL);
444       gdk_window_destroy (child->window);
445       child->window = NULL;
446     }
447
448   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->unrealize (widget);
449 }
450
451 static void
452 gtk_overlay_map (GtkWidget *widget)
453 {
454   GtkOverlay *overlay = GTK_OVERLAY (widget);
455   GtkOverlayPrivate *priv = overlay->priv;
456   GtkOverlayChild *child;
457   GSList *children;
458
459   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->map (widget);
460
461   for (children = priv->children; children; children = children->next)
462     {
463       child = children->data;
464
465       if (child->window != NULL &&
466           gtk_widget_get_visible (child->widget) &&
467           gtk_widget_get_child_visible (child->widget))
468         gdk_window_show (child->window);
469     }
470 }
471
472 static void
473 gtk_overlay_unmap (GtkWidget *widget)
474 {
475   GtkOverlay *overlay = GTK_OVERLAY (widget);
476   GtkOverlayPrivate *priv = overlay->priv;
477   GtkOverlayChild *child;
478   GSList *children;
479
480   for (children = priv->children; children; children = children->next)
481     {
482       child = children->data;
483
484       if (child->window != NULL &&
485           gdk_window_is_visible (child->window))
486         gdk_window_hide (child->window);
487     }
488
489   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->unmap (widget);
490 }
491
492 static gboolean
493 gtk_overlay_draw (GtkWidget *widget,
494                   cairo_t   *cr)
495 {
496   GtkOverlay *overlay = GTK_OVERLAY (widget);
497   GtkOverlayPrivate *priv = overlay->priv;
498   GtkOverlayChild *child;
499   GSList *children;
500
501   for (children = priv->children; children; children = children->next)
502     {
503       child = children->data;
504
505       if (gtk_cairo_should_draw_window (cr, child->window))
506         {
507           cairo_save (cr);
508           gtk_cairo_transform_to_window (cr, widget, child->window);
509           gtk_render_background (gtk_widget_get_style_context (widget),
510                                  cr,
511                                  0, 0,
512                                  gdk_window_get_width (child->window),
513                                  gdk_window_get_height (child->window));
514           cairo_restore (cr);
515         }
516     }
517
518   GTK_WIDGET_CLASS (gtk_overlay_parent_class)->draw (widget, cr);
519
520   return FALSE;
521 }
522
523 static void
524 gtk_overlay_remove (GtkContainer *container,
525                     GtkWidget    *widget)
526 {
527   GtkOverlayPrivate *priv = GTK_OVERLAY (container)->priv;
528   GtkOverlayChild *child;
529   GSList *children;
530
531   for (children = priv->children; children; children = children->next)
532     {
533       child = children->data;
534
535       if (child->widget == widget)
536         {
537           if (child->window != NULL)
538             {
539               gdk_window_set_user_data (child->window, NULL);
540               gdk_window_destroy (child->window);
541             }
542
543           gtk_widget_unparent (widget);
544
545           priv->children = g_slist_delete_link (priv->children, children);
546           g_slice_free (GtkOverlayChild, child);
547
548           return;
549         }
550     }
551
552   GTK_CONTAINER_CLASS (gtk_overlay_parent_class)->remove (container, widget);
553 }
554
555 static void
556 gtk_overlay_forall (GtkContainer *overlay,
557                     gboolean      include_internals,
558                     GtkCallback   callback,
559                     gpointer      callback_data)
560 {
561   GtkOverlayPrivate *priv = GTK_OVERLAY (overlay)->priv;
562   GtkOverlayChild *child;
563   GSList *children;
564   GtkWidget *main_widget;
565
566   main_widget = gtk_bin_get_child (GTK_BIN (overlay));
567   if (main_widget)
568     (* callback) (main_widget, callback_data);
569
570   children = priv->children;
571   while (children)
572     {
573       child = children->data;
574       children = children->next;
575
576       (* callback) (child->widget, callback_data);
577     }
578 }
579
580 static void
581 gtk_overlay_class_init (GtkOverlayClass *klass)
582 {
583   GObjectClass *object_class = G_OBJECT_CLASS (klass);
584   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
585   GtkContainerClass *container_class = GTK_CONTAINER_CLASS (klass);
586
587   widget_class->get_preferred_width = gtk_overlay_get_preferred_width;
588   widget_class->get_preferred_height = gtk_overlay_get_preferred_height;
589   widget_class->size_allocate = gtk_overlay_size_allocate;
590   widget_class->realize = gtk_overlay_realize;
591   widget_class->unrealize = gtk_overlay_unrealize;
592   widget_class->map = gtk_overlay_map;
593   widget_class->unmap = gtk_overlay_unmap;
594   widget_class->draw = gtk_overlay_draw;
595
596   container_class->remove = gtk_overlay_remove;
597   container_class->forall = gtk_overlay_forall;
598
599   klass->get_child_position = gtk_overlay_get_child_position;
600
601   /**
602    * GtkOverlay::get-child-position:
603    * @overlay: the #GtkOverlay
604    * @widget: the child widget to position
605    * @allocation: (out): return location for the allocation
606    *
607    * The ::get-child-position signal is emitted to determine
608    * the position and size of any overlay child widgets. A
609    * handler for this signal should fill @allocation with
610    * the desired position and size for @widget, relative to
611    * the 'main' child of @overlay.
612    *
613    * The default handler for this signal uses the @widget's
614    * halign and valign properties to determine the position
615    * and gives the widget its natural size (except that an
616    * alignment of %GTK_ALIGN_FILL will cause the overlay to
617    * be full-width/height). If the main child is a
618    * #GtkScrolledWindow, the overlays are placed relative
619    * to its contents.
620    *
621    * Return: %TRUE if the @allocation has been filled
622    */
623   signals[GET_CHILD_POSITION] =
624     g_signal_new (I_("get-child-position"),
625                   G_TYPE_FROM_CLASS (object_class),
626                   G_SIGNAL_RUN_LAST,
627                   G_STRUCT_OFFSET (GtkOverlayClass, get_child_position),
628                   _gtk_boolean_handled_accumulator, NULL,
629                   _gtk_marshal_BOOLEAN__OBJECT_BOXED,
630                   G_TYPE_BOOLEAN, 2,
631                   GTK_TYPE_WIDGET,
632                   GDK_TYPE_RECTANGLE | G_SIGNAL_TYPE_STATIC_SCOPE);
633
634   g_type_class_add_private (object_class, sizeof (GtkOverlayPrivate));
635 }
636
637 static void
638 gtk_overlay_init (GtkOverlay *overlay)
639 {
640   overlay->priv = G_TYPE_INSTANCE_GET_PRIVATE (overlay, GTK_TYPE_OVERLAY, GtkOverlayPrivate);
641
642   gtk_widget_set_has_window (GTK_WIDGET (overlay), FALSE);
643 }
644
645 static void
646 gtk_overlay_buildable_add_child (GtkBuildable *buildable,
647                                  GtkBuilder   *builder,
648                                  GObject      *child,
649                                  const gchar  *type)
650 {
651   if (type && strcmp (type, "overlay") == 0)
652     gtk_overlay_add_overlay (GTK_OVERLAY (buildable), GTK_WIDGET (child));
653   else if (!type)
654     gtk_container_add (GTK_CONTAINER (buildable), GTK_WIDGET (child));
655   else
656     GTK_BUILDER_WARN_INVALID_CHILD_TYPE (buildable, type);
657 }
658
659 static void
660 gtk_overlay_buildable_init (GtkBuildableIface *iface)
661 {
662   iface->add_child = gtk_overlay_buildable_add_child;
663 }
664
665 /**
666  * gtk_overlay_new:
667  *
668  * Creates a new #GtkOverlay.
669  *
670  * Returns: a new #GtkOverlay object.
671  *
672  * Since: 3.2
673  */
674 GtkWidget *
675 gtk_overlay_new (void)
676 {
677   return g_object_new (GTK_TYPE_OVERLAY, NULL);
678 }
679
680 /**
681  * gtk_overlay_add_overlay:
682  * @overlay: a #GtkOverlay
683  * @widget: a #GtkWidget to be added to the container
684  *
685  * Adds @widget to @overlay.
686  *
687  * The widget will be stacked on top of the main widget
688  * added with gtk_container_add().
689  *
690  * The position at which @widget is placed is determined
691  * from its #GtkWidget:halign and #GtkWidget:valign properties.
692  *
693  * Since: 3.2
694  */
695 void
696 gtk_overlay_add_overlay (GtkOverlay *overlay,
697                          GtkWidget  *widget)
698 {
699   GtkOverlayPrivate *priv = overlay->priv;
700   GtkOverlayChild *child;
701
702   g_return_if_fail (GTK_IS_OVERLAY (overlay));
703   g_return_if_fail (GTK_IS_WIDGET (widget));
704
705   child = g_slice_new0 (GtkOverlayChild);
706   child->widget = widget;
707
708   priv->children = g_slist_append (priv->children, child);
709
710   if (gtk_widget_get_realized (GTK_WIDGET (overlay)))
711     {
712       child->window = gtk_overlay_create_child_window (overlay, widget);
713       gtk_widget_set_parent (widget, GTK_WIDGET (overlay));
714       gtk_overlay_child_allocate (overlay, child);
715     }
716   else
717     gtk_widget_set_parent (widget, GTK_WIDGET (overlay));
718
719 }