Re: Size allocation and redrawing issues



Tim Janik <timj gtk org> writes:

> On 30 Oct 2001, Owen Taylor wrote:
> 
> > Attached is my attempt at implement what I described. Brief summary
> > of what it does:
> [...]
> 
> > But beyond that, it achieves my goals of eliminating hysteresis,
> > and allowing widgets that want to handle resizes in a "smarter"
> > to do so.
> 
> there's one thing that i'm a bit worried about.
> iirc, one of the reasons for the hysteresis was:
> 
> window
>   |
>   vbox
>     |
>     +-hbox
>     |  |
>     |  +-label
>     |
>     +- foo (other) widgets
> 
> if label constantly changes text (say from a timeout), and thusly resizes
> (grows and/or shrinks), that could screw the whole GUI, worst case
> scenario was the window itself resizing with every timeout.

This patch has no affect on this. 

 * If the toplevel is user-resizable, then we don't shrink for a 
   shrinking requisition. The only size changes we ever make
   to toplevels are those that are forced.

 * If the toplevel is not user-resizable, then in GTK+-1.2, 
   current CVS and with my patch, the behavior is the same -
   the allocation of the window is always exactly the
   requisition of the toplevel.
 
> off head, what container would give me the old behaviour, say:
> struct {
>  GtkContainer...;
>  guint old_width, old_height;
> };
> init () { old_width=old_height=0; }
> size_request () {
>   forall children do { old_width=MAX(old_width,child->width);
>     old_height = MAX (old_height, child->height);
>   }
>  width=old_width;
>  height=old_height;
> }
> 
> and, to play nicely after some time, connect to toplevel's ::size_allocate,
> and reset old_width=old_height=0; in the handler?

I don't think the old behavior is ever desirable, because the
old behavior basically involves the allocations of the widgets
within the container being in an inconsistent state; size-allocate
on the toplevel should never cause widgets that _haven't_ changed
to abruptly change size/position in my opinion.

For a status-bar style continually changing display, I think the right
behavior is simply to truncate the label at the allocation and make
the toplevel resizable - if the user wants to see more, they can make
the window bigger. Having changing text bump the window bigger 
is not really a good idea.

(Yes, you could write a big-as-it-ever-was container, but that
would only be useful in non-resizable toplevels, and if I
was doing that, I'd make it reset only when removed from
the toplevel, or on an explicit reset() method, rather than
keying off size-allocate on the toplevel.)
 
> other than that, here're a few comments on the patch.
> 
> 
> > diff -u -p -r1.24 gtkprivate.h
> > --- gtk/gtkprivate.h    2001/10/29 07:06:36     1.24
> > +++ gtk/gtkprivate.h    2001/10/29 23:17:04
> > @@ -43,14 +43,16 @@ typedef enum
> >  {
> >    PRIVATE_GTK_USER_STYLE       = 1 <<  0,
> >    PRIVATE_GTK_RESIZE_PENDING   = 1 <<  2,
> > -  PRIVATE_GTK_RESIZE_NEEDED    = 1 <<  3,
> 
> if you do this, you need to adapt the shift counts so
> they stay incrementing.

Well, note there was already a gap there, though I was probably
responsible for that too. :-) 

My general feeling is that when changing enumeration values, it's best
to leave removed flags unused for a while and use new values to catch
breakage most clearly. Since these are private, of course, it doesn't
matter much at all here if we clean them up and change the values.

I'll do that before committing.

> > diff -u -p -r1.3 gtksizegroup.c
> > --- gtk/gtksizegroup.c  2001/10/26 23:47:38     1.3
> > +++ gtk/gtksizegroup.c  2001/10/29 23:17:04
> > @@ -20,6 +20,7 @@
> > 
> >  #include "gtkcontainer.h"
> >  #include "gtkintl.h"
> > +#include "gtkprivate.h"
> >  #include "gtksignal.h"
> >  #include "gtksizegroup.h"
> > 
> > @@ -116,8 +117,8 @@ add_widget_to_closure (GtkWidget       *
> >  static void
> >  real_queue_resize (GtkWidget *widget)
> >  {
> > -  if (GTK_IS_RESIZE_CONTAINER (widget))
> > -    _gtk_container_clear_resize_widgets (GTK_CONTAINER (widget));
> > +  GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
> > +  GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED);
> > 
> >    if (widget->parent)
> >      _gtk_container_queue_resize (GTK_CONTAINER (widget->parent));
> 
> hm, doesn't gtk_widget_queue_resize(widget) have the same effect as
> GTK_PRIVATE_SET_FLAG (widget, GTK_ALLOC_NEEDED);
> GTK_PRIVATE_SET_FLAG (widget, GTK_REQUEST_NEEDED);
> _gtk_container_queue_resize (widget->Parent);
> ?

I'm not sure I understand - this _is_ the implementation of
gtk_widget_queue_resize(). All sizing is redirected through
the size-group code.
 
> > @@ -1469,64 +1470,6 @@ gtk_widget_unparent (GtkWidget *widget)
> [...]
> 
> unset GTK_ALLOC_NEEDED and GTK_REQUEST_NEEDED here, those flags
> are bogus for unparented widgets (except prolly windows).

Well, they aren't _bogus_, they are irrelevant.

There are some issues here we need to think through in terms
of how requisition and allocation relate to the state of
widgets, in particular to it being:

 - Parent set 
 - Anchored
 - Realized 
 - style ensured
 - visible
 - mapped
 - viewable (anchored and all parents visible)

In terms of requisition, there are basically three conditions:

 R1) "requisition not meaingful"
 R2) "requisition meaingful, but we don't put the widget
    in the resize queue for resize if it changes"
 R3) "We update the requisition through the resize queue"

For allocation, the conditions are:

 A1) We can't call size_allocate()
 A2) We can call size_allocate()
 A3) "We update the requisition through the resize queue"

I believe that the conditions are:

 R1,A1)
 R2,A2) Widget is anchored (note that to call size_request()
        we need to ensure the style, but that can be done
        at any point when the widget is anchored)
 R3,A3) Widget is viewable

So, it seems to me that the corresponding flag/resize queue
requirements are only:

 R1 => R2 : Set ALLOC_NEEDED, RESIZE_NEEDED
 R2 => R3 : If ALLOC_NEEDED or RESIZE_NEEDED is set queue
            for resize

(the current logic isn't really close to this, though I
think it works out that from R1=>R3 we will set ALLOC_NEEDED
and RESIZE_NEEDED and queue for resize)

On the reverse transitions:

 R3 => R2 : "Unqueue for resize" isn't needed since 
            parent widgets won't allocate non-visible
            children.
 R2 => R1 : "Clear ALLOC_NEEDED RESIZE_NEEDED" flags. Not  
            necessary since the flags are meaningless
            in R1. 

Is it OK if I go ahead and commit what I have now and we
can deal with the details of exactly when ALLOC_NEEDED and
REQUEST_NEEDED from there?

Regards,
                                        Owen



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