[mutter/wip/texture-purge-on-nvidia: 12/17] clutter-stage: add mechanism for peeking at queued events



commit 02e3192a06b7f9117fe4ce7bcae281d731471cb8
Author: Ray Strode <rstrode redhat com>
Date:   Wed Jan 9 16:52:05 2019 -0500

    clutter-stage: add mechanism for peeking at queued events
    
    We need to be able to see events when they're queued, not
    when they're dispatched for updating idle time.  This is
    because events aren't dispatched when the frame clock is
    frozen, and we don't unfreeze the frame clock until the
    user idletime is updated.
    
    This commit adds a mechanism for peeking at queued events.
    A future commit will use that mechanism for fixing idletime
    bookkeeping.

 clutter/clutter/clutter-stage.c | 73 +++++++++++++++++++++++++++++++++++++++++
 clutter/clutter/clutter-stage.h |  9 +++++
 2 files changed, 82 insertions(+)
---
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 9352f49e8..e01aa2adf 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -105,6 +105,11 @@ struct _ClutterStageQueueRedrawEntry
   ClutterPaintVolume clip;
 };
 
+typedef struct _ClutterStageEventFilter {
+  ClutterEventFilterFunc func;
+  gpointer user_data;
+} ClutterStageEventFilter;
+
 struct _ClutterStagePrivate
 {
   /* the stage implementation */
@@ -149,6 +154,8 @@ struct _ClutterStagePrivate
   gpointer paint_data;
   GDestroyNotify paint_notify;
 
+  GList *event_filters;
+
   guint relayout_pending       : 1;
   guint redraw_pending         : 1;
   guint is_fullscreen          : 1;
@@ -204,6 +211,8 @@ static void clutter_stage_maybe_finish_queue_redraws (ClutterStage *stage);
 static void free_queue_redraw_entry (ClutterStageQueueRedrawEntry *entry);
 
 static void clutter_container_iface_init (ClutterContainerIface *iface);
+static gboolean clutter_stage_process_filters (ClutterStage *stage,
+                                               ClutterEvent *event);
 
 G_DEFINE_TYPE_WITH_CODE (ClutterStage, clutter_stage, CLUTTER_TYPE_GROUP,
                          G_ADD_PRIVATE (ClutterStage)
@@ -919,6 +928,12 @@ _clutter_stage_queue_event (ClutterStage *stage,
       _clutter_input_device_set_state (device, event_state);
       _clutter_input_device_set_time (device, event_time);
     }
+
+  if (clutter_stage_process_filters (stage, event) == CLUTTER_EVENT_STOP)
+    {
+      g_queue_pop_tail (priv->event_queue);
+      clutter_event_free (event);
+    }
 }
 
 gboolean
@@ -4903,3 +4918,61 @@ clutter_stage_capture_into (ClutterStage          *stage,
   view = get_view_at_rect (stage, rect);
   capture_view_into (stage, paint, view, rect, data, rect->width * bpp);
 }
+
+static gboolean
+clutter_stage_process_filters (ClutterStage *self,
+                               ClutterEvent *event)
+{
+  GList *l, *next;
+  ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
+
+  /* Event filters are handled in order from least recently added to
+   * most recently added */
+
+  for (l = priv->event_filters; l; l = next)
+    {
+      ClutterStageEventFilter *event_filter = l->data;
+
+      next = l->next;
+
+      if (event_filter->func (event, event_filter->user_data) == CLUTTER_EVENT_STOP)
+        return CLUTTER_EVENT_STOP;
+    }
+
+  return CLUTTER_EVENT_PROPAGATE;
+}
+
+void
+clutter_stage_add_filter (ClutterStage          *self,
+                          ClutterEventFilterFunc func,
+                          gpointer               user_data)
+{
+  ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
+  ClutterStageEventFilter *event_filter = g_slice_new (ClutterStageEventFilter);
+  static guint event_filter_id = 0;
+
+  event_filter->func = func;
+  event_filter->user_data = user_data;
+
+  priv->event_filters = g_list_append (priv->event_filters, event_filter);
+}
+
+void
+clutter_stage_remove_filter (ClutterStage           *self,
+                            ClutterEventFilterFunc  func,
+                            gpointer                user_data)
+{
+  ClutterStagePrivate *priv = CLUTTER_STAGE (self)->priv;
+  GList *l;
+
+  for (l = priv->event_filters; l; l = l->next)
+    {
+      ClutterStageEventFilter *event_filter = l->data;
+
+      if (event_filter->func == func && event_filter->user_data == user_data)
+        {
+          priv->event_filters = g_list_delete_link (priv->event_filters, l);
+          g_slice_free (ClutterStageEventFilter, event_filter);
+        }
+    }
+}
diff --git a/clutter/clutter/clutter-stage.h b/clutter/clutter/clutter-stage.h
index e8fbda84c..5bc31cb1d 100644
--- a/clutter/clutter/clutter-stage.h
+++ b/clutter/clutter/clutter-stage.h
@@ -265,6 +265,15 @@ gboolean clutter_stage_capture (ClutterStage          *stage,
                                 ClutterCapture       **captures,
                                 int                   *n_captures);
 
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_stage_add_filter (ClutterStage          *self,
+                               ClutterEventFilterFunc func,
+                               gpointer               user_data);
+CLUTTER_AVAILABLE_IN_MUTTER
+void clutter_stage_remove_filter (ClutterStage           *self,
+                                  ClutterEventFilterFunc  func,
+                                  gpointer                user_data);
+
 G_END_DECLS
 
 #endif /* __CLUTTER_STAGE_H__ */


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