On Mon, 27 Sep 2004, Owen Taylor wrote:
I'm not *completely* sure this should be considered a GTK+ bug, since what you are doing is fairly marginal. But there is a fairly easy fix, which would be, in gtk_widget_size_allocate(), do:
alloc_needed = GTK_WIDGET_ALLOC_NEEDED (widget); - GTK_PRIVATE_UNSET_FLAG (widget, GTK_ALLOC_NEEDED); + /* Preserve request/allocate ordering */ + if (!GTK_WIDGET_REQUEST_NEEDED (widget)) + GTK_PRIVATE_UNSET_FLAG (widget, GTK_ALLOC_NEEDED);
So, I'd actually appreciate it if you could file a bug in bugzilla with your test case as an attachment and a link to this analysis in the mail.gnome.org archives.
that is: #153896.
i've run into REQUEST_NEEDED still being set upon ::size-allocate while debugging another scenario. unfortunately, the exact setup to reproduce the bug i'm talking about is fairly complicated, it involves a lot of widgets, a bunch of signal connections, size groups and a scrolled window. here, siblings of a scrolled window (grouped together with the scrolled window in a GtkSizeGroup) end up size requested but not properly size allocated, with flags !REQUEST_NEEDED && ALLOC_NEEDED or with both flags unset, but the last size-allocate left out.
the actual problem is that gtk_widget_size_request() may be called during size-allocation. with scrolled windows, this is actually not
uncommon, since size-allocate on a scrolled window changes the scroll
adjustments, and that in turn may change scrollbar visibility (which
queues a resize).
but if queue_resize is called during the size-allocation phase, for some selected widgets inside a hirachy, the following state changes can occour (widget and sibling don't need to share the same immediate parent, but they have a common container in their ancestry and share a size-group):
queue_resize: REQUEST_NEEDED ALLOC_NEEDED ancestry * * widget * * sibling * *
size_request: REQUEST_NEEDED ALLOC_NEEDED ancestry * widget * sibling *
start of size_allocate phase: REQUEST_NEEDED ALLOC_NEEDED ancestry (got allocated) widget (currently being allocated) sibling *
widget calls queue_resize from size_allocate, which causes queue_resize(sibling) (due to the GtkSizeGroup): REQUEST_NEEDED ALLOC_NEEDED ancestry * * widget * * sibling * *
end of first size_allocate phase:
REQUEST_NEEDED ALLOC_NEEDED
ancestry * * widget * *
sibling * (got allocated)
after another size_request and size_allocate round, this will lead to ancestry and widget being allocated new sizes, but will leave sibling unallocated (though it was requested a new size).
calling gtk_widget_size_request() on a widget basically means: 1) call size_request on this widget (REQUEST_NEEDED set) 2) call size-allocate on this widget (ALLOC_NEEDED set) and having REQUEST_NEEDED and/or ALLOC_NEEDED set on a widget requires 3) all its ancestry up to its resize-container have those flags set as well, 4) its resize-container must be in the idle-sizer queue.
so, doing just:
- GTK_PRIVATE_UNSET_FLAG (widget, GTK_ALLOC_NEEDED); + /* Preserve request/allocate ordering */ + if (!GTK_WIDGET_REQUEST_NEEDED (widget)) + GTK_PRIVATE_UNSET_FLAG (widget, GTK_ALLOC_NEEDED);
in gtk_widget_size_allocate() isn't good enough. only calling gtk_widget_size_allocate() will cause proper size requisition on GtkSizeGroup siblings and care of the ancestry invariants (3) and (4).
so CVS head now contains:
+Tue Oct 5 17:06:26 2004 Tim Janik <timj@xxxxxxx> + + * gtk/gtkwidget.c (gtk_widget_size_allocate): if REQUEST_NEEDED is still + set on ::size-allocate, another size-request has been queued since + ::size-request and needs to be requeued. + --- gtk/gtkwidget.c 16 Aug 2004 18:38:55 -0000 1.380 +++ gtk/gtkwidget.c 5 Oct 2004 15:08:14 -0000 @@ -2705,7 +2705,13 @@ gtk_widget_size_allocate (GtkWidget *wid old_allocation.y != real_allocation.y);
if (!alloc_needed && !size_changed && !position_changed) - return; + { + if (GTK_WIDGET_REQUEST_NEEDED (widget)) + { /* another resize has been queued */ + gtk_widget_queue_resize (widget); + } + return; + }
g_signal_emit (widget, widget_signals[SIZE_ALLOCATE], 0, &real_allocation);
@@ -2743,6 +2749,11 @@ gtk_widget_size_allocate (GtkWidget *wid
GdkRegion *invalidate = gdk_region_rectangle (&widget->parent->allocation);
gtk_widget_invalidate_widget_windows (widget->parent, invalidate);
gdk_region_destroy (invalidate);
+ }
+ + if (GTK_WIDGET_REQUEST_NEEDED (widget))
+ { /* another resize has been queued */
+ gtk_widget_queue_resize (widget);
}
}
and i want to merge this into 2.4, but thought i'd ask for review first. (this should also fix the issue reported in #153896)
--- ciaoTJ _______________________________________________ gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list