[mutter/wip/carlosg/unthrottled-wayland: 60/65] clutter: Store the per-pointer picked actor's clear area




commit 78b877b525f7db9e6fb75b33621077bb1d6bf3af
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Jul 5 17:23:21 2021 +0200

    clutter: Store the per-pointer picked actor's clear area
    
    And resort to it first, unless we are told to ignore the cache
    (e.g. after relayouts). This avoids further pick context operations
    while the pointer is on the current actor.

 clutter/clutter/clutter-main.c          |  1 +
 clutter/clutter/clutter-mutter.h        |  1 +
 clutter/clutter/clutter-stage-private.h |  4 +-
 clutter/clutter/clutter-stage.c         | 84 +++++++++++++++++++++++++++------
 4 files changed, 74 insertions(+), 16 deletions(-)
---
diff --git a/clutter/clutter/clutter-main.c b/clutter/clutter/clutter-main.c
index 574959f844..ae8eae3319 100644
--- a/clutter/clutter/clutter-main.c
+++ b/clutter/clutter/clutter-main.c
@@ -900,6 +900,7 @@ remove_device_for_event (ClutterStage *stage,
                                point,
                                time,
                                NULL,
+                               NULL,
                                TRUE);
 
   clutter_stage_remove_device_entry (stage, device, sequence);
diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h
index 1b5d216797..b383ff518c 100644
--- a/clutter/clutter/clutter-mutter.h
+++ b/clutter/clutter/clutter-mutter.h
@@ -108,6 +108,7 @@ void clutter_stage_update_device (ClutterStage         *stage,
                                   graphene_point_t      point,
                                   uint32_t              time,
                                   ClutterActor         *new_actor,
+                                  cairo_region_t       *region,
                                   gboolean              emit_crossing);
 
 CLUTTER_EXPORT
diff --git a/clutter/clutter/clutter-stage-private.h b/clutter/clutter/clutter-stage-private.h
index 0fc4711b03..ac8e515171 100644
--- a/clutter/clutter/clutter-stage-private.h
+++ b/clutter/clutter/clutter-stage-private.h
@@ -35,6 +35,7 @@ typedef enum
 {
   CLUTTER_DEVICE_UPDATE_NONE = 0,
   CLUTTER_DEVICE_UPDATE_EMIT_CROSSING = 1 << 0,
+  CLUTTER_DEVICE_UPDATE_IGNORE_CACHE = 1 << 1,
 } ClutterDeviceUpdateFlags;
 
 /* stage */
@@ -135,7 +136,8 @@ void clutter_stage_update_device_entry (ClutterStage         *self,
                                         ClutterInputDevice   *device,
                                         ClutterEventSequence *sequence,
                                         graphene_point_t      coords,
-                                        ClutterActor         *actor);
+                                        ClutterActor         *actor,
+                                        cairo_region_t       *clear_area);
 
 void clutter_stage_remove_device_entry (ClutterStage         *self,
                                         ClutterInputDevice   *device,
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 338f8bf35a..03c7205a20 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -96,6 +96,7 @@ typedef struct _PointerDeviceEntry
   ClutterEventSequence *sequence;
   graphene_point_t coords;
   ClutterActor *current_actor;
+  cairo_region_t *clear_area;
 } PointerDeviceEntry;
 
 struct _ClutterStagePrivate
@@ -917,6 +918,7 @@ clutter_stage_update_devices (ClutterStage *stage,
       clutter_stage_pick_and_update_device (stage,
                                             device,
                                             NULL,
+                                            CLUTTER_DEVICE_UPDATE_IGNORE_CACHE |
                                             CLUTTER_DEVICE_UPDATE_EMIT_CROSSING,
                                             entry->coords,
                                             CLUTTER_CURRENT_TIME);
@@ -993,11 +995,12 @@ setup_ray_for_coordinates (ClutterStage       *stage,
 }
 
 static ClutterActor *
-_clutter_stage_do_pick_on_view (ClutterStage     *stage,
-                                float             x,
-                                float             y,
-                                ClutterPickMode   mode,
-                                ClutterStageView *view)
+_clutter_stage_do_pick_on_view (ClutterStage      *stage,
+                                float              x,
+                                float              y,
+                                ClutterPickMode    mode,
+                                ClutterStageView  *view,
+                                cairo_region_t   **clear_area)
 {
   g_autoptr (ClutterPickStack) pick_stack = NULL;
   ClutterPickContext *pick_context;
@@ -1015,7 +1018,7 @@ _clutter_stage_do_pick_on_view (ClutterStage     *stage,
   pick_stack = clutter_pick_context_steal_stack (pick_context);
   clutter_pick_context_destroy (pick_context);
 
-  actor = clutter_pick_stack_search_actor (pick_stack, &p, &ray, NULL);
+  actor = clutter_pick_stack_search_actor (pick_stack, &p, &ray, clear_area);
   return actor ? actor : CLUTTER_ACTOR (stage);
 }
 
@@ -1047,10 +1050,11 @@ clutter_stage_get_view_at (ClutterStage *stage,
 }
 
 static ClutterActor *
-_clutter_stage_do_pick (ClutterStage   *stage,
-                        float           x,
-                        float           y,
-                        ClutterPickMode mode)
+_clutter_stage_do_pick (ClutterStage     *stage,
+                        float             x,
+                        float             y,
+                        ClutterPickMode   mode,
+                        cairo_region_t  **clear_area)
 {
   ClutterActor *actor = CLUTTER_ACTOR (stage);
   ClutterStagePrivate *priv = stage->priv;
@@ -1074,7 +1078,7 @@ _clutter_stage_do_pick (ClutterStage   *stage,
 
   view = clutter_stage_get_view_at (stage, x, y);
   if (view)
-    return _clutter_stage_do_pick_on_view (stage, x, y, mode, view);
+    return _clutter_stage_do_pick_on_view (stage, x, y, mode, view, clear_area);
 
   return actor;
 }
@@ -1914,7 +1918,7 @@ clutter_stage_get_actor_at_pos (ClutterStage    *stage,
 {
   g_return_val_if_fail (CLUTTER_IS_STAGE (stage), NULL);
 
-  return _clutter_stage_do_pick (stage, x, y, pick_mode);
+  return _clutter_stage_do_pick (stage, x, y, pick_mode, NULL);
 }
 
 /**
@@ -3252,6 +3256,7 @@ on_device_actor_reactive_changed (ClutterActor       *actor,
   clutter_stage_pick_and_update_device (self,
                                         entry->device,
                                         entry->sequence,
+                                        CLUTTER_DEVICE_UPDATE_IGNORE_CACHE |
                                         CLUTTER_DEVICE_UPDATE_EMIT_CROSSING,
                                         entry->coords,
                                         CLUTTER_CURRENT_TIME);
@@ -3269,6 +3274,7 @@ on_device_actor_destroyed (ClutterActor       *actor,
    * trigger a repick here.
    */
   entry->current_actor = NULL;
+  g_clear_pointer (&entry->clear_area, cairo_region_destroy);
 }
 
 static void
@@ -3288,6 +3294,8 @@ free_pointer_device_entry (PointerDeviceEntry *entry)
       _clutter_actor_set_has_pointer (actor, FALSE);
    }
 
+  g_clear_pointer (&entry->clear_area, cairo_region_destroy);
+
   g_free (entry);
 }
 
@@ -3296,7 +3304,8 @@ clutter_stage_update_device_entry (ClutterStage         *self,
                                    ClutterInputDevice   *device,
                                    ClutterEventSequence *sequence,
                                    graphene_point_t      coords,
-                                   ClutterActor         *actor)
+                                   ClutterActor         *actor,
+                                   cairo_region_t       *clear_area)
 {
   ClutterStagePrivate *priv = self->priv;
   PointerDeviceEntry *entry = NULL;
@@ -3352,6 +3361,10 @@ clutter_stage_update_device_entry (ClutterStage         *self,
           _clutter_actor_set_has_pointer (actor, TRUE);
         }
     }
+
+  g_clear_pointer (&entry->clear_area, cairo_region_destroy);
+  if (clear_area)
+    entry->clear_area = cairo_region_reference (clear_area);
 }
 
 void
@@ -3469,6 +3482,7 @@ clutter_stage_update_device (ClutterStage         *stage,
                              graphene_point_t      point,
                              uint32_t              time_ms,
                              ClutterActor         *new_actor,
+                             cairo_region_t       *clear_area,
                              gboolean              emit_crossing)
 {
   ClutterInputDeviceType device_type;
@@ -3486,7 +3500,8 @@ clutter_stage_update_device (ClutterStage         *stage,
   clutter_stage_update_device_entry (stage,
                                      device, sequence,
                                      point,
-                                     new_actor);
+                                     new_actor,
+                                     clear_area);
 
   if (device_actor_changed)
     {
@@ -3527,11 +3542,38 @@ clutter_stage_repick_device (ClutterStage       *stage,
   clutter_stage_pick_and_update_device (stage,
                                         device,
                                         NULL,
+                                        CLUTTER_DEVICE_UPDATE_IGNORE_CACHE |
                                         CLUTTER_DEVICE_UPDATE_EMIT_CROSSING,
                                         point,
                                         CLUTTER_CURRENT_TIME);
 }
 
+static gboolean
+clutter_stage_check_in_clear_area (ClutterStage         *stage,
+                                   ClutterInputDevice   *device,
+                                   ClutterEventSequence *sequence,
+                                   graphene_point_t      point)
+{
+  ClutterStagePrivate *priv = stage->priv;
+  PointerDeviceEntry *entry = NULL;
+
+  g_return_val_if_fail (CLUTTER_IS_STAGE (stage), FALSE);
+  g_return_val_if_fail (device != NULL, FALSE);
+
+  if (sequence != NULL)
+    entry = g_hash_table_lookup (priv->touch_sequences, sequence);
+  else
+    entry = g_hash_table_lookup (priv->pointer_devices, device);
+
+  if (!entry)
+    return FALSE;
+  if (!entry->clear_area)
+    return FALSE;
+
+  return cairo_region_contains_point (entry->clear_area,
+                                      point.x, point.y);
+}
+
 ClutterActor *
 clutter_stage_pick_and_update_device (ClutterStage             *stage,
                                       ClutterInputDevice       *device,
@@ -3541,11 +3583,20 @@ clutter_stage_pick_and_update_device (ClutterStage             *stage,
                                       uint32_t                  time_ms)
 {
   ClutterActor *new_actor;
+  cairo_region_t *clear_area = NULL;
+
+  if ((flags & CLUTTER_DEVICE_UPDATE_IGNORE_CACHE) == 0)
+    {
+      if (clutter_stage_check_in_clear_area (stage, device,
+                                             sequence, point))
+        return clutter_stage_get_device_actor (stage, device, sequence);
+    }
 
   new_actor = _clutter_stage_do_pick (stage,
                                       point.x,
                                       point.y,
-                                      CLUTTER_PICK_REACTIVE);
+                                      CLUTTER_PICK_REACTIVE,
+                                      &clear_area);
 
   /* Picking should never fail, but if it does, we bail out here */
   g_return_val_if_fail (new_actor != NULL, NULL);
@@ -3555,7 +3606,10 @@ clutter_stage_pick_and_update_device (ClutterStage             *stage,
                                point,
                                time_ms,
                                new_actor,
+                               clear_area,
                                !!(flags & CLUTTER_DEVICE_UPDATE_EMIT_CROSSING));
 
+  g_clear_pointer (&clear_area, cairo_region_destroy);
+
   return new_actor;
 }


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