mirror of
https://github.com/brl/mutter.git
synced 2024-11-26 10:00:45 -05:00
125bded814
Bug 1138 - No trackable "mapped" state * Add a VISIBLE flag tracking application programmer's expected showing-state for the actor, allowing us to always ensure we keep what the app wants while tracking internal implementation state separately. * Make MAPPED reflect whether the actor will be painted; add notification on a ClutterActor::mapped property. Keep MAPPED state updated as the actor is shown, ancestors are shown, actor is reparented, etc. * Require a stage and realized parents to realize; this means at realization time the correct window system and GL resources are known. But unparented actors can no longer be realized. * Allow children to be unrealized even if parent is realized. Otherwise in effect either all actors or no actors are realized, i.e. it becomes a stage-global flag. * Allow clutter_actor_realize() to "fail" if not inside a toplevel * Rework clutter_actor_unrealize() so internally we have a flavor that does not mess with visibility flag * Add _clutter_actor_rerealize() to encapsulate a somewhat tricky operation we were doing in a couple of places * Do not realize/unrealize children in ClutterGroup, ClutterActor already does it * Do not realize impl by hand in clutter_stage_show(), since showing impl already does that * Do not unrealize in various dispose() methods, since ClutterActor dispose implementation already does it and chaining up is mandatory * ClutterTexture uses COGL while unrealizable (before it's added to a stage). Previously this breakage was affecting ClutterActor because we had to allow realize outside a stage. Move the breakage to ClutterTexture, by making ClutterTexture just use COGL while not realized. * Unrealize before we set parent to NULL in clutter_actor_unparent(). This means unrealize() implementations can get to the stage. Because actors need the stage in order to detach from stage. * Update clutter-actor-invariants.txt to reflect latest changes * Remove explicit hide/unrealize from ClutterActor::dispose since unparent already forces those Instead just assert that unparent() occurred and did the right thing. * Check whether parent implements unrealize before chaining up Needed because ClutterGroup no longer has to implement unrealize. * Perform unrealize in the default handler for the signal. This allows non-containers that have children to work properly, and allows containers to override how it's done. * Add map/unmap virtual methods and set MAPPED flag on self and children in there. This allows subclasses to hook map/unmap. These are not signals, because notify::mapped is better for anything it's legitimate for a non-subclass to do. Signed-off-by: Emmanuele Bassi <ebassi@linux.intel.com>
304 lines
11 KiB
Plaintext
304 lines
11 KiB
Plaintext
ClutterActor Invariants
|
|
===============================================================================
|
|
|
|
ClutterActor behaviour has invariants that will be kept with the same API and
|
|
ABI guarantees as the whole Clutter library.
|
|
|
|
This document refers to the 0.8 release of Clutter.
|
|
|
|
Sections:
|
|
|
|
i. Flags
|
|
a. Public ClutterActor Flags
|
|
b. Private ClutterActor Flags
|
|
c. Private Pick Modes
|
|
ii. Invariants
|
|
iii. State changes
|
|
iv. Responsibilities of a ClutterActor
|
|
a. Adding to a container
|
|
b. Removing from a container
|
|
c. Initial state
|
|
|
|
i. Flags
|
|
-------------------------------------------------------------------------------
|
|
|
|
This section describes the various flags and enumerations used by
|
|
ClutterActor.
|
|
|
|
a. Public ClutterActor Flags
|
|
|
|
CLUTTER_ACTOR_REALIZED
|
|
Means: the actor has GPU resources associated to its paint
|
|
cycle.
|
|
|
|
Set by clutter_actor_realize(), unset by
|
|
clutter_actor_unrealize(). Generally set implicitly when the
|
|
actor becomes MAPPED (see below).
|
|
|
|
May only be set if one of the actor's ancestors is a toplevel.
|
|
May only be set if all of the actor's ancestors are realized.
|
|
|
|
Once realized an actor remains realized until removed from the
|
|
toplevel. Hide, reparent will not unrealize; but unparent or
|
|
destroy will unrealize since they remove the actor from the
|
|
toplevel.
|
|
|
|
CLUTTER_ACTOR_MAPPED
|
|
Means: the actor will be painted if the stage is mapped.
|
|
|
|
On non-toplevels, will be set if all of the following are
|
|
true, and unset otherwise:
|
|
* the actor's VISIBLE flag is set
|
|
* all of the actor's non-toplevel ancestors have the MAPPED
|
|
flag set
|
|
* the actor has a toplevel ancestor
|
|
* the toplevel ancestor's VISIBLE flag is set
|
|
* the toplevel ancestor's REALIZED flag is set
|
|
|
|
On toplevels, MAPPED is set asynchronously when the window
|
|
system notifies Clutter that the toplevel has been made
|
|
visible on the screen.
|
|
|
|
The MAPPED flag requires that an actor is REALIZED. When
|
|
Clutter sets the MAPPED flag, it forces realization; this is
|
|
the "normal" way for realization to occur, though explicit
|
|
realization with clutter_actor_realize() is permitted.
|
|
|
|
CLUTTER_ACTOR_VISIBLE
|
|
Means: the actor's "visible" property was set to true by
|
|
the application programmer.
|
|
|
|
Set by clutter_actor_show(), unset by clutter_actor_hide().
|
|
|
|
This is an application-controlled property, while MAPPED and
|
|
REALIZED are usually managed by Clutter (with the exception
|
|
that applications can "realize early" with
|
|
clutter_actor_realize()).
|
|
|
|
If VISIBLE is unset, the actor (and any children) must
|
|
be immediately unmapped, to maintain the invariants for
|
|
the MAPPED flag.
|
|
|
|
CLUTTER_ACTOR_REACTIVE
|
|
Set and unset by clutter_actor_set_reactive()
|
|
Means: the actor is now reactive to events.
|
|
Notes:
|
|
* If parents need to be reactive for child its up to the
|
|
parent implementation. In the case of ClutterGroup it
|
|
being marked unreactive does not mark all children unreactive.
|
|
* Clutter stage is always reactive.
|
|
|
|
|
|
b. Private ClutterActor flags
|
|
|
|
CLUTTER_ACTOR_IN_DESTRUCTION
|
|
Set internally by clutter_actor_destroy().
|
|
Used to avoid uneeded overhead when freeing GPU resources on unrealize
|
|
|
|
CLUTTER_ACTOR_IS_TOPLEVEL
|
|
Set internally by the initialization of ClutterStage
|
|
|
|
CLUTTER_ACTOR_IN_REPARENT
|
|
Set internally by clutter_actor_reparent(). This flag
|
|
optimizes the reparent process by avoiding the need
|
|
to pass through an unrealized state when the actor is
|
|
removed from the old parent.
|
|
|
|
CLUTTER_ACTOR_ABOUT_TO_UNPARENT
|
|
Set internally during part of clutter_actor_unparent().
|
|
Causes the actor to pretend it has no parent, then
|
|
update invariants; which effectively forces the actor
|
|
to unrealize. The purpose of this is to unrealize _before_ the
|
|
actor is removed from the stage, so unrealize implementations
|
|
can use clutter_actor_get_stage().
|
|
|
|
CLUTTER_ACTOR_SYNC_MATRICES
|
|
Set internally by ClutterStage implementations
|
|
Means: the size of the stage changed and the viewport must be
|
|
synchronized to the new size
|
|
|
|
CLUTTER_ACTOR_IN_PAINT:
|
|
Set internally by clutter_actor_paint()
|
|
|
|
CLUTTER_ACTOR_IN_RELAYOUT
|
|
Set internally by clutter_relayout()
|
|
|
|
c. Private Pick Modes
|
|
|
|
CLUTTER_PICK_NONE
|
|
No pick operation is performed during the paint
|
|
|
|
CLUTTER_PICK_REACTIVE
|
|
Only reactive actors will be picked
|
|
|
|
CLUTTER_PICK_ALL
|
|
All visible actors will be picked
|
|
|
|
ii. Invariants
|
|
-------------------------------------------------------------------------------
|
|
|
|
This section describes the various constraints and invariants on ClutterActor.
|
|
|
|
In the following
|
|
|
|
A => B means if A is true then B is true
|
|
A <=> B means A is true if and only if B is true
|
|
(equivalent to A => B && A <= B)
|
|
|
|
1) CLUTTER_ACTOR_IN_DESTRUCTION => !CLUTTER_ACTOR_IS_MAPPED (actor) &&
|
|
!CLUTTER_ACTOR_IS_REALIZED (actor)
|
|
|
|
clutter_actor_destroy() will cause an actor to be unparented,
|
|
which means the actor must be unmapped and unrealized as
|
|
well.
|
|
|
|
2) CLUTTER_ACTOR_IS_MAPPED (actor) => CLUTTER_ACTOR_IS_REALIZED (actor)
|
|
|
|
when an actor is mapped, it must first be realized.
|
|
|
|
This is the most common way an actor becomes realized.
|
|
|
|
3) if clutter_actor_set_parent (actor, parent):
|
|
((parent_is_not_toplevel && CLUTTER_ACTOR_IS_MAPPED (parent)) ||
|
|
(parent_is_toplevel && CLUTTER_ACTOR_IS_VISIBLE(parent))) &&
|
|
CLUTTER_ACTOR_IS_VISIBLE (actor)
|
|
=> CLUTTER_ACTOR_IS_MAPPED (actor)
|
|
|
|
calling clutter_actor_set_parent() on an actor and a mapped
|
|
parent will map the actor if it has been shown.
|
|
|
|
4) if clutter_actor_unparent (actor):
|
|
CLUTTER_ACTOR_IS_MAPPED (actor) <=> CLUTTER_ACTOR_IN_REPARENT
|
|
|
|
calling clutter_actor_unparent() on an actor will unmap and
|
|
unrealize the actor since it no longer has a toplevel.
|
|
|
|
calling clutter_actor_reparent() on an actor will leave the
|
|
actor mapped and realized (if it was before) until it has a
|
|
new parent, at which point the invariants implied by the new
|
|
parent's state are applied.
|
|
|
|
5) CLUTTER_ACTOR_IS_REALIZED(actor) => CLUTTER_ACTOR_IS_REALIZED(parent)
|
|
|
|
Actors may only be realized if their parent is realized.
|
|
However, they may be unrealized even though their parent
|
|
is realized.
|
|
|
|
This implies that an actor may not be realized unless
|
|
it has a parent, or is a toplevel.
|
|
|
|
Since only toplevels can realize without a parent, no actor
|
|
can be realized unless it either is a toplevel or has a
|
|
toplevel ancestor.
|
|
|
|
As long as they are unmapped, actors may be unrealized. This
|
|
will force all children of the actor to be unrealized, since
|
|
children may not be realized while parents are unrealized.
|
|
|
|
6) CLUTTER_ACTOR_IS_MAPPED(actor) <=>
|
|
( ( (CLUTTER_ACTOR_IS_VISIBLE(toplevel_parent) &&
|
|
CLUTTER_ACTOR_IS_REALIZED(toplevel_parent)) ||
|
|
CLUTTER_ACTOR_IS_MAPPED(non_toplevel_parent) ) ) &&
|
|
CLUTTER_ACTOR_IS_VISIBLE(actor)
|
|
|
|
Actors _must_ be mapped if and only if they are visible and
|
|
their parent is mapped, or they are visible and their
|
|
parent is a toplevel that's realized and visible.
|
|
|
|
This invariant enables us to track whether an actor will
|
|
be painted (whether it's MAPPED) without ever traversing
|
|
the actor graph.
|
|
|
|
iii. State changes
|
|
-------------------------------------------------------------------------------
|
|
|
|
clutter_actor_show:
|
|
1. sets VISIBLE
|
|
2. sets MAPPED if invariants are met; mapping in turn sets
|
|
REALIZED
|
|
|
|
clutter_actor_hide:
|
|
1. sets !VISIBLE
|
|
2. unsets MAPPED if actor was mapped previously
|
|
3. does not affect REALIZED
|
|
|
|
clutter_actor_destroy:
|
|
1. sets CLUTTER_ACTOR_IN_DESTRUCTION
|
|
2. unparents the actor, which in turn implies unmap and unrealize
|
|
|
|
clutter_actor_realize:
|
|
1. attempts to set REALIZED on all parents, failing if
|
|
invariants are not met, e.g. not in a toplevel yet
|
|
2. sets REALIZED on actor if parent was successfully realized
|
|
|
|
clutter_actor_unrealize:
|
|
1. sets !VISIBLE which forces !MAPPED
|
|
2. sets !REALIZED
|
|
3. !MAPPED and !REALIZED forces unmap and unrealize of all
|
|
children
|
|
|
|
clutter_actor_set_parent:
|
|
1. sets actor->parent
|
|
2. if actor->show_on_set_parent is TRUE calls clutter_actor_show
|
|
3. sets MAPPED if all prerequisites are now met for map
|
|
4. if !CLUTTER_ACTOR_IN_REPARENT emits ::parent-set with
|
|
old_parent set to NULL
|
|
|
|
clutter_actor_unparent:
|
|
1. unsets actor->parent
|
|
2. if !CLUTTER_ACTOR_IN_REPARENT, sets !MAPPED and !REALIZED
|
|
since the invariants for those flags are no longer met
|
|
3. if !CLUTTER_ACTOR_IN_REPARENT emits ::parent-set with
|
|
old_parent set to the previous parent
|
|
|
|
clutter_actor_reparent:
|
|
1. sets CLUTTER_ACTOR_IN_REPARENT
|
|
2. emits ::parent-set with old_parent set to the previous parent
|
|
equivalent to:
|
|
clutter_actor_unparent
|
|
clutter_actor_set_parent
|
|
3. updates state of the actor to match invariants
|
|
(may change MAPPED or REALIZED in either direction,
|
|
depending on state of the new parent)
|
|
|
|
|
|
iv. Responsibilities of a ClutterActor
|
|
-------------------------------------------------------------------------------
|
|
|
|
a. Adding to a container
|
|
|
|
When adding an actor to a container, the container must:
|
|
|
|
1. call clutter_actor_set_parent (actor, container)
|
|
2. call clutter_actor_queue_relayout (container) if
|
|
adding the actor changes the container's preferred
|
|
size
|
|
|
|
b. Removing from a container
|
|
|
|
When removing an actor from a container, the container must:
|
|
|
|
1. call clutter_actor_unparent (actor)
|
|
2. call clutter_actor_queue_relayout (container) if removing
|
|
the actor changes the container's preferred size
|
|
|
|
Notes:
|
|
|
|
* here a container actor is any actor that contains children actors; it
|
|
does not imply the implementation of the ClutterContainer interface.
|
|
|
|
* clutter_actor_unparent() will unmap and unrealize the actor except
|
|
in the special case when CLUTTER_ACTOR_IN_REPARENT is set.
|
|
|
|
* 'Composite' Clutter actors need to pass down any allocations to children.
|
|
|
|
c. Initial state
|
|
|
|
When creating an actor, the initial state is:
|
|
|
|
1. !CLUTTER_ACTOR_REALIZED
|
|
2. !CLUTTER_ACTOR_MAPPED
|
|
|
|
===============================================================================
|
|
$LastChangedDate$
|