From 19cdba8abef53d9b3e6ad5337e0d2e76469fd72b Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 5 Jul 2021 17:20:35 +0200 Subject: [PATCH] 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. Part-of: --- 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 93181c333..9bcf5dd82 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 c5bc87ccc..c7d8a71b6 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 ab42a1745..338f8bf35 100644 --- a/clutter/clutter/clutter-stage.c +++ b/clutter/clutter/clutter-stage.c @@ -1015,7 +1015,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); }