Bug in get_preferred_height_for_width() [was Re: Minimum height for minimum width]



On Wed, 2010-10-13 at 02:50 +0900, Tristan Van Berkom wrote:
> On Tue, 2010-10-12 at 13:27 -0400, Havoc Pennington wrote:
> > Hi,
> > 
> > On Tue, Oct 12, 2010 at 12:38 PM, Havoc Pennington <hp pobox com> wrote:
> > > d) max size widget can do something useful with
> > > e) size at which widget acts like expand=false (this is what I'd call
> > > "max size" and I think it's a feature GTK doesn't have right now)
> > 
> > Trying to think about how these two are different, and not really
> > getting anywhere. It seems like you'd never set the max size above the
> > natural size.
> > 
> > So in the scrolled window case, to get the effect Matthias was going
> > for, maybe the answer would just be to set the max size hint on the
> > window to the natural size. The problem with that is basically
> > maximization and fullscreen, i.e. that we don't really want a max size
> > - it's better to add padding.
> > 
> > Conclusion perhaps, e) is not useful, user should always be able to
> > resize "too high" and get extra padding in the layout, if they want.
> > 
> > The situation where it could make sense to add max_size to
> > get_preferred_{width,height} might be if the natural size were defined
> > as c) "a good size", then you'd also be able to use a separate "max
> > useful size." For example then a box layout would first bring all
> > children up to the good size; if still extra space, then bring them
> > all up to max size; if still extra space, then start padding them.
> 
> Ah interesting, I suppose that when a label's xalign property is 
> not FILL, it will cease unwrapping and giving away height once 
> allocated any size greater than its natural width.
> 
> I suppose that's not really a problem though, the desired effect
> of "align != FILL" needs only to be properly interpreted.

Actually now that I give this a little more consideration, this
is quite a serious bug.

The problem here is what happens when you call
'gtk_widget_get_preferred_height_for_width ()', with a for_width
that is greater than the natural width; on a widget 
that has xalign != FILL. It can cause some disasters ;-)

This is not to say that the bug was introduced by introducing
the x/yalign properties, its just something that so far has
not come up and hasn't been considered yet (actually having
the xalign property on GtkWidgetClass gives us a decent
starting point to fix the bug).

So to be more clear, lets consider a GtkLabel that is
configured to have a minimum width of a word and a natural
width of say, around 50 chars (lets say that the paragraph
does not want to compete for space after 50 chars but wants
instead to maintain a reasonable 3 or so lines before expanding):

Minimum:
+----------+
| A word   |
| length   |
| minimum  |
| and a    |
| natural  |
| with of  |
| some     |
| arbitrary|
| value    |
+----------+
(Figure A)

Natural:
+--------------------------------+
| A word length minimum and a    |
| natural with of some arbitrary |
| value                          |
+--------------------------------+
(Figure B)

When allocated something wider than natural (i.e. expand space in play)
+-------------------------------------+
| A word length minimum and a natural |
| with of some arbitrary value        |
+-------------------------------------+
(Figure C)

Currently if the widget receives any expand space (or more importantly
when the parent container requests how much height a widget needs for 
a width that is greater than the widget's natural width) the widget, 
for instance a GtkLabel in Figure C will request a height for only 2
lines.

But then if the label is not set to FILL its horizontal space,
gtk_widget_real_adjust_size_allocation() will come along and
remove any remaining size that flows over the natural width,
and try to fit the required height for the natural width
instead.

In other words, the parent container will expect the child
to have a size like Figure C and allocate only enough height
for Figure C, while gtk_widget_real_adjust_size_allocation()
will then try to stuff a size like Figure B into the allocation
of Figure C.

Some ways we can go about addressing this:

  a) Widget implementations have to check their xalign and never
     report a height smaller than the height required for natural
     width.

     This is obviously undesirable, we don't want widget implementations
     special casing the xalign property form inside height-for-width
     methods.

  b) From deep inside gtksizerequest.c, we actually check if the 
     xexpand != FILL before issuing the height_for_width() call to
     the widget implementation, i.e. never really request a height
     for > natural width whenever the widget wont fill

     Better than option 'a' but adds cycles to the request
     process. Where xexpand != FILL then natural size needs to be
     consulted again from within
     gtk_widget_get_preferred_height_for_width().

  c) Add "full_width" and "full_height" arguments to all
     height-for-width APIs, I think this is undesirable because
     it makes the API even harder to describe/understand/implement.

     However if widgets could be asked their full-width, then the
     xalign != FILL could fill up to the full-possible-width of
     a widget (if it were given expand space) and then start
     aligning only once the full width of a widget is less than
     its allocated width.

I'm leaning right now towards option 'b'; actually with option 'b'
I dont think it's needed (or appropriate) to call the vfunc for
get_preferred_width(), we can use a cached value here that is
also pre-adjusted by size-groups and a possible
gtk_widget_set_natural_size_request() api.

I'm going to go ahead and try an implementation of 'b' and
write up a test case which reproduces the problem.

Cheers,
       -Tristan

> 
> 
> 
> _______________________________________________
> gtk-devel-list mailing list
> gtk-devel-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-devel-list




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