[mutter/gbsneto/screencast-improvements: 17/18] stage: Introduce MetaStageWatch and family



commit 9b5d9f3cb37a197000a04028a93400e06210f57c
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Mon Jun 17 21:43:05 2019 -0300

    stage: Introduce MetaStageWatch and family
    
    MetaStageWatch, watch modes and the watch function are part
    of the new stage view watching API. It's design does not
    rely on signals on purpose; the number of signals that would
    be emitted would be too high, and would impact performance.
    
    MetaStageWatch is an opaque structure outside of MetaStage.
    
    This will be used by the screencast code to monitor a single
    view, which has a one-to-one relatioship to logical monitors.
    
    https://gitlab.gnome.org/GNOME/mutter/merge_requests/623

 src/backends/meta-stage-private.h |  22 ++++++++
 src/backends/meta-stage.c         | 103 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 125 insertions(+)
---
diff --git a/src/backends/meta-stage-private.h b/src/backends/meta-stage-private.h
index 639d2372c..963017688 100644
--- a/src/backends/meta-stage-private.h
+++ b/src/backends/meta-stage-private.h
@@ -27,8 +27,21 @@
 
 G_BEGIN_DECLS
 
+typedef struct _MetaStageWatch MetaStageWatch;
 typedef struct _MetaOverlay    MetaOverlay;
 
+typedef enum
+{
+  META_STAGE_WATCH_BEFORE_PAINT,
+  META_STAGE_WATCH_AFTER_ACTOR_PAINT,
+  META_STAGE_WATCH_AFTER_OVERLAY_PAINT,
+  META_STAGE_WATCH_AFTER_PAINT,
+} MetaStageWatchPhase;
+
+typedef void (* MetaStageWatchFunc) (MetaStage        *stage,
+                                     ClutterStageView *view,
+                                     gpointer          user_data);
+
 ClutterActor     *meta_stage_new                     (MetaBackend *backend);
 
 MetaOverlay      *meta_stage_create_cursor_overlay   (MetaStage   *stage);
@@ -43,6 +56,15 @@ void              meta_stage_update_cursor_overlay   (MetaStage   *stage,
 void meta_stage_set_active (MetaStage *stage,
                             gboolean   is_active);
 
+MetaStageWatch * meta_stage_watch_view (MetaStage           *stage,
+                                        ClutterStageView    *view,
+                                        MetaStageWatchPhase  watch_mode,
+                                        MetaStageWatchFunc   callback,
+                                        gpointer             user_data);
+
+void meta_stage_remove_watch (MetaStage      *stage,
+                              MetaStageWatch *watch);
+
 G_END_DECLS
 
 #endif /* META_STAGE_PRIVATE_H */
diff --git a/src/backends/meta-stage.c b/src/backends/meta-stage.c
index a98cbc7e2..47922f1f3 100644
--- a/src/backends/meta-stage.c
+++ b/src/backends/meta-stage.c
@@ -30,6 +30,8 @@
 #include "meta/meta-monitor-manager.h"
 #include "meta/util.h"
 
+#define N_WATCH_MODES 4
+
 enum
 {
   ACTORS_PAINTED,
@@ -39,6 +41,13 @@ enum
 
 static guint signals[N_SIGNALS];
 
+struct _MetaStageWatch
+{
+  ClutterStageView *view;
+  MetaStageWatchFunc callback;
+  gpointer user_data;
+};
+
 struct _MetaOverlay
 {
   gboolean enabled;
@@ -55,6 +64,9 @@ struct _MetaStage
 {
   ClutterStage parent;
 
+  GPtrArray *watchers[N_WATCH_MODES];
+  ClutterStageView *current_view;
+
   GList *overlays;
   gboolean is_active;
 };
@@ -135,6 +147,7 @@ meta_stage_finalize (GObject *object)
 {
   MetaStage *stage = META_STAGE (object);
   GList *l;
+  int i;
 
   l = stage->overlays;
   while (l)
@@ -143,9 +156,33 @@ meta_stage_finalize (GObject *object)
       l = g_list_delete_link (l, l);
     }
 
+  for (i = 0; i < N_WATCH_MODES; i++)
+    g_clear_pointer (&stage->watchers[i], g_ptr_array_unref);
+
   G_OBJECT_CLASS (meta_stage_parent_class)->finalize (object);
 }
 
+static void
+notify_watchers_for_mode (MetaStage           *stage,
+                          ClutterStageView    *view,
+                          MetaStageWatchPhase  watch_phase)
+{
+  GPtrArray *watchers;
+  int i;
+
+  watchers = stage->watchers[watch_phase];
+
+  for (i = 0; i < watchers->len; i++)
+    {
+      MetaStageWatch *watch = g_ptr_array_index (watchers, i);
+
+      if (watch->view && view != watch->view)
+        continue;
+
+      watch->callback (stage, view, watch->user_data);
+    }
+}
+
 static void
 meta_stage_paint (ClutterActor *actor)
 {
@@ -154,10 +191,30 @@ meta_stage_paint (ClutterActor *actor)
 
   CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor);
 
+  notify_watchers_for_mode (stage, stage->current_view,
+                            META_STAGE_WATCH_AFTER_ACTOR_PAINT);
+
   g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
 
   for (l = stage->overlays; l; l = l->next)
     meta_overlay_paint (l->data);
+
+  notify_watchers_for_mode (stage, stage->current_view,
+                            META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
+}
+
+static void
+meta_stage_paint_view (ClutterStage     *stage,
+                       ClutterStageView *view)
+{
+  MetaStage *meta_stage = META_STAGE (stage);
+
+  notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_BEFORE_PAINT);
+
+  meta_stage->current_view = view;
+  CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view);
+
+  notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_AFTER_PAINT);
 }
 
 static void
@@ -202,6 +259,7 @@ meta_stage_class_init (MetaStageClass *klass)
 
   stage_class->activate = meta_stage_activate;
   stage_class->deactivate = meta_stage_deactivate;
+  stage_class->paint_view = meta_stage_paint_view;
 
   signals[ACTORS_PAINTED] = g_signal_new ("actors-painted",
                                           G_TYPE_FROM_CLASS (klass),
@@ -214,6 +272,10 @@ meta_stage_class_init (MetaStageClass *klass)
 static void
 meta_stage_init (MetaStage *stage)
 {
+  int i;
+
+  for (i = 0; i < N_WATCH_MODES; i++)
+    stage->watchers[i] = g_ptr_array_new_with_free_func (g_free);
 }
 
 ClutterActor *
@@ -345,3 +407,44 @@ meta_stage_set_active (MetaStage *stage,
    */
   clutter_stage_event (CLUTTER_STAGE (stage), &event);
 }
+
+MetaStageWatch *
+meta_stage_watch_view (MetaStage           *stage,
+                       ClutterStageView    *view,
+                       MetaStageWatchPhase  watch_phase,
+                       MetaStageWatchFunc   callback,
+                       gpointer             user_data)
+{
+  MetaStageWatch *watch;
+  GPtrArray *watchers;
+
+  watch = g_new0 (MetaStageWatch, 1);
+  watch->view = view;
+  watch->callback = callback;
+  watch->user_data = user_data;
+
+  watchers = stage->watchers[watch_phase];
+  g_ptr_array_add (watchers, watch);
+
+  return watch;
+}
+
+void
+meta_stage_remove_watch (MetaStage      *stage,
+                         MetaStageWatch *watch)
+{
+  GPtrArray *watchers;
+  gboolean removed = FALSE;
+  int i;
+
+  for (i = 0; i < N_WATCH_MODES; i++)
+    {
+      watchers = stage->watchers[i];
+      removed = g_ptr_array_remove_fast (watchers, watch);
+
+      if (removed)
+        break;
+    }
+
+  g_assert (removed);
+}


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