Size allocation and redrawing issues
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org
- Cc: timj gtk org, blizzard redhat com
- Subject: Size allocation and redrawing issues
- Date: 24 Oct 2001 19:06:50 -0400
Hi Tim,
Could you please review the following: it describes some things I'd
like to improve with allocation and redrawing, gives a list of
"invariants" that I think we need to maintain, and proposes a few
changes to the way we do allocation and redrawing.
Thanks,
Owen
====
There are essentially issues that I'd like to address:
* We need to get rid of hysteresis. This is the phenomena where
if a widget's requisitions shrinks, it won't be allocated
smaller, until something happens to cause gtk_widget_size_allocate()
on the toplevel.
* There are some optimizations that we are missing. For example,
if you are resizing a toplevel, it should not be necessary to redraw
no-window widgets that don't change size.
* It should be possible to write a widget that can change size
without it being completely redrawn. This is important for smooth
resizing in a situation where you are displaying a portion of a
large "canvas".
An example inside GTK+ is GtkTreeView - if you resize a GtkTreeView
larger, all columns are redrawn, not just the last visible column.
The important things that must be maintained:
* If you call gtk_widget_queue_resize() on a widget, that must result
in:
- a call to gtk_widget_size_request() on the widget
- a call to gtk_widget_size_allocate() on the widget
- the widget being redrawn
Currently, all three of these will propagate to descendents
of the widget, but I don't think there is actually any real
requirement that the second two propagate (except as required
by changing allocations, and propagation of exposes to NO_WINDOW
children.)
* If a NO_WINDOW widget is allocated with a different
allocation->x, allocation->y, then we must invalidate all of
the new and old widget->allocation in widget->window. There is
no need to invalidate in other windows owned by the widget.
* By default, if a widget is allocated with a different size,
we must invalidate all of the new and old allocation in
widget->window and any descendent windows owned by the widget.
We do not need to invalidate in descendent windows not
owned by the widget.
It may be desirable to add a widget flag to turn off this behavior.
* If widget->allocation changes in any way and the reallocate_redraws
flag is set on the widget's parent, then the parent must be redrawn
in its entirety.
* When a NO_WINDOW widget is mapped, widget->allocation must
be invalidated in widget->window. !NO_WINDOW widgets and
descendent windows owned by the widget do not need to be
invalidated. (It's useful to invalidate them to prevent round
trips to the server; this should be done in GDK, however.)
* When a NO_WINDOW widget is unmapped, widget->allocation must
be invalidated in widget->window.
The scheme I have for achieving the first three goals while maintaining
the above facts (some of the stuff below is already done, but included
for clarity.)
* Add a flag:
void gtk_widget_set_redraw_on_allocate (GtkWidget widget, gboolean redraw_on_allocate);
Defaulting to TRUE, where TRUE means "If I get a new size, redraw all of me".
If FALSE, then the only invalidation GTK+ will do on size change is the
new part of the allocation, and any invalidation from GdkWindows changing
size.
This is unfortunately close in name to gtk_container_set_reallocate_redraws(),
but nothing much we can do about that - set_reallocate_redraws() should have
been named "set_child_reallocate_redraws()" or something.
* In gtk_widget_queue_resize(), invalidate the allocation of the widget
in widget->window and all descendent windows owned by the widget.
* Use the following algorithm in gtk_container_resize_children():
Set a private ALLOCATE_NEEDED flag for all widgets in
resize_widgets, and all intermediate widgets between those
widgets and the container.
Call gtk_widget_size_allocate() on the container.
* In gtk_widget_size_allocate():
Clear the allocate_needed flag.
If the allocate_needed flag was not set and the new allocation is
equal to widget->allocation, return.
Call size_allocate() on the widget
If the allocation->x,y changed and its a NO_WINDOW widget, invalidate
the union of the old and new allocation.
If allocation->width,height changes:
If redraw_on_allocate is not set:
Invalidate difference of old and new allocation in widget->window
if it's A NO_WINDOW widget, otherwise do nothing
Iif redraw_on_allocate is set:
Invalidate the union of the old and new allocation in widget->window
and in all descendents of widget->window owned by the widget.
* On map and unmap:
If the widget is NO_WINDOW, invalidate the widget's allocation.
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]