mutter/doc/size-negotiation.txt

99 lines
3.6 KiB
Plaintext

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.
Fixed preferred size
--------------------
If an actor has a fixed size then that size will take precedence over the cached
size and the actor's implementation of the get_preferred_* virtual functions.
Constraints
-----------
Constraints only affect the allocation phase; each constraint is allowed to
modify the allocation passed to clutter_actor_allocate(), before it will be
checked and eventually discarded.