99 lines
3.6 KiB
Plaintext
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.
|