[gtk+] GtkOverlay: Don't allocate child except in size_allocate



commit 785a916267c940a3cf67cf4986d2ff4469ff87e5
Author: Alexander Larsson <alexl redhat com>
Date:   Thu Mar 28 12:10:09 2013 +0100

    GtkOverlay: Don't allocate child except in size_allocate
    
    We were calling gtk_overlay_child_allocate() both in realize
    and in add as we wanted to create and position the child windows
    for the widgets. However, this call also actually called
    gtk_widget_size_allocate() on the child, which it shouldn't. In some
    cases the overlay is realized before being allocated, and thus it
    will allocate the child at 0x0 which is an invalid size for it to be in.
    In particular, if the child has margins set this will result in negative
    allocations and warnings.
    
    This fix splits out the allocation computation so that
    gtk_overlay_create_child_window can use it without callers
    having to call gtk_overlay_child_allocate() to move the windows.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=696623

 gtk/gtkoverlay.c |   99 ++++++++++++++++++++++++++++++------------------------
 1 files changed, 55 insertions(+), 44 deletions(-)
---
diff --git a/gtk/gtkoverlay.c b/gtk/gtkoverlay.c
index de80637..d87e977 100644
--- a/gtk/gtkoverlay.c
+++ b/gtk/gtkoverlay.c
@@ -82,9 +82,52 @@ G_DEFINE_TYPE_WITH_CODE (GtkOverlay, gtk_overlay, GTK_TYPE_BIN,
                          G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE,
                                                 gtk_overlay_buildable_init))
 
+static void
+gtk_overlay_compute_child_allocation (GtkOverlay      *overlay,
+                                     GtkOverlayChild *child,
+                                     GtkAllocation *window_allocation,
+                                     GtkAllocation *widget_allocation)
+{
+  gint left, right, top, bottom;
+  GtkAllocation allocation, overlay_allocation;
+  gboolean result;
+
+  g_signal_emit (overlay, signals[GET_CHILD_POSITION],
+                 0, child->widget, &allocation, &result);
+
+  gtk_widget_get_allocation (GTK_WIDGET (overlay), &overlay_allocation);
+
+  allocation.x += overlay_allocation.x;
+  allocation.y += overlay_allocation.y;
+
+  /* put the margins outside the window; also arrange things
+   * so that the adjusted child allocation still ends up at 0, 0
+   */
+  left = gtk_widget_get_margin_left (child->widget);
+  right = gtk_widget_get_margin_right (child->widget);
+  top = gtk_widget_get_margin_top (child->widget);
+  bottom = gtk_widget_get_margin_bottom (child->widget);
+
+  if (widget_allocation)
+    {
+      widget_allocation->x = - left;
+      widget_allocation->y = - top;
+      widget_allocation->width = allocation.width;
+      widget_allocation->height = allocation.height;
+    }
+
+  if (window_allocation)
+    {
+      window_allocation->x = allocation.x + left;
+      window_allocation->y = allocation.y + top;
+      window_allocation->width = allocation.width - (left + right);
+      window_allocation->height = allocation.height - (top + bottom);
+    }
+}
+
 static GdkWindow *
 gtk_overlay_create_child_window (GtkOverlay *overlay,
-                                 GtkWidget  *child)
+                                 GtkOverlayChild *child)
 {
   GtkWidget *widget = GTK_WIDGET (overlay);
   GtkAllocation allocation;
@@ -92,7 +135,7 @@ gtk_overlay_create_child_window (GtkOverlay *overlay,
   GdkWindowAttr attributes;
   gint attributes_mask;
 
-  gtk_widget_get_allocation (child, &allocation);
+  gtk_overlay_compute_child_allocation (overlay, child, &allocation, NULL);
 
   attributes.window_type = GDK_WINDOW_CHILD;
   attributes.wclass = GDK_INPUT_OUTPUT;
@@ -108,8 +151,8 @@ gtk_overlay_create_child_window (GtkOverlay *overlay,
   gtk_widget_register_window (widget, window);
   gtk_style_context_set_background (gtk_widget_get_style_context (widget), window);
 
-  gtk_widget_set_parent_window (child, window);
-
+  gtk_widget_set_parent_window (child->widget, window);
+  
   return window;
 }
 
@@ -240,9 +283,7 @@ static void
 gtk_overlay_child_allocate (GtkOverlay      *overlay,
                             GtkOverlayChild *child)
 {
-  gint left, right, top, bottom;
-  GtkAllocation allocation, child_allocation, overlay_allocation;
-  gboolean result;
+  GtkAllocation window_allocation, child_allocation;
 
   if (gtk_widget_get_mapped (GTK_WIDGET (overlay)))
     {
@@ -255,38 +296,14 @@ gtk_overlay_child_allocate (GtkOverlay      *overlay,
   if (!gtk_widget_get_visible (child->widget))
     return;
 
-  g_signal_emit (overlay, signals[GET_CHILD_POSITION],
-                 0, child->widget, &allocation, &result);
-
-  gtk_widget_get_allocation (GTK_WIDGET (overlay), &overlay_allocation);
-
-  allocation.x += overlay_allocation.x;
-  allocation.y += overlay_allocation.y;
-
-  /* put the margins outside the window; also arrange things
-   * so that the adjusted child allocation still ends up at 0, 0
-   */
-  left = gtk_widget_get_margin_left (child->widget);
-  right = gtk_widget_get_margin_right (child->widget);
-  top = gtk_widget_get_margin_top (child->widget);
-  bottom = gtk_widget_get_margin_bottom (child->widget);
-
-  child_allocation.x = - left;
-  child_allocation.y = - top;
-  child_allocation.width = allocation.width;
-  child_allocation.height = allocation.height;
-
-  allocation.x += left;
-  allocation.y += top;
-  allocation.width -= left + right;
-  allocation.height -= top + bottom;
+  gtk_overlay_compute_child_allocation (overlay, child, &window_allocation, &child_allocation);
 
   if (child->window)
     gdk_window_move_resize (child->window,
-                            allocation.x, allocation.y,
-                            allocation.width, allocation.height);
+                            window_allocation.x, window_allocation.y,
+                            window_allocation.width, window_allocation.height);
 
-  gtk_overlay_child_update_style_classes (overlay, child->widget, &allocation);
+  gtk_overlay_child_update_style_classes (overlay, child->widget, &window_allocation);
   gtk_widget_size_allocate (child->widget, &child_allocation);
 }
 
@@ -346,9 +363,7 @@ gtk_overlay_size_allocate (GtkWidget     *widget,
   gtk_widget_size_allocate (main_widget, allocation);
 
   for (children = priv->children; children; children = children->next)
-    {
-      gtk_overlay_child_allocate (overlay, children->data);
-    }
+    gtk_overlay_child_allocate (overlay, children->data);
 }
 
 static gboolean
@@ -423,10 +438,7 @@ gtk_overlay_realize (GtkWidget *widget)
       child = children->data;
 
       if (child->window == NULL)
-       {
-         child->window = gtk_overlay_create_child_window (overlay, child->widget);
-         gtk_overlay_child_allocate (overlay, child);
-       }
+       child->window = gtk_overlay_create_child_window (overlay, child);
     }
 }
 
@@ -712,9 +724,8 @@ gtk_overlay_add_overlay (GtkOverlay *overlay,
 
   if (gtk_widget_get_realized (GTK_WIDGET (overlay)))
     {
-      child->window = gtk_overlay_create_child_window (overlay, widget);
+      child->window = gtk_overlay_create_child_window (overlay, child);
       gtk_widget_set_parent (widget, GTK_WIDGET (overlay));
-      gtk_overlay_child_allocate (overlay, child);
     }
   else
     gtk_widget_set_parent (widget, GTK_WIDGET (overlay));


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]