docs: Add a simple description of the size negotiation mechanism

Describe (with an example) the ordering and meaning of flags for the
size negotiation in ClutterActor.
This commit is contained in:
Emmanuele Bassi 2011-07-19 14:01:30 +01:00
parent 123bd41e6c
commit c1951ab17a

85
doc/size-negotiation.txt Normal file
View File

@ -0,0 +1,85 @@
Size negotiation in Clutter
---------------------------
Clutter uses a two-pass size negotiation mechanism. Each parent will ask its
children (if any) for their preferred size, which will affect the parent's own
preferred size; once this preferred size query returns to the stage, the stage
will allocate the size of each child, which in turn will allocate each one of
their own children, until it reaches the end of the scene graph.
The preferred size of an actor is defined through the:
get_preferred_width()
get_preferred_height()
virtual functions that should be implemented by every actor. The virtual
functions will only be invoked if the corresponding flags:
needs_width_request
needs_height_request
are set; otherwise, the preferred size will be cached inside ClutterActor
itself.
Actors can inform their parents that their preferred size has changed by using:
clutter_actor_queue_relayout()
on themselves. This function will "bubble up" through the scene graph, and it
will clear the:
needs_width_request
needs_height_request
needs_allocation
flags inside the actor and its parents up to the stage.
At the beginning of the next frame, the stage will check if there is a relayout
pending, and it will ask each child for its preferred size; depending on the
state of the flags, the implementations for the virtual functions:
get_preferred_width()
get_preferred_height()
allocate()
will be invoked in that order. Each parent is responsible for calling
clutter_actor_allocate() on its children.
Example
-------
Let's consider a scene composed by actors following this layout:
+---------------------------------------+
|3 +=============+ +==+ +=============+ |
| | +-+ +-+ +-+ | | | |2 +-+ +----+ | |
| | | | | | | | | | | | |1| | | | |
| | +-+ +-+ +-+ | | | | +-+ +----+ | |
| +=============+ +==+ +=============+ |
+---------------------------------------+
The actor (1) calls queue_relayout(), which clears the needs_* flags on its
parent (2), and its grand-parent (3); the state of the other siblings will be
left untouched.
+---------------------------------------+
|a +=============+ +==+ +=============+ |
| |b+-+ +-+ +-+ | |f | |g +---+ +--+ | |
| | |c| |d| |e| | | | | |h | |i | | |
| | +-+ +-+ +-+ | | | | +---+ +--+ | |
| +=============+ +==+ +=============+ |
+---------------------------------------+
At the beginning of the following frame, clutter_actor_allocate() will be called
starting from the actor (a). Since its needs_* flags have been cleared, the
allocate() virtual function will be invoked. This will cause
clutter_actor_allocate() to be called on its children, starting from (b). The
size computed by the parent (a) for its child (b) hasn't changed, and its
needs_* flags haven't been cleared, so clutter_actor_allocate() will
short-circuit, and will not cause the implementation of the allocate() virtual
function for (b) to be called, effectively skipping the branch of the scene
graph. The same will happen for (f).
The child (g) has the same size, but its needs_* flags will have been cleared,
so its allocate() implementation will be invoked; this will cause the (h) and
(i) children to be allocated as well.