clutter: Introduce pick contexts

Just as with painting, add a pick context that carries pick related
temporary state when doing actor picking. It is currently unused, and
will at least at first still carry around a framebuffer to deal track
view transforms etc.

https://gitlab.gnome.org/GNOME/mutter/merge_requests/935
This commit is contained in:
Jonas Ådahl 2019-11-20 21:46:41 +01:00 committed by Georges Basile Stavracas Neto
parent e8e5ccf82d
commit cb9d6b79ef
12 changed files with 218 additions and 29 deletions

View File

@ -1330,6 +1330,7 @@ _clutter_actor_transform_local_box_to_stage (ClutterActor *self,
/**
* clutter_actor_pick_box:
* @self: The #ClutterActor being "pick" painted.
* @pick_context: The #ClutterPickContext
* @box: A rectangle in the actor's own local coordinates.
*
* Logs (does a virtual paint of) a rectangle for picking. Note that @box is
@ -1340,6 +1341,7 @@ _clutter_actor_transform_local_box_to_stage (ClutterActor *self,
*/
void
clutter_actor_pick_box (ClutterActor *self,
ClutterPickContext *pick_context,
const ClutterActorBox *box)
{
ClutterStage *stage;
@ -2321,7 +2323,8 @@ _clutter_actor_rerealize (ClutterActor *self,
}
static void
clutter_actor_real_pick (ClutterActor *self)
clutter_actor_real_pick (ClutterActor *self,
ClutterPickContext *pick_context)
{
if (clutter_actor_should_pick_paint (self))
{
@ -2332,7 +2335,7 @@ clutter_actor_real_pick (ClutterActor *self)
.y2 = clutter_actor_get_height (self),
};
clutter_actor_pick_box (self, &box);
clutter_actor_pick_box (self, pick_context, &box);
}
/* XXX - this thoroughly sucks, but we need to maintain compatibility
@ -2349,7 +2352,7 @@ clutter_actor_real_pick (ClutterActor *self)
for (iter = self->priv->first_child;
iter != NULL;
iter = iter->priv->next_sibling)
clutter_actor_pick (iter);
clutter_actor_pick (iter, pick_context);
}
}
@ -4174,7 +4177,8 @@ clutter_actor_continue_paint (ClutterActor *self,
* Asks @actor to perform a pick.
*/
void
clutter_actor_pick (ClutterActor *actor)
clutter_actor_pick (ClutterActor *actor,
ClutterPickContext *pick_context)
{
ClutterActorPrivate *priv;
ClutterActorBox clip;
@ -4234,7 +4238,7 @@ clutter_actor_pick (ClutterActor *actor)
_clutter_meta_group_peek_metas (priv->effects);
}
clutter_actor_continue_pick (actor);
clutter_actor_continue_pick (actor, pick_context);
if (clip_set)
_clutter_actor_pop_pick_clip (actor);
@ -4256,7 +4260,8 @@ clutter_actor_pick (ClutterActor *actor)
* is the last effect in the chain.
*/
void
clutter_actor_continue_pick (ClutterActor *actor)
clutter_actor_continue_pick (ClutterActor *actor,
ClutterPickContext *pick_context)
{
ClutterActorPrivate *priv;
@ -4282,9 +4287,9 @@ clutter_actor_continue_pick (ClutterActor *actor)
*/
if (g_signal_has_handler_pending (actor, actor_signals[PICK],
0, TRUE))
g_signal_emit (actor, actor_signals[PICK], 0);
g_signal_emit (actor, actor_signals[PICK], 0, pick_context);
else
CLUTTER_ACTOR_GET_CLASS (actor)->pick (actor);
CLUTTER_ACTOR_GET_CLASS (actor)->pick (actor, pick_context);
}
else
{
@ -4298,7 +4303,7 @@ clutter_actor_continue_pick (ClutterActor *actor)
priv->current_effect = priv->next_effect_to_paint->data;
priv->next_effect_to_paint = priv->next_effect_to_paint->next;
_clutter_effect_pick (priv->current_effect);
_clutter_effect_pick (priv->current_effect, pick_context);
priv->current_effect = old_current_effect;
}
@ -8610,6 +8615,7 @@ clutter_actor_class_init (ClutterActorClass *klass)
/**
* ClutterActor::pick:
* @actor: the #ClutterActor that received the signal
* @pick_context: a #ClutterPickContext
*
* The ::pick signal is emitted each time an actor is being painted
* in "pick mode". The pick mode is used to identify the actor during
@ -8631,7 +8637,8 @@ clutter_actor_class_init (ClutterActorClass *klass)
G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED,
G_STRUCT_OFFSET (ClutterActorClass, pick),
NULL, NULL, NULL,
G_TYPE_NONE, 0);
G_TYPE_NONE, 1,
CLUTTER_TYPE_PICK_CONTEXT);
/**
* ClutterActor::allocation-changed:

View File

@ -40,6 +40,7 @@
#include <clutter/clutter-types.h>
#include <clutter/clutter-event.h>
#include <clutter/clutter-paint-context.h>
#include <clutter/clutter-pick-context.h>
G_BEGIN_DECLS
@ -235,7 +236,8 @@ struct _ClutterActorClass
ClutterActor *old_parent);
void (* destroy) (ClutterActor *self);
void (* pick) (ClutterActor *actor);
void (* pick) (ClutterActor *actor,
ClutterPickContext *pick_context);
gboolean (* queue_redraw) (ClutterActor *actor,
ClutterActor *leaf_that_queued,
@ -357,9 +359,11 @@ CLUTTER_EXPORT
void clutter_actor_continue_paint (ClutterActor *self,
ClutterPaintContext *paint_context);
CLUTTER_EXPORT
void clutter_actor_pick (ClutterActor *actor);
void clutter_actor_pick (ClutterActor *actor,
ClutterPickContext *pick_context);
CLUTTER_EXPORT
void clutter_actor_continue_pick (ClutterActor *actor);
void clutter_actor_continue_pick (ClutterActor *actor,
ClutterPickContext *pick_context);
CLUTTER_EXPORT
void clutter_actor_queue_redraw (ClutterActor *self);
CLUTTER_EXPORT
@ -911,6 +915,7 @@ void clutter_actor_bind_model_with_properties
CLUTTER_EXPORT
void clutter_actor_pick_box (ClutterActor *self,
ClutterPickContext *pick_context,
const ClutterActorBox *box);
G_END_DECLS

View File

@ -15,7 +15,8 @@ gboolean _clutter_effect_has_custom_paint_volume (ClutterEffect
void _clutter_effect_paint (ClutterEffect *effect,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags);
void _clutter_effect_pick (ClutterEffect *effect);
void _clutter_effect_pick (ClutterEffect *effect,
ClutterPickContext *pick_context);
G_END_DECLS

View File

@ -219,13 +219,14 @@ clutter_effect_real_paint (ClutterEffect *effect,
}
static void
clutter_effect_real_pick (ClutterEffect *effect)
clutter_effect_real_pick (ClutterEffect *effect,
ClutterPickContext *pick_context)
{
ClutterActorMeta *actor_meta = CLUTTER_ACTOR_META (effect);
ClutterActor *actor;
actor = clutter_actor_meta_get_actor (actor_meta);
clutter_actor_continue_pick (actor);
clutter_actor_continue_pick (actor, pick_context);
}
static void
@ -293,11 +294,12 @@ _clutter_effect_paint (ClutterEffect *effect,
}
void
_clutter_effect_pick (ClutterEffect *effect)
_clutter_effect_pick (ClutterEffect *effect,
ClutterPickContext *pick_context)
{
g_return_if_fail (CLUTTER_IS_EFFECT (effect));
CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect);
CLUTTER_EFFECT_GET_CLASS (effect)->pick (effect, pick_context);
}
gboolean

View File

@ -31,6 +31,7 @@
#include <clutter/clutter-actor-meta.h>
#include <clutter/clutter-paint-context.h>
#include <clutter/clutter-pick-context.h>
G_BEGIN_DECLS
@ -86,7 +87,8 @@ struct _ClutterEffectClass
void (* paint) (ClutterEffect *effect,
ClutterPaintContext *paint_context,
ClutterEffectPaintFlags flags);
void (* pick) (ClutterEffect *effect);
void (* pick) (ClutterEffect *effect,
ClutterPickContext *pick_context);
/*< private >*/
void (* _clutter_effect4) (void);

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_PICK_CONTEXT_PRIVATE_H
#define CLUTTER_PICK_CONTEXT_PRIVATE_H
#include "clutter-pick-context.h"
ClutterPickContext * clutter_pick_context_new_for_view (ClutterStageView *view);
#endif /* CLUTTER_PICK_CONTEXT_PRIVATE_H */

View File

@ -0,0 +1,83 @@
/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "clutter-build-config.h"
#include "clutter-pick-context-private.h"
struct _ClutterPickContext
{
grefcount ref_count;
CoglFramebuffer *framebuffer;
};
G_DEFINE_BOXED_TYPE (ClutterPickContext, clutter_pick_context,
clutter_pick_context_ref,
clutter_pick_context_unref)
ClutterPickContext *
clutter_pick_context_new_for_view (ClutterStageView *view)
{
ClutterPickContext *pick_context;
pick_context = g_new0 (ClutterPickContext, 1);
g_ref_count_init (&pick_context->ref_count);
pick_context->framebuffer =
cogl_object_ref (clutter_stage_view_get_framebuffer (view));
return pick_context;
}
ClutterPickContext *
clutter_pick_context_ref (ClutterPickContext *pick_context)
{
g_ref_count_inc (&pick_context->ref_count);
return pick_context;
}
static void
clutter_pick_context_dispose (ClutterPickContext *pick_context)
{
g_clear_pointer (&pick_context->framebuffer, cogl_object_unref);
}
void
clutter_pick_context_unref (ClutterPickContext *pick_context)
{
if (g_ref_count_dec (&pick_context->ref_count))
{
clutter_pick_context_dispose (pick_context);
g_free (pick_context);
}
}
void
clutter_pick_context_destroy (ClutterPickContext *pick_context)
{
clutter_pick_context_dispose (pick_context);
clutter_pick_context_unref (pick_context);
}
/**
* clutter_pick_context_get_framebuffer: (skip)
*/
CoglFramebuffer *
clutter_pick_context_get_framebuffer (ClutterPickContext *pick_context)
{
return pick_context->framebuffer;
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2019 Red Hat Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef CLUTTER_PICK_CONTEXT_H
#define CLUTTER_PICK_CONTEXT_H
#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION)
#error "Only <clutter/clutter.h> can be included directly."
#endif
#include <glib-object.h>
#include "clutter-macros.h"
#include "clutter-stage-view.h"
typedef struct _ClutterPickContext ClutterPickContext;
#define CLUTTER_TYPE_PICK_CONTEXT (clutter_pick_context_get_type ())
CLUTTER_EXPORT
GType clutter_pick_context_get_type (void);
CLUTTER_EXPORT
ClutterPickContext * clutter_pick_context_ref (ClutterPickContext *pick_context);
CLUTTER_EXPORT
void clutter_pick_context_unref (ClutterPickContext *pick_context);
CLUTTER_EXPORT
void clutter_pick_context_destroy (ClutterPickContext *pick_context);
CLUTTER_EXPORT
CoglFramebuffer * clutter_pick_context_get_framebuffer (ClutterPickContext *pick_context);
#endif /* CLUTTER_PICK_CONTEXT_H */

View File

@ -70,6 +70,7 @@
#include "clutter-mutter.h"
#include "clutter-paint-context-private.h"
#include "clutter-paint-volume-private.h"
#include "clutter-pick-context-private.h"
#include "clutter-private.h"
#include "clutter-stage-manager-private.h"
#include "clutter-stage-private.h"
@ -981,7 +982,8 @@ clutter_stage_paint (ClutterActor *self,
}
static void
clutter_stage_pick (ClutterActor *self)
clutter_stage_pick (ClutterActor *self,
ClutterPickContext *pick_context)
{
ClutterActorIter iter;
ClutterActor *child;
@ -992,7 +994,7 @@ clutter_stage_pick (ClutterActor *self)
*/
clutter_actor_iter_init (&iter, self);
while (clutter_actor_iter_next (&iter, &child))
clutter_actor_pick (child);
clutter_actor_pick (child, pick_context);
}
static gboolean
@ -1652,17 +1654,21 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage,
if (mode != priv->cached_pick_mode)
{
ClutterPickContext *pick_context;
_clutter_stage_clear_pick_stack (stage);
pick_context = clutter_pick_context_new_for_view (view);
cogl_push_framebuffer (fb);
context->pick_mode = mode;
setup_view_for_pick_or_paint (stage, view, NULL);
clutter_actor_pick (CLUTTER_ACTOR (stage));
clutter_actor_pick (CLUTTER_ACTOR (stage), pick_context);
context->pick_mode = CLUTTER_PICK_NONE;
priv->cached_pick_mode = mode;
cogl_pop_framebuffer ();
clutter_pick_context_destroy (pick_context);
add_pick_stack_weak_refs (stage);
}

View File

@ -292,14 +292,15 @@ clutter_group_real_paint (ClutterActor *actor,
}
static void
clutter_group_real_pick (ClutterActor *actor)
clutter_group_real_pick (ClutterActor *actor,
ClutterPickContext *pick_context)
{
ClutterGroupPrivate *priv = CLUTTER_GROUP (actor)->priv;
/* Chain up so we get a bounding box pained (if we are reactive) */
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor);
CLUTTER_ACTOR_CLASS (clutter_group_parent_class)->pick (actor, pick_context);
g_list_foreach (priv->children, (GFunc) clutter_actor_pick, NULL);
g_list_foreach (priv->children, (GFunc) clutter_actor_pick, pick_context);
}
static void

View File

@ -64,6 +64,7 @@ clutter_headers = [
'clutter-pan-action.h',
'clutter-path-constraint.h',
'clutter-path.h',
'clutter-pick-context.h',
'clutter-property-transition.h',
'clutter-rotate-action.h',
'clutter-script.h',
@ -153,6 +154,7 @@ clutter_sources = [
'clutter-pan-action.c',
'clutter-path-constraint.c',
'clutter-path.c',
'clutter-pick-context.c',
'clutter-property-transition.c',
'clutter-rotate-action.c',
'clutter-script.c',

View File

@ -131,7 +131,8 @@ meta_surface_actor_paint (ClutterActor *actor,
}
static void
meta_surface_actor_pick (ClutterActor *actor)
meta_surface_actor_pick (ClutterActor *actor,
ClutterPickContext *pick_context)
{
MetaSurfaceActor *self = META_SURFACE_ACTOR (actor);
MetaSurfaceActorPrivate *priv =
@ -144,7 +145,12 @@ meta_surface_actor_pick (ClutterActor *actor)
/* If there is no region then use the regular pick */
if (priv->input_region == NULL)
CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class)->pick (actor);
{
ClutterActorClass *actor_class =
CLUTTER_ACTOR_CLASS (meta_surface_actor_parent_class);
actor_class->pick (actor, pick_context);
}
else
{
int n_rects;
@ -163,14 +169,14 @@ meta_surface_actor_pick (ClutterActor *actor)
box.y1 = rect.y;
box.x2 = rect.x + rect.width;
box.y2 = rect.y + rect.height;
clutter_actor_pick_box (actor, &box);
clutter_actor_pick_box (actor, pick_context, &box);
}
}
clutter_actor_iter_init (&iter, actor);
while (clutter_actor_iter_next (&iter, &child))
clutter_actor_pick (child);
clutter_actor_pick (child, pick_context);
}
static gboolean