clutter: Split pick and paint

Add the corresponding clutter_actor_pick() and
clutter_actor_continue_pick() as public APIs,
and use them in pick overrides and ClutterEffect.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/865
This commit is contained in:
Georges Basile Stavracas Neto 2019-10-17 17:01:25 +02:00
parent 98892391d7
commit 179d5ba6a6
5 changed files with 153 additions and 4 deletions

View File

@ -2373,7 +2373,7 @@ clutter_actor_real_pick (ClutterActor *self)
for (iter = self->priv->first_child;
iter != NULL;
iter = iter->priv->next_sibling)
clutter_actor_paint (iter);
clutter_actor_pick (iter);
}
}
@ -4215,6 +4215,149 @@ clutter_actor_continue_paint (ClutterActor *self)
}
}
/**
* clutter_actor_pick:
* @actor: A #ClutterActor
*
* Asks @actor to perform a pick.
*/
void
clutter_actor_pick (ClutterActor *actor)
{
ClutterActorPrivate *priv;
ClutterActorBox clip;
gboolean clip_set = FALSE;
if (CLUTTER_ACTOR_IN_DESTRUCTION (actor))
return;
priv = actor->priv;
/* if we aren't paintable (not in a toplevel with all
* parents paintable) then do nothing.
*/
if (!CLUTTER_ACTOR_IS_MAPPED (actor))
return;
clutter_actor_ensure_resource_scale (actor);
/* mark that we are in the paint process */
CLUTTER_SET_PRIVATE_FLAGS (actor, CLUTTER_IN_PICK);
cogl_push_matrix ();
if (priv->enable_model_view_transform)
{
CoglMatrix matrix;
cogl_get_modelview_matrix (&matrix);
_clutter_actor_apply_modelview_transform (actor, &matrix);
cogl_set_modelview_matrix (&matrix);
}
if (priv->has_clip)
{
clip.x1 = priv->clip.origin.x;
clip.y1 = priv->clip.origin.y;
clip.x2 = priv->clip.origin.x + priv->clip.size.width;
clip.y2 = priv->clip.origin.y + priv->clip.size.height;
clip_set = TRUE;
}
else if (priv->clip_to_allocation)
{
clip.x1 = 0.f;
clip.y1 = 0.f;
clip.x2 = priv->allocation.x2 - priv->allocation.x1;
clip.y2 = priv->allocation.y2 - priv->allocation.y1;
clip_set = TRUE;
}
if (clip_set)
clip_set = _clutter_actor_push_pick_clip (actor, &clip);
priv->next_effect_to_paint = NULL;
if (priv->effects)
{
priv->next_effect_to_paint =
_clutter_meta_group_peek_metas (priv->effects);
}
clutter_actor_continue_pick (actor);
if (clip_set)
_clutter_actor_pop_pick_clip (actor);
cogl_pop_matrix ();
/* paint sequence complete */
CLUTTER_UNSET_PRIVATE_FLAGS (actor, CLUTTER_IN_PICK);
}
/**
* clutter_actor_continue_pick:
* @actor: A #ClutterActor
*
* Run the next stage of the pick sequence. This function should only
* be called within the implementation of the pick virtual of a
* #ClutterEffect. It will cause the run method of the next effect to
* be applied, or it will pick the actual actor if the current effect
* is the last effect in the chain.
*/
void
clutter_actor_continue_pick (ClutterActor *actor)
{
ClutterActorPrivate *priv;
g_return_if_fail (CLUTTER_IS_ACTOR (actor));
g_return_if_fail (CLUTTER_ACTOR_IN_PICK (actor));
priv = actor->priv;
/* Skip any effects that are disabled */
while (priv->next_effect_to_paint &&
!clutter_actor_meta_get_enabled (priv->next_effect_to_paint->data))
priv->next_effect_to_paint = priv->next_effect_to_paint->next;
/* If this has come from the last effect then we'll just pick the
* actual actor.
*/
if (priv->next_effect_to_paint == NULL)
{
/* The actor will log a silhouette of itself to the stage pick log.
*
* XXX:2.0 - Call the pick() virtual directly
*/
if (g_signal_has_handler_pending (actor, actor_signals[PICK],
0, TRUE))
g_signal_emit (actor, actor_signals[PICK], 0);
else
CLUTTER_ACTOR_GET_CLASS (actor)->pick (actor);
}
else
{
ClutterEffect *old_current_effect;
ClutterEffectPaintFlags run_flags = 0;
/* Cache the current effect so that we can put it back before
* returning.
*/
old_current_effect = priv->current_effect;
priv->current_effect = priv->next_effect_to_paint->data;
priv->next_effect_to_paint = priv->next_effect_to_paint->next;
/* We can't determine when an actor has been modified since
* its last pick so lets just assume it has always been
* modified.
*/
run_flags |= CLUTTER_EFFECT_PAINT_ACTOR_DIRTY;
_clutter_effect_pick (priv->current_effect, run_flags);
priv->current_effect = old_current_effect;
}
}
static void
_clutter_actor_stop_transitions (ClutterActor *self)
{

View File

@ -353,6 +353,10 @@ void clutter_actor_paint
CLUTTER_EXPORT
void clutter_actor_continue_paint (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_pick (ClutterActor *actor);
CLUTTER_EXPORT
void clutter_actor_continue_pick (ClutterActor *actor);
CLUTTER_EXPORT
void clutter_actor_queue_redraw (ClutterActor *self);
CLUTTER_EXPORT
void clutter_actor_queue_redraw_with_clip (ClutterActor *self,

View File

@ -223,7 +223,7 @@ clutter_effect_real_pick (ClutterEffect *effect,
ClutterActor *actor;
actor = clutter_actor_meta_get_actor (actor_meta);
clutter_actor_continue_paint (actor);
clutter_actor_continue_pick (actor);
}
static void

View File

@ -67,6 +67,7 @@ typedef struct _ClutterVertex4 ClutterVertex4;
#define CLUTTER_ACTOR_IN_DESTRUCTION(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_DESTRUCTION) != FALSE)
#define CLUTTER_ACTOR_IN_REPARENT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_REPARENT) != FALSE)
#define CLUTTER_ACTOR_IN_PAINT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PAINT) != FALSE)
#define CLUTTER_ACTOR_IN_PICK(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PICK) != FALSE)
#define CLUTTER_ACTOR_IN_RELAYOUT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_RELAYOUT) != FALSE)
#define CLUTTER_ACTOR_IN_PREF_WIDTH(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_WIDTH) != FALSE)
#define CLUTTER_ACTOR_IN_PREF_HEIGHT(a) ((CLUTTER_PRIVATE_FLAGS (a) & CLUTTER_IN_PREF_HEIGHT) != FALSE)
@ -104,9 +105,10 @@ typedef enum
/* Used to avoid recursion */
CLUTTER_IN_PAINT = 1 << 5,
CLUTTER_IN_PICK = 1 << 6,
/* Used to avoid recursion */
CLUTTER_IN_RELAYOUT = 1 << 6,
CLUTTER_IN_RELAYOUT = 1 << 7,
} ClutterPrivateFlags;
/*

View File

@ -168,7 +168,7 @@ meta_surface_actor_pick (ClutterActor *actor)
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
clutter_actor_paint (child);
clutter_actor_pick (child);
}
static gboolean