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.