[clone] Allow painting hidden source actors

With the introduction of the map/unmap flags and the split of the
visible state from the mapped state we require that every part of
a scene graph branch is mapped in order to be painted. This breaks
the ability of a ClutterClone to paint an hidden source actor.

In order to fix this we need to introduce an override flag, similar
in spirit to the current modelview and paint opacity overrides that
Clone is already using.

The override flag, when set, will force a temporary map on a
Clone source (and its children).
This commit is contained in:
Emmanuele Bassi 2009-05-01 12:33:42 +01:00
parent 5d2d8297e2
commit 1a87e4e252
3 changed files with 112 additions and 30 deletions

View File

@ -328,7 +328,8 @@ struct _ClutterActorPrivate
PangoContext *pango_context;
ClutterActor *opacity_parent;
gboolean enable_model_view_transform;
guint enable_model_view_transform : 1;
guint enable_paint_unmapped : 1;
};
enum
@ -514,13 +515,16 @@ G_DEFINE_ABSTRACT_TYPE_WITH_CODE (ClutterActor,
clutter_scriptable_iface_init));
/* FIXME this is for debugging only, remove once working (or leave in
* only in some debug mode). Should leave it for a little while
#ifdef CLUTTER_ENABLE_DEBUG
/* XXX - this is for debugging only, remove once working (or leave
* in only in some debug mode). Should leave it for a little while
* until we're confident in the new map/realize/visible handling.
*/
static void
static inline void
clutter_actor_verify_map_state (ClutterActor *self)
{
ClutterActorPrivate *priv = self->priv;
if (CLUTTER_ACTOR_IS_REALIZED (self))
{
/* all bets are off during reparent when we're potentially realized,
@ -528,22 +532,20 @@ clutter_actor_verify_map_state (ClutterActor *self)
*/
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_REPARENT))
{
if (self->priv->parent_actor == NULL)
if (priv->parent_actor == NULL)
{
if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL)
{
}
else
{
g_warning ("Realized non-toplevel actor should have a parent");
}
}
else if (!CLUTTER_ACTOR_IS_REALIZED (self->priv->parent_actor))
else if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_actor))
{
g_warning ("Realized actor %s %p has an unrealized parent %s %p",
g_warning ("Realized actor %s[%p] has an unrealized parent %s[%p]",
G_OBJECT_TYPE_NAME (self), self,
G_OBJECT_TYPE_NAME (self->priv->parent_actor),
self->priv->parent_actor);
G_OBJECT_TYPE_NAME (priv->parent_actor),
priv->parent_actor);
}
}
}
@ -558,7 +560,7 @@ clutter_actor_verify_map_state (ClutterActor *self)
*/
if (!(CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IN_REPARENT))
{
if (self->priv->parent_actor == NULL)
if (priv->parent_actor == NULL)
{
if (CLUTTER_PRIVATE_FLAGS (self) & CLUTTER_ACTOR_IS_TOPLEVEL)
{
@ -573,27 +575,47 @@ clutter_actor_verify_map_state (ClutterActor *self)
}
else
{
if (!CLUTTER_ACTOR_IS_VISIBLE (self->priv->parent_actor))
ClutterActor *parent = priv->parent_actor;
/* check for the enable_paint_unmapped flag on any of the
* parents; if the flag is enabled at any point of this
* branch of the scene graph then all the later checks
* become pointless
*/
while (parent != NULL)
{
g_warning ("Actor should not be mapped if parent is not visible");
if (parent->priv->enable_paint_unmapped)
return;
parent = parent->priv->parent_actor;
}
if (!CLUTTER_ACTOR_IS_REALIZED (self->priv->parent_actor))
if (!CLUTTER_ACTOR_IS_VISIBLE (priv->parent_actor))
{
g_warning ("Actor should not be mapped if parent is not realized");
g_warning ("Actor should not be mapped if parent "
"is not visible");
}
if (!(CLUTTER_PRIVATE_FLAGS (self->priv->parent_actor) &
if (!CLUTTER_ACTOR_IS_REALIZED (priv->parent_actor))
{
g_warning ("Actor should not be mapped if parent "
"is not realized");
}
if (!(CLUTTER_PRIVATE_FLAGS (priv->parent_actor) &
CLUTTER_ACTOR_IS_TOPLEVEL))
{
if (!CLUTTER_ACTOR_IS_MAPPED (self->priv->parent_actor))
g_warning ("Actor is mapped but its non-toplevel parent is not mapped");
if (!CLUTTER_ACTOR_IS_MAPPED (priv->parent_actor))
g_warning ("Actor is mapped but its non-toplevel "
"parent is not mapped");
}
}
}
}
}
#endif /* CLUTTER_ENABLE_DEBUG */
static void
clutter_actor_set_mapped (ClutterActor *self,
gboolean mapped)
@ -745,13 +767,28 @@ clutter_actor_update_map_state (ClutterActor *self,
}
}
/* if the actor has been set to be painted even if unmapped
* then we should map it and check for realization as well;
* this is an override for the branch of the scene graph
* which begins with this node
*/
if (priv->enable_paint_unmapped)
{
if (priv->parent_actor == NULL)
g_warning ("Attempting to map an unparented actor");
should_be_mapped = TRUE;
must_be_realized = TRUE;
}
if (!CLUTTER_ACTOR_IS_REALIZED (parent))
may_be_realized = FALSE;
}
if (change == MAP_STATE_MAKE_MAPPED && !should_be_mapped)
{
g_warning ("Attempting to map a child that does not meet the necessary invariants");
g_warning ("Attempting to map a child that does not "
"meet the necessary invariants");
}
/* If in reparent, we temporarily suspend unmap and unrealize.
@ -782,7 +819,8 @@ clutter_actor_update_map_state (ClutterActor *self,
if (should_be_mapped)
{
if (!must_be_realized)
g_warning ("Somehow we think an actor should be mapped but not realized, which isn't allowed");
g_warning ("Somehow we think an actor should be mapped but "
"not realized, which isn't allowed");
/* realization is allowed to fail (though I don't know what
* an app is supposed to do about that - shouldn't it just
@ -790,11 +828,9 @@ clutter_actor_update_map_state (ClutterActor *self,
* happens)
*/
if (CLUTTER_ACTOR_IS_REALIZED (self))
{
clutter_actor_set_mapped (self, TRUE);
}
}
}
/* check all invariants were kept */
clutter_actor_verify_map_state (self);
@ -950,7 +986,10 @@ clutter_actor_show (ClutterActor *self)
g_return_if_fail (CLUTTER_IS_ACTOR (self));
clutter_actor_verify_map_state (self); /* FIXME leave this for debugging only */
#ifdef CLUTTER_ENABLE_DEBUG
/* FIXME leave this for debugging only */
clutter_actor_verify_map_state (self);
#endif
priv = self->priv;
@ -1027,7 +1066,10 @@ clutter_actor_hide (ClutterActor *self)
g_return_if_fail (CLUTTER_IS_ACTOR (self));
clutter_actor_verify_map_state (self); /* FIXME leave this for debugging only */
#ifdef CLUTTER_ENABLE_DEBUG
/* FIXME leave this for debugging only */
clutter_actor_verify_map_state (self);
#endif
priv = self->priv;
@ -1092,7 +1134,10 @@ clutter_actor_realize (ClutterActor *self)
{
g_return_if_fail (CLUTTER_IS_ACTOR (self));
clutter_actor_verify_map_state (self); /* FIXME leave this for debugging only */
#ifdef CLUTTER_ENABLE_DEBUG
/* FIXME leave this for debugging only */
clutter_actor_verify_map_state (self);
#endif
if (CLUTTER_ACTOR_IS_REALIZED (self))
return;
@ -1183,7 +1228,10 @@ clutter_actor_unrealize (ClutterActor *self)
g_return_if_fail (CLUTTER_IS_ACTOR (self));
g_return_if_fail (!CLUTTER_ACTOR_IS_MAPPED (self));
clutter_actor_verify_map_state (self); /* FIXME leave this for debugging only */
#ifdef CLUTTER_ENABLE_DEBUG
/* FIXME leave this for debugging only */
clutter_actor_verify_map_state (self);
#endif
clutter_actor_hide (self);
@ -1265,7 +1313,10 @@ _clutter_actor_rerealize (ClutterActor *self,
g_return_if_fail (CLUTTER_IS_ACTOR (self));
clutter_actor_verify_map_state (self); /* FIXME leave this for debugging only */
#ifdef CLUTTER_ENABLE_DEBUG
/* FIXME leave this for debugging only */
clutter_actor_verify_map_state (self);
#endif
was_realized = CLUTTER_ACTOR_IS_REALIZED (self);
was_mapped = CLUTTER_ACTOR_IS_MAPPED (self);
@ -8931,6 +8982,24 @@ _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
self->priv->enable_model_view_transform = enable;
}
void
_clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
gboolean enable)
{
ClutterActorPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR (self));
priv = self->priv;
priv->enable_paint_unmapped = enable;
if (priv->enable_paint_unmapped)
clutter_actor_update_map_state (self, MAP_STATE_MAKE_MAPPED);
else
clutter_actor_update_map_state (self, MAP_STATE_MAKE_UNMAPPED);
}
static void
clutter_anchor_coord_get_units (ClutterActor *self,
const AnchorCoord *coord,

View File

@ -122,6 +122,7 @@ clutter_clone_paint (ClutterActor *self)
ClutterClonePrivate *priv = clone->priv;
ClutterGeometry geom, clone_geom;
gfloat x_scale, y_scale;
gboolean was_unmapped = FALSE;
if (G_UNLIKELY (priv->clone_source == NULL))
return;
@ -155,8 +156,17 @@ clutter_clone_paint (ClutterActor *self)
_clutter_actor_set_opacity_parent (priv->clone_source, self);
_clutter_actor_set_enable_model_view_transform (priv->clone_source, FALSE);
if (!CLUTTER_ACTOR_IS_MAPPED (priv->clone_source))
{
_clutter_actor_set_enable_paint_unmapped (priv->clone_source, TRUE);
was_unmapped = TRUE;
}
clutter_actor_paint (priv->clone_source);
if (was_unmapped)
_clutter_actor_set_enable_paint_unmapped (priv->clone_source, FALSE);
_clutter_actor_set_enable_model_view_transform (priv->clone_source, TRUE);
_clutter_actor_set_opacity_parent (priv->clone_source, NULL);
}

View File

@ -232,6 +232,9 @@ void _clutter_actor_set_opacity_parent (ClutterActor *self,
void _clutter_actor_set_enable_model_view_transform (ClutterActor *self,
gboolean enable);
void _clutter_actor_set_enable_paint_unmapped (ClutterActor *self,
gboolean enable);
G_END_DECLS
#endif /* _HAVE_CLUTTER_PRIVATE_H */