changing usize in ::size-request (bug #155139)
- From: Tim Janik <timj gtk org>
- To: Gtk+ Developers <gtk-devel-list gnome org>
- Cc: Owen Taylor <otaylor redhat com>
- Subject: changing usize in ::size-request (bug #155139)
- Date: Tue, 12 Oct 2004 18:04:50 +0200 (CEST)
hi all.
matthias just pointed me at #155139, which in a nutshell fails to draw
notebook tabs since we applied:
alloc_needed = GTK_WIDGET_ALLOC_NEEDED (widget);
- GTK_PRIVATE_UNSET_FLAG (widget, GTK_ALLOC_NEEDED);
+ if (!GTK_WIDGET_REQUEST_NEEDED (widget)) /* Preserve request/allocate ordering */
+ GTK_PRIVATE_UNSET_FLAG (widget, GTK_ALLOC_NEEDED);
the reason for this can be found in the bug report itself:
static void
tab_label_set_size (GtkWidget *window, GtkWidget *label)
{
int label_width;
label_width = window->allocation.width/TAB_NB_MAX;
if (label_width < TAB_MIN_SIZE) label_width = TAB_MIN_SIZE;
gtk_widget_set_size_request (label, label_width, -1);
}
static void
tab_label_size_request_cb (GtkWidget *window,
GtkRequisition *requisition,
GtkWidget *child)
{
GtkWidget *hbox;
GtkWidget *nb;
nb = child->parent;
hbox = gtk_notebook_get_tab_label (GTK_NOTEBOOK (nb),
child);
tab_label_set_size (window, hbox);
}
[...]
label = gtk_label_new ("new tab");
[...]
g_signal_connect (window, "size_request",
G_CALLBACK (tab_label_size_request_cb), child);
that is, in the label's ::size-request handler tab_label_size_request_cb()
(at which point the label itself has already been size requested), the
testcase unconditionally sets the label's usize. that in turn queues a
new resize on the label.
however, due to the handling of the ::size-request signal inside
gtk, this request is later forgotten about (gtksizegroup.c):
g_signal_emit_by_name (widget,
"size_request",
&widget->requisition);
GTK_PRIVATE_UNSET_FLAG (widget, GTK_REQUEST_NEEDED);
basically, gtk doesn't support queueing new size requests from
::size-request, and that's been that way for a looong time.
[owen: FYI, applying my if (GTK_WIDGET_REQUEST_NEEDED (widget))
gtk_widget_size_request (widget); fix from last week did indeed trigger an
endless resizing loop with the test case and without the set_usize() guards.]
the bug at hand can fairly easily be circumvented in gtk by not queueing a
resize from set_usize() if the new usize doesn't actually change anything.
since this is a reasonable efficiency improvement to make anyway, i've
comitted the appropriate guards to gtk_widget_set_usize_internal(). it
doesn't fix the more fundamental problem of people wanting to adjust widget
sizes around size requisition time though.
ideally, the ::size-request signal would be RUN_LAST. it's not,
due to historic reasons though, and i'm afraid making it RUN_LAST
will significantly affect signal connections in exiting code:
static void
example_size_request_handler (GtkWidget *widget,
GtkRequisition *requisition)
{
requisition->width += 200; /* increase the size of a stock GtkTextView or similar widget */
requisition->height += 100;
}
such a handler would be rendered ineffective if the size requisition
default handler is executed *after* ordinary signal handlers (RUN_LAST),
unless example_size_request_handler is connected as GTK_CONNECT_AFTER.
so in order to deal with widget size adjustments around ::size-request time,
i see these possibilities:
1) make ::size-request a RUN_LAST signal as it ought to be. this should only
be done, when people are willing to put some work into porting their
applications to a new gtk+ version anyway, e.g. around gtk+-3.0.
2) introduce a ::custom-size or similar signal that is emitted directly
before ::size-request, and can be used by users to setup resizing handler
connections like the above (tab_label_size_request_cb, example_size_request_handler).
3) preserve the current state of affairs, where size adjustments that queue
a new resize during ::size-request are simply not supported.
4) make ::size-request a NO_RECURSE signal, and introduce a new private flag for
widgets (or similar mechanism like a private in-request widget list), which
can be used to detect queueing resizes during emission of ::size-request.
in that case, gtk_widget_queue_resize() could simply emit_by_name (widget,
"size-request"); which will cause a the current emission of ::size-request
to be restarted after the user handler queueing a resize returned.
that is, make ::size-request deal with recursive resize requests the way we
handle GtkAdjustment::value-changed.
this may still be incompatible with some existing user code setups, but
hopefully less so than simply making ::size-request RUN_LAST and as a
consequence, the caveats from (1) about applying this around a 3.0 change
only probably apply here as well.
for the first three cases, it might actually make sense to add some magic to the
signal code, to issue a warning once per runtime, for !AFTER signal connections
to ::size-request.
---
ciaoTJ
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]