aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_geometry.h6
-rw-r--r--types/wlr_cursor.c33
-rw-r--r--types/wlr_geometry.c54
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 <stdbool.h>
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 <limits.h>
#include <stdlib.h>
#include <math.h>
+#include <stdbool.h>
#include <wlr/types/wlr_geometry.h>
+#include <wlr/util/log.h>
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;
+}