diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index 95b7b1f15..75f1a0136 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -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: diff --git a/clutter/clutter/clutter-actor.h b/clutter/clutter/clutter-actor.h index 41082cf61..bb968ddd0 100644 --- a/clutter/clutter/clutter-actor.h +++ b/clutter/clutter/clutter-actor.h @@ -40,6 +40,7 @@ #include #include #include +#include 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 diff --git a/clutter/clutter/clutter-effect-private.h b/clutter/clutter/clutter-effect-private.h index 5b3874613..f081a0535 100644 --- a/clutter/clutter/clutter-effect-private.h +++ b/clutter/clutter/clutter-effect-private.h @@ -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 diff --git a/clutter/clutter/clutter-effect.c b/clutter/clutter/clutter-effect.c index fe355d24e..cde26fc4d 100644 --- a/clutter/clutter/clutter-effect.c +++ b/clutter/clutter/clutter-effect.c @@ -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 diff --git a/clutter/clutter/clutter-effect.h b/clutter/clutter/clutter-effect.h index 50e06f889..8e8b57b92 100644 --- a/clutter/clutter/clutter-effect.h +++ b/clutter/clutter/clutter-effect.h @@ -31,6 +31,7 @@ #include #include +#include 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); diff --git a/clutter/clutter/clutter-pick-context-private.h b/clutter/clutter/clutter-pick-context-private.h new file mode 100644 index 000000000..4e6db156b --- /dev/null +++ b/clutter/clutter/clutter-pick-context-private.h @@ -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 . + */ + +#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 */ diff --git a/clutter/clutter/clutter-pick-context.c b/clutter/clutter/clutter-pick-context.c new file mode 100644 index 000000000..a02d6e795 --- /dev/null +++ b/clutter/clutter/clutter-pick-context.c @@ -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 . + */ + +#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; +} diff --git a/clutter/clutter/clutter-pick-context.h b/clutter/clutter/clutter-pick-context.h new file mode 100644 index 000000000..a1f8dec41 --- /dev/null +++ b/clutter/clutter/clutter-pick-context.h @@ -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 . + */ + +#ifndef CLUTTER_PICK_CONTEXT_H +#define CLUTTER_PICK_CONTEXT_H + +#if !defined(__CLUTTER_H_INSIDE__) && !defined(CLUTTER_COMPILATION) +#error "Only can be included directly." +#endif + +#include + +#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 */ diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c index ba573a08b..14838bd2b 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -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); } diff --git a/clutter/clutter/deprecated/clutter-group.c b/clutter/clutter/deprecated/clutter-group.c index ac52916dd..af602fd51 100644 --- a/clutter/clutter/deprecated/clutter-group.c +++ b/clutter/clutter/deprecated/clutter-group.c @@ -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 diff --git a/clutter/clutter/meson.build b/clutter/clutter/meson.build index 2a2e0a103..8173ad923 100644 --- a/clutter/clutter/meson.build +++ b/clutter/clutter/meson.build @@ -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', diff --git a/src/compositor/meta-surface-actor.c b/src/compositor/meta-surface-actor.c index a2f95ef26..104daf9a1 100644 --- a/src/compositor/meta-surface-actor.c +++ b/src/compositor/meta-surface-actor.c @@ -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