[mutter/wip/carlosg/update-devices-in-view] clutter: Do not check redraw area for pointer repicks




commit 446da5afae0176fe64ad64bfe2906ae13e0e322a
Author: Carlos Garnacho <carlosg gnome org>
Date:   Wed Jan 26 18:39:27 2022 +0100

    clutter: Do not check redraw area for pointer repicks
    
    This looks like a relic of glReadPixels-based picking, the pointer
    might well be outside redrawn areas, yet still require a device
    update (e.g. in order to reflect the actor layout changes in the
    "clear area" info).
    
    Instead, always update all devices that are inside the view after
    relayouts, the tracking on the need for that update is now done
    on each ClutterStageView, instead of globally in the ClutterStage.
    
    This theoretically fixes situations where pointers might miss
    updating their "clear area" after the actor tree changed.
    
    Related: https://gitlab.gnome.org/GNOME/mutter/-/issues/2117

 clutter/clutter/clutter-stage-private.h      |  3 ++-
 clutter/clutter/clutter-stage-view-private.h |  2 ++
 clutter/clutter/clutter-stage-view.c         | 14 ++++++++++-
 clutter/clutter/clutter-stage.c              | 37 +++++++++++++++++-----------
 4 files changed, 39 insertions(+), 17 deletions(-)
---
diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h
index 50502845bf..efa341cc19 100644
--- a/clutter/clutter/clutter-stage-private.h
+++ b/clutter/clutter/clutter-stage-private.h
@@ -75,7 +75,8 @@ void                _clutter_stage_maybe_setup_viewport  (ClutterStage
                                                           ClutterStageView      *view);
 void                clutter_stage_maybe_relayout         (ClutterActor          *stage);
 void                clutter_stage_maybe_finish_queue_redraws (ClutterStage      *stage);
-GSList *            clutter_stage_find_updated_devices   (ClutterStage          *stage);
+GSList *            clutter_stage_find_updated_devices   (ClutterStage          *stage,
+                                                          ClutterStageView      *view);
 void                clutter_stage_update_devices         (ClutterStage          *stage,
                                                           GSList                *devices);
 void                clutter_stage_finish_layout          (ClutterStage          *stage);
diff --git a/clutter/clutter/clutter-stage-view-private.h b/clutter/clutter/clutter-stage-view-private.h
index 0a20d75b17..39d8601ea5 100644
--- a/clutter/clutter/clutter-stage-view-private.h
+++ b/clutter/clutter/clutter-stage-view-private.h
@@ -79,4 +79,6 @@ void clutter_stage_view_notify_presented (ClutterStageView *view,
 CLUTTER_EXPORT
 void clutter_stage_view_notify_ready (ClutterStageView *view);
 
+void clutter_stage_view_invalidate_input_devices (ClutterStageView *view);
+
 #endif /* __CLUTTER_STAGE_VIEW_PRIVATE_H__ */
diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c
index ea7f572480..8a82de71ed 100644
--- a/clutter/clutter/clutter-stage-view.c
+++ b/clutter/clutter/clutter-stage-view.c
@@ -93,6 +93,7 @@ typedef struct _ClutterStageViewPrivate
 
   guint dirty_viewport   : 1;
   guint dirty_projection : 1;
+  guint needs_update_devices : 1;
 } ClutterStageViewPrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (ClutterStageView, clutter_stage_view, G_TYPE_OBJECT)
@@ -1176,7 +1177,8 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
 
   clutter_stage_finish_layout (stage);
 
-  devices = clutter_stage_find_updated_devices (stage);
+  if (priv->needs_update_devices)
+    devices = clutter_stage_find_updated_devices (stage, view);
 
   frame = CLUTTER_FRAME_INIT;
 
@@ -1200,6 +1202,7 @@ handle_frame_clock_frame (ClutterFrameClock *frame_clock,
   _clutter_stage_window_finish_frame (stage_window, view, &frame);
 
   clutter_stage_update_devices (stage, devices);
+  priv->needs_update_devices = FALSE;
 
   _clutter_run_repaint_functions (CLUTTER_REPAINT_FLAGS_POST_PAINT);
   clutter_stage_emit_after_update (stage, view);
@@ -1522,3 +1525,12 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass)
 
   g_object_class_install_properties (object_class, PROP_LAST, obj_props);
 }
+
+void
+clutter_stage_view_invalidate_input_devices (ClutterStageView *view)
+{
+  ClutterStageViewPrivate *priv =
+    clutter_stage_view_get_instance_private (view);
+
+  priv->needs_update_devices = TRUE;
+}
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 3ef7ba69eb..b402952a15 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -127,7 +127,6 @@ struct _ClutterStagePrivate
 
   int update_freeze_count;
 
-  gboolean needs_update_devices;
   gboolean pending_finish_queue_redraws;
 
   GHashTable *pointer_devices;
@@ -785,6 +784,19 @@ clutter_stage_dequeue_actor_relayout (ClutterStage *stage,
     }
 }
 
+static void
+clutter_stage_invalidate_views_devices (ClutterStage *stage)
+{
+  GList *l;
+
+  for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
+    {
+      ClutterStageView *view = l->data;
+
+      clutter_stage_view_invalidate_input_devices (view);
+    }
+}
+
 void
 clutter_stage_maybe_relayout (ClutterActor *actor)
 {
@@ -832,36 +844,31 @@ clutter_stage_maybe_relayout (ClutterActor *actor)
   CLUTTER_NOTE (ACTOR, "<<< Completed recomputing layout of %d subtrees", count);
 
   if (count)
-    priv->needs_update_devices = TRUE;
+    clutter_stage_invalidate_views_devices (stage);
 }
 
 GSList *
-clutter_stage_find_updated_devices (ClutterStage *stage)
+clutter_stage_find_updated_devices (ClutterStage     *stage,
+                                    ClutterStageView *view)
 {
   ClutterStagePrivate *priv = stage->priv;
   GSList *updating = NULL;
   GHashTableIter iter;
   gpointer value;
 
-  if (!priv->needs_update_devices)
-    return NULL;
-
-  priv->needs_update_devices = FALSE;
-
   g_hash_table_iter_init (&iter, priv->pointer_devices);
   while (g_hash_table_iter_next (&iter, NULL, &value))
     {
       PointerDeviceEntry *entry = value;
-      ClutterStageView *view;
-      const cairo_region_t *clip;
+      ClutterStageView *pointer_view;
 
-      view = clutter_stage_get_view_at (stage, entry->coords.x, entry->coords.y);
-      if (!view)
+      pointer_view = clutter_stage_get_view_at (stage, entry->coords.x, entry->coords.y);
+      if (!pointer_view)
+        continue;
+      if (pointer_view != view)
         continue;
 
-      clip = clutter_stage_view_peek_redraw_clip (view);
-      if (!clip || cairo_region_contains_point (clip, entry->coords.x, entry->coords.y))
-        updating = g_slist_prepend (updating, entry->device);
+      updating = g_slist_prepend (updating, entry->device);
     }
 
   return updating;


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