[mutter] clutter: Introduce pick contexts



commit cb9d6b79ef884255062b61facf25c618e3a9aaf6
Author: Jonas Ã…dahl <jadahl gmail com>
Date:   Wed Nov 20 21:46:41 2019 +0100

    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

 clutter/clutter/clutter-actor.c                | 27 +++++----
 clutter/clutter/clutter-actor.h                | 11 +++-
 clutter/clutter/clutter-effect-private.h       |  3 +-
 clutter/clutter/clutter-effect.c               | 10 ++--
 clutter/clutter/clutter-effect.h               |  4 +-
 clutter/clutter/clutter-pick-context-private.h | 25 ++++++++
 clutter/clutter/clutter-pick-context.c         | 83 ++++++++++++++++++++++++++
 clutter/clutter/clutter-pick-context.h         | 49 +++++++++++++++
 clutter/clutter/clutter-stage.c                | 12 +++-
 clutter/clutter/deprecated/clutter-group.c     |  7 ++-
 clutter/clutter/meson.build                    |  2 +
 src/compositor/meta-surface-actor.c            | 14 +++--
 12 files changed, 218 insertions(+), 29 deletions(-)
---
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 <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
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 <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);
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 <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 */
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 <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;
+}
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 <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 */
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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]