Re: changing usize in ::size-request (bug #155139)

On Tue, 12 Oct 2004, Owen Taylor wrote:

On Tue, 2004-10-12 at 19:39 +0200, Tim Janik wrote:

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.

let me add:
5) change gtk_widget_size_allocate() to re-queue a resize if GTK_REQUEST_NEEDED
    remains set upon function exit. this keeps the invariant of ::size-request
    having to follow every queue_resize (for DRAWABLE widgets).
    this may trigger endless resizing loops, but only if users unconditionally
    cause queue_resize from ::size-request signal handlers, in which case it
    can be argued they get what they deserve (requested). note that the testcase
    from #155139 is such a scenrio though. it only happens to work with
    recent CVS because i made set_usize() queue a resize conditionally.

Silly question - doesn't it fix everything if we simply just move
unsetting the GTK_REQUEST_NEEDED flag before we emit ::size-request?

Of the invariants I outlined earlier, the one that is broken is
"REQUEST_NEEDED on child implies REQUEST_NEEDED on parent.

When we emit ::size-request on the widget, one two things can happen:

- Either no descendant calls gtk_widget_queue_resize(), in which case
  REQUEST_NEEDED will be unset on all children

- Or a descendant calls gtk_widget_queue_resize() in which case the
  REQUEST_NEEDED flag will be set again on the widget.

i don't think things will continue to work as smoothly, if one of your
resize containers is an immediate resize container and you queue a resize
from within ::size-request of one of its children.
so some of my suggestions (esp. (4)) tried to implement proper recursion
handling from within ::size-request.
come to think of it, i'm now pretty sure gtksizegroup.c implicitely depends
on asyncronous resizes as well though.

mundane cases can easily be constructed where such circular scenarios either:
- loop endlessly due to ping-pong size requests (the lable<->window dependancy might
   request alternating sizes like: 4,5,4,5,4,5,4,5), or
- get into a feedback loop (with size requests: 8,...,256,...,65536,...)
and due to float-round-off, font-sizes, theme settings, etc. these pathologic cases
might not even always be triggered.

if we want to completely prevent such scenarios, i might even add:
(6) explicitely catch queue_resize() during ::size-request emissions by a mechanism
     similar to that suggested in (4), and issue a warning.

i think we should stop to look for more use cases for queue_resize() from ::size-request
though. experience shows that code is usually used in unintended or not planned for
ways, so we should rather make a general decision on how to deal with recursive resize
requests, than to focus on getting arbitrary cases to work and ignore others.

I think we should give people the rope ... yes, calling queue_resize()
out of ::size-request or ::size-allocate can easily trigger loops, but
especially when the entire window content is known, it can be safe and
useful in cases... you can use it to emulate height-for-width for a
widget, for example.

ok, for 2.6, i'd sugegst we then do:
- unsetting the GTK_REQUEST_NEEDED flag before we emit ::size-request, as you suggest
- deprecate GTK_RESIZE_IMMEDIATE and internally treat it as GTK_RESIZE_QUEUE
  (if somebody would really wanted to shoot himself into the foot with immediate
  resizing, he can still call gtk_container_check_resize() himself)
- leave the
    s/while (!GTK_WIDGET_ALLOC_NEEDED (widget) ||
             !GTK_WIDGET_REQUEST_NEEDED (widget))/while (TRUE)/
  change from 2.4 in place. while it shouldn't strictly be neccessary, the
  checks aren't strictly necessary either and simply "set ALLOC_NEEDED and
  REQUEST_NEEDED up to the resize_container" is easier to read and understand.



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