backends/native: Allow infinitely small pointer constraint regions

The small catch is that MtkRegion (and pixman regions) "optimize away"
0-size rectangles, so a 0-sized region will always be seen as having
a 0,0 origin. We don't want that, so transfer the origin separately from
the region.

While at it, make the Wayland pointer lock use one such 0-size region,
to avoid the 1x1px wiggle room that it currently has (accounting for subpixel
motion).

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3420>
This commit is contained in:
Carlos Garnacho 2023-11-17 18:15:27 +01:00 committed by Robert Mader
parent c931ed0d81
commit 07d24fe502
7 changed files with 47 additions and 15 deletions

View File

@ -48,6 +48,7 @@ struct _MetaPointerConstraint
{ {
GObject parent_instance; GObject parent_instance;
MtkRegion *region; MtkRegion *region;
graphene_point_t origin;
double min_edge_distance; double min_edge_distance;
}; };
@ -82,20 +83,26 @@ meta_pointer_constraint_class_init (MetaPointerConstraintClass *klass)
MetaPointerConstraint * MetaPointerConstraint *
meta_pointer_constraint_new (const MtkRegion *region, meta_pointer_constraint_new (const MtkRegion *region,
graphene_point_t origin,
double min_edge_distance) double min_edge_distance)
{ {
MetaPointerConstraint *constraint; MetaPointerConstraint *constraint;
constraint = g_object_new (META_TYPE_POINTER_CONSTRAINT, NULL); constraint = g_object_new (META_TYPE_POINTER_CONSTRAINT, NULL);
constraint->region = mtk_region_copy (region); constraint->region = mtk_region_copy (region);
constraint->origin = origin;
constraint->min_edge_distance = min_edge_distance; constraint->min_edge_distance = min_edge_distance;
return constraint; return constraint;
} }
MtkRegion * MtkRegion *
meta_pointer_constraint_get_region (MetaPointerConstraint *constraint) meta_pointer_constraint_get_region (MetaPointerConstraint *constraint,
graphene_point_t *origin)
{ {
if (origin)
*origin = constraint->origin;
return constraint->region; return constraint->region;
} }

View File

@ -33,9 +33,11 @@ G_DECLARE_FINAL_TYPE (MetaPointerConstraint, meta_pointer_constraint,
META, POINTER_CONSTRAINT, GObject); META, POINTER_CONSTRAINT, GObject);
MetaPointerConstraint * meta_pointer_constraint_new (const MtkRegion *region, MetaPointerConstraint * meta_pointer_constraint_new (const MtkRegion *region,
graphene_point_t origin,
double min_edge_distance); double min_edge_distance);
MtkRegion * meta_pointer_constraint_get_region (MetaPointerConstraint *constraint); MtkRegion * meta_pointer_constraint_get_region (MetaPointerConstraint *constraint,
graphene_point_t *origin);
double meta_pointer_constraint_get_min_edge_distance (MetaPointerConstraint *constraint); double meta_pointer_constraint_get_min_edge_distance (MetaPointerConstraint *constraint);

View File

@ -400,13 +400,15 @@ meta_backend_native_set_pointer_constraint (MetaBackend *backend,
if (constraint) if (constraint)
{ {
graphene_point_t origin;
double min_edge_distance; double min_edge_distance;
region = meta_pointer_constraint_get_region (constraint); region = meta_pointer_constraint_get_region (constraint, &origin);
min_edge_distance = min_edge_distance =
meta_pointer_constraint_get_min_edge_distance (constraint); meta_pointer_constraint_get_min_edge_distance (constraint);
constraint_impl = meta_pointer_constraint_impl_native_new (constraint, constraint_impl = meta_pointer_constraint_impl_native_new (constraint,
region, region,
origin,
min_edge_distance); min_edge_distance);
} }

View File

@ -33,6 +33,7 @@ struct _MetaPointerConstraintImplNative
MetaPointerConstraintImpl parent; MetaPointerConstraintImpl parent;
MetaPointerConstraint *constraint; MetaPointerConstraint *constraint;
MtkRegion *region; MtkRegion *region;
graphene_point_t origin;
double min_edge_distance; double min_edge_distance;
}; };
@ -461,6 +462,14 @@ meta_pointer_constraint_impl_native_constraint (MetaPointerConstraintImpl *const
constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (constraint_impl); constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (constraint_impl);
region = mtk_region_ref (constraint_impl_native->region); region = mtk_region_ref (constraint_impl_native->region);
if (mtk_region_is_empty (region))
{
*x_inout = constraint_impl_native->origin.x;
*y_inout = constraint_impl_native->origin.y;
return;
}
x = *x_inout; x = *x_inout;
y = *y_inout; y = *y_inout;
@ -589,6 +598,7 @@ meta_pointer_constraint_impl_native_ensure_constrained (MetaPointerConstraintImp
{ {
MetaPointerConstraintImplNative *constraint_impl_native; MetaPointerConstraintImplNative *constraint_impl_native;
graphene_point_t point; graphene_point_t point;
ClutterSeat *seat;
g_autoptr (MtkRegion) region = NULL; g_autoptr (MtkRegion) region = NULL;
float x; float x;
float y; float y;
@ -596,17 +606,24 @@ meta_pointer_constraint_impl_native_ensure_constrained (MetaPointerConstraintImp
constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (constraint_impl); constraint_impl_native = META_POINTER_CONSTRAINT_IMPL_NATIVE (constraint_impl);
region = mtk_region_ref (constraint_impl_native->region); region = mtk_region_ref (constraint_impl_native->region);
clutter_seat_query_state (clutter_input_device_get_seat (device), seat = clutter_input_device_get_seat (device);
device, NULL, &point, NULL); clutter_seat_query_state (seat, device, NULL, &point, NULL);
x = point.x; x = point.x;
y = point.y; y = point.y;
if (!mtk_region_contains_point (region, (int) x, (int) y)) if (mtk_region_is_empty (region))
{
if (x != constraint_impl_native->origin.x ||
y != constraint_impl_native->origin.y)
clutter_seat_warp_pointer (seat, x, y);
}
else if (!mtk_region_contains_point (region,
(int) x - constraint_impl_native->origin.x,
(int) y - constraint_impl_native->origin.y))
{ {
g_autoptr (GArray) borders = NULL; g_autoptr (GArray) borders = NULL;
float closest_distance_2 = FLT_MAX; float closest_distance_2 = FLT_MAX;
MetaBorder *closest_border = NULL; MetaBorder *closest_border = NULL;
ClutterSeat *seat;
unsigned int i; unsigned int i;
borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder)); borders = g_array_new (FALSE, FALSE, sizeof (MetaBorder));
@ -628,7 +645,6 @@ meta_pointer_constraint_impl_native_ensure_constrained (MetaPointerConstraintImp
closest_point_behind_border (closest_border, &x, &y); closest_point_behind_border (closest_border, &x, &y);
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
clutter_seat_warp_pointer (seat, x, y); clutter_seat_warp_pointer (seat, x, y);
} }
} }
@ -667,6 +683,7 @@ meta_pointer_constraint_impl_native_class_init (MetaPointerConstraintImplNativeC
MetaPointerConstraintImpl * MetaPointerConstraintImpl *
meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint, meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint,
const MtkRegion *region, const MtkRegion *region,
graphene_point_t origin,
double min_edge_distance) double min_edge_distance)
{ {
MetaPointerConstraintImplNative *constraint_impl; MetaPointerConstraintImplNative *constraint_impl;
@ -676,6 +693,7 @@ meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint,
constraint_impl->constraint = constraint; constraint_impl->constraint = constraint;
constraint_impl->region = mtk_region_copy (region); constraint_impl->region = mtk_region_copy (region);
constraint_impl->min_edge_distance = min_edge_distance; constraint_impl->min_edge_distance = min_edge_distance;
constraint_impl->origin = origin;
return META_POINTER_CONSTRAINT_IMPL (constraint_impl); return META_POINTER_CONSTRAINT_IMPL (constraint_impl);
} }

View File

@ -37,6 +37,7 @@ G_DECLARE_FINAL_TYPE (MetaPointerConstraintImplNative,
MetaPointerConstraintImpl * meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint_impl, MetaPointerConstraintImpl * meta_pointer_constraint_impl_native_new (MetaPointerConstraint *constraint_impl,
const MtkRegion *region, const MtkRegion *region,
graphene_point_t origin,
double min_edge_distance); double min_edge_distance);
G_END_DECLS G_END_DECLS

View File

@ -245,10 +245,10 @@ meta_pointer_confinement_wayland_create_constraint (MetaPointerConfinementWaylan
} }
meta_wayland_surface_get_absolute_coordinates (surface, 0, 0, &dx, &dy); meta_wayland_surface_get_absolute_coordinates (surface, 0, 0, &dx, &dy);
mtk_region_translate (region, dx, dy);
min_edge_distance = wl_fixed_to_double (1) * geometry_scale; min_edge_distance = wl_fixed_to_double (1) * geometry_scale;
constraint = meta_pointer_constraint_new (g_steal_pointer (&region), constraint = meta_pointer_constraint_new (g_steal_pointer (&region),
GRAPHENE_POINT_INIT (dx, dy),
min_edge_distance); min_edge_distance);
return constraint; return constraint;

View File

@ -74,10 +74,12 @@ meta_pointer_lock_wayland_create_constraint (MetaPointerConfinementWayland *conf
&sx, &sy); &sx, &sy);
meta_wayland_surface_get_absolute_coordinates (surface, sx, sy, &x, &y); meta_wayland_surface_get_absolute_coordinates (surface, sx, sy, &x, &y);
rect = (MtkRectangle) { .x = x, .y = y, .width = 1, .height = 1 }; rect = (MtkRectangle) { .x = 0, .y = 0, .width = 0, .height = 0 };
region = mtk_region_create_rectangle (&rect); region = mtk_region_create_rectangle (&rect);
constraint = meta_pointer_constraint_new (g_steal_pointer (&region), 0.0); constraint = meta_pointer_constraint_new (g_steal_pointer (&region),
GRAPHENE_POINT_INIT (x, y),
0.0);
return constraint; return constraint;
} }