From ac503a47a71e2ab5d149a1bb9184d424609c7da7 Mon Sep 17 00:00:00 2001 From: Tony Crisci Date: Sat, 26 Aug 2017 11:55:24 -0400 Subject: [PATCH] intersect cursor and device regions --- include/wlr/types/wlr_geometry.h | 6 ++++ types/wlr_cursor.c | 33 ++++++++++++------- types/wlr_geometry.c | 54 ++++++++++++++++++++++++++++++++ 3 files changed, 82 insertions(+), 11 deletions(-) diff --git a/include/wlr/types/wlr_geometry.h b/include/wlr/types/wlr_geometry.h index 3e218bed..7ac2f843 100644 --- a/include/wlr/types/wlr_geometry.h +++ b/include/wlr/types/wlr_geometry.h @@ -1,5 +1,6 @@ #ifndef _WLR_TYPES_GEOMETRY_H #define _WLR_TYPES_GEOMETRY_H +#include struct wlr_geometry { int x, y; @@ -9,4 +10,9 @@ struct wlr_geometry { void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, int *dest_x, int *dest_y, double *distance); +bool wlr_geometry_intersection(struct wlr_geometry *geo_a, + struct wlr_geometry *geo_b, struct wlr_geometry **dest); + +bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y); + #endif diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c index c0b2b6ae..28d9f8c9 100644 --- a/types/wlr_cursor.c +++ b/types/wlr_cursor.c @@ -147,19 +147,20 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, double x = cur->x + delta_x; double y = cur->y + delta_y; - // cursor geometry constraints - if (cur->state->mapped_geometry) { - int closest_x, closest_y; - wlr_geometry_closest_boundary(cur->state->mapped_geometry, x, y, - &closest_x, &closest_y, NULL); - x = closest_x; - y = closest_y; - } + // geometry constraints + struct wlr_geometry *constraints = NULL; + if (cur->state->mapped_geometry != NULL || + c_device->mapped_geometry != NULL) { + constraints = calloc(1, sizeof(struct wlr_geometry)); + + if (!wlr_geometry_intersection(cur->state->mapped_geometry, + c_device->mapped_geometry, &constraints)) { + // TODO handle no possible movement + goto out; + } - // device constraints - if (c_device->mapped_geometry) { int closest_x, closest_y; - wlr_geometry_closest_boundary(c_device->mapped_geometry, x, y, + wlr_geometry_closest_boundary(constraints, x, y, &closest_x, &closest_y, NULL); x = closest_x; y = closest_y; @@ -177,10 +178,20 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev, y = closest_y; } + if (constraints && !wlr_geometry_contains_point(constraints, x, y)) { + // TODO handle no possible movement + goto out; + } + if (wlr_cursor_warp(cur, dev, x, y)) { cur->x = x; cur->y = y; } + +out: + if (constraints) { + free(constraints); + } } static void handle_pointer_motion(struct wl_listener *listener, void *data) { diff --git a/types/wlr_geometry.c b/types/wlr_geometry.c index 8358d887..be4a80eb 100644 --- a/types/wlr_geometry.c +++ b/types/wlr_geometry.c @@ -1,7 +1,9 @@ #include #include #include +#include #include +#include static double get_distance(double x1, double y1, double x2, double y2) { double distance; @@ -34,3 +36,55 @@ void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y, *distance = get_distance(*dest_x, *dest_y, x, y); } } + +#ifndef max +#define max(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +static bool wlr_geometry_empty(struct wlr_geometry *geo) { + return geo == NULL || geo->width < 0 || geo->height < 0; +} + +bool wlr_geometry_intersection(struct wlr_geometry *geo_a, + struct wlr_geometry *geo_b, struct wlr_geometry **geo_dest) { + struct wlr_geometry *dest = *geo_dest; + bool a_empty = wlr_geometry_empty(geo_a); + bool b_empty = wlr_geometry_empty(geo_b); + + if (a_empty && b_empty) { + return false; + } else if (a_empty) { + dest->x = geo_b->x; + dest->y = geo_b->y; + dest->height = geo_b->height; + dest->width = geo_b->width; + return true; + } else if (b_empty) { + dest->x = geo_a->x; + dest->y = geo_a->y; + dest->height = geo_a->height; + dest->width = geo_a->width; + return true; + } + + int x1 = max(geo_a->x, geo_b->x); + int y1 = max(geo_a->y, geo_b->y); + int x2 = min(geo_a->x + geo_a->width, geo_b->x + geo_b->width); + int y2 = min(geo_a->y + geo_a->height, geo_b->y + geo_b->height); + + dest->x = x1; + dest->y = y1; + dest->width = x2 - x1; + dest->height = y2 - y1; + + return !wlr_geometry_empty(dest); +} + +bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y) { + return x >= geo->x && x <= geo->x + geo->width && + y >= geo->y && y <= geo->y + geo->height; +}