forked from AuroraMiddleware/gtk
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
This commit is contained in:
parent
6f607fc8b4
commit
785a916267
@ -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));
|
||||
|
Loading…
Reference in New Issue
Block a user