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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1915>
This commit is contained in:
parent
5428b96f1b
commit
19cdba8abe
@ -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)
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user