[mutter/wip/carlosg/unthrottled-wayland: 15/16] clutter: Calculate "safe area" during pointer pick




commit e7f8330189b04e53872653ab2ff2ecb23e3de3b3
Author: Carlos Garnacho <carlosg gnome org>
Date:   Mon Jul 5 17:20:35 2021 +0200

    clutter: Calculate "safe area" during pointer pick
    
    This safe area is the region (in stage coordinates) where the pointer
    is ensured to stay within the current actor. This is not used yet, but
    will be used for optimizations in pointer picking.

 clutter/clutter/clutter-pick-stack-private.h |  7 ++-
 clutter/clutter/clutter-pick-stack.c         | 84 ++++++++++++++++++++++++++--
 clutter/clutter/clutter-stage.c              |  2 +-
 3 files changed, 85 insertions(+), 8 deletions(-)
---
diff --git a/clutter/clutter/clutter-pick-stack-private.h b/clutter/clutter/clutter-pick-stack-private.h
index 93181c3336..9bcf5dd82a 100644
--- a/clutter/clutter/clutter-pick-stack-private.h
+++ b/clutter/clutter/clutter-pick-stack-private.h
@@ -59,9 +59,10 @@ void clutter_pick_stack_get_transform (ClutterPickStack  *pick_stack,
 void clutter_pick_stack_pop_transform (ClutterPickStack *pick_stack);
 
 ClutterActor *
-clutter_pick_stack_search_actor (ClutterPickStack         *pick_stack,
-                                 const graphene_point3d_t *point,
-                                 const graphene_ray_t     *ray);
+clutter_pick_stack_search_actor (ClutterPickStack          *pick_stack,
+                                 const graphene_point3d_t  *point,
+                                 const graphene_ray_t      *ray,
+                                 cairo_region_t           **clear_area);
 
 G_DEFINE_AUTOPTR_CLEANUP_FUNC (ClutterPickStack, clutter_pick_stack_unref)
 
diff --git a/clutter/clutter/clutter-pick-stack.c b/clutter/clutter/clutter-pick-stack.c
index c5bc87ccca..c7d8a71b63 100644
--- a/clutter/clutter/clutter-pick-stack.c
+++ b/clutter/clutter/clutter-pick-stack.c
@@ -429,10 +429,82 @@ clutter_pick_stack_pop_transform (ClutterPickStack *pick_stack)
   cogl_matrix_stack_pop (pick_stack->matrix_stack);
 }
 
+static gboolean
+get_verts_rectangle (graphene_point3d_t     verts[4],
+                     cairo_rectangle_int_t *rect)
+{
+  if (verts[0].x != verts[2].x ||
+      verts[0].y != verts[1].y ||
+      verts[3].x != verts[1].x ||
+      verts[3].y != verts[2].y ||
+      verts[0].x > verts[3].x ||
+      verts[0].y > verts[3].y)
+    return FALSE;
+
+  *rect = (cairo_rectangle_int_t) {
+    .x = ceilf (verts[0].x),
+    .y = ceilf (verts[0].y),
+    .width = floor (verts[1].x - ceilf (verts[0].x)),
+    .height = floor (verts[2].y - ceilf (verts[0].y)),
+  };
+
+  return TRUE;
+}
+
+static void
+calculate_clear_area (ClutterPickStack  *pick_stack,
+                      int                elem,
+                      ClutterActor      *actor,
+                      cairo_region_t   **clear_area)
+{
+  cairo_region_t *area = NULL;
+  graphene_point3d_t verts[4];
+  cairo_rectangle_int_t rect;
+  int i;
+
+  clutter_actor_get_abs_allocation_vertices (actor,
+                                             (graphene_point3d_t *) &verts);
+  if (!get_verts_rectangle (verts, &rect))
+    {
+      if (clear_area)
+        *clear_area = NULL;
+      return;
+    }
+
+  area = cairo_region_create_rectangle (&rect);
+
+  for (i = elem + 1; i < pick_stack->vertices_stack->len; i++)
+    {
+      PickRecord *rec =
+        &g_array_index (pick_stack->vertices_stack, PickRecord, i);
+      ClutterActorBox paint_box;
+
+      if (!rec->is_overlap &&
+         (rec->base.rect.x1 == rec->base.rect.x2 ||
+          rec->base.rect.y1 == rec->base.rect.y2))
+        continue;
+
+      clutter_actor_get_paint_box (rec->actor, &paint_box);
+      cairo_region_subtract_rectangle (area,
+                                       &(cairo_rectangle_int_t) {
+                                         .x = paint_box.x1,
+                                         .y = paint_box.y1,
+                                         .width = paint_box.x2 - paint_box.x1,
+                                         .height = paint_box.y2 - paint_box.y1,
+                                       });
+    }
+
+  if (clear_area)
+    *clear_area = g_steal_pointer (&area);
+
+  g_clear_pointer (&area, cairo_region_destroy);
+}
+
 ClutterActor *
-clutter_pick_stack_search_actor (ClutterPickStack         *pick_stack,
-                                 const graphene_point3d_t *point,
-                                 const graphene_ray_t     *ray)
+clutter_pick_stack_search_actor (ClutterPickStack          *pick_stack,
+                                 const graphene_point3d_t  *point,
+                                 const graphene_ray_t      *ray,
+                                 cairo_region_t           **clear_area)
 {
   int i;
 
@@ -447,7 +519,11 @@ clutter_pick_stack_search_actor (ClutterPickStack         *pick_stack,
 
       if (!rec->is_overlap && rec->actor &&
           ray_intersects_record (pick_stack, rec, point, ray))
-        return rec->actor;
+        {
+          if (clear_area)
+            calculate_clear_area (pick_stack, i, rec->actor, clear_area);
+          return rec->actor;
+        }
     }
 
   return NULL;
diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c
index 9fc20d9bc6..e04f059e35 100644
--- a/clutter/clutter/clutter-stage.c
+++ b/clutter/clutter/clutter-stage.c
@@ -1082,7 +1082,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);
+  actor = clutter_pick_stack_search_actor (pick_stack, &p, &ray, NULL);
   return actor ? actor : CLUTTER_ACTOR (stage);
 }
 


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