aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--types/wlr_cursor.c188
-rw-r--r--types/wlr_geometry.c8
-rw-r--r--types/wlr_output_layout.c12
3 files changed, 98 insertions, 110 deletions
diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c
index f315727f..f183e64a 100644
--- a/types/wlr_cursor.c
+++ b/types/wlr_cursor.c
@@ -97,6 +97,7 @@ static struct wlr_cursor_device *get_cursor_device(struct wlr_cursor *cur,
}
static void wlr_cursor_warp_unchecked(struct wlr_cursor *cur, double x, double y) {
+ assert(cur->state->layout);
int hotspot_x = 0;
int hotspot_y = 0;
@@ -119,145 +120,111 @@ static void wlr_cursor_warp_unchecked(struct wlr_cursor *cur, double x, double y
}
}
-bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev,
- double x, double y) {
+/**
+ * Get the most specific mapping box for the device in this order:
+ *
+ * 1. device geometry mapping
+ * 2. device output mapping
+ * 3. cursor geometry mapping
+ * 4. cursor output mapping
+ *
+ * Absolute movement for touch and pen devices will be relative to this box and
+ * pointer movement will be constrained to this box.
+ *
+ * If none of these are set, returns NULL and absolute movement should be
+ * relative to the extents of the layout.
+ */
+static struct wlr_geometry *get_mapping(struct wlr_cursor *cur,
+ struct wlr_input_device *dev) {
assert(cur->state->layout);
- struct wlr_output *output;
- output = wlr_output_layout_output_at(cur->state->layout, x, y);
-
- struct wlr_output *mapped_output = NULL;
struct wlr_cursor_device *c_device = get_cursor_device(cur, dev);
- if (c_device && c_device->mapped_output) {
- mapped_output = c_device->mapped_output;
- } else {
- mapped_output = cur->state->mapped_output;
+ if (c_device) {
+ if (c_device->mapped_geometry) {
+ return c_device->mapped_geometry;
+ }
+ if (c_device->mapped_output) {
+ return wlr_output_layout_get_geometry(cur->state->layout,
+ c_device->mapped_output);
+ }
}
- if (!output) {
- return false;
+ if (cur->state->mapped_geometry) {
+ return cur->state->mapped_geometry;
}
-
- if (mapped_output &&
- !wlr_output_layout_contains_point(cur->state->layout, mapped_output,
- x, y)) {
- return false;
+ if(cur->state->mapped_output) {
+ return wlr_output_layout_get_geometry(cur->state->layout,
+ cur->state->mapped_output);
}
- wlr_cursor_warp_unchecked(cur, x, y);
- return true;
+ return NULL;
}
-void wlr_cursor_warp_absolute(struct wlr_cursor *cur,
- struct wlr_input_device *dev, double x_mm, double y_mm) {
- // convert from absolute to global coordinates
+bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev,
+ double x, double y) {
assert(cur->state->layout);
- struct wlr_output *mapped_output = NULL;
- struct wlr_cursor_device *c_device = get_cursor_device(cur, dev);
+ bool result = false;
- if (c_device && c_device->mapped_output) {
- mapped_output = c_device->mapped_output;
- } else {
- mapped_output = cur->state->mapped_output;
+ struct wlr_geometry *mapping = get_mapping(cur, dev);
+
+ if (mapping) {
+ if (wlr_geometry_contains_point(mapping, x, y)) {
+ wlr_cursor_warp_unchecked(cur, x, y);
+ result = true;
+ }
+ } else if (wlr_output_layout_contains_point(cur->state->layout, NULL, x, y)) {
+ wlr_cursor_warp_unchecked(cur, x, y);
+ result = true;
}
- struct wlr_geometry *constraints = calloc(1, sizeof(struct wlr_geometry));
- // XXX how do we express infinite regions?
- constraints->x = INT_MIN / 2;
- constraints->y = INT_MIN / 2;
- constraints->width = INT_MAX;
- constraints->height = INT_MAX;
+ return result;
+}
- if (cur->state->mapped_geometry) {
- wlr_geometry_intersection(cur->state->mapped_geometry, constraints,
- &constraints);
- }
- if (c_device->mapped_geometry) {
- wlr_geometry_intersection(c_device->mapped_geometry, constraints,
- &constraints);
- }
- struct wlr_geometry *geo;
- if (mapped_output) {
- geo = wlr_output_layout_get_geometry(cur->state->layout, mapped_output);
- wlr_geometry_intersection(geo, constraints, &constraints);
- }
- geo = wlr_output_layout_get_geometry(cur->state->layout, NULL);
- wlr_geometry_intersection(geo, constraints, &constraints);
+void wlr_cursor_warp_absolute(struct wlr_cursor *cur,
+ struct wlr_input_device *dev, double x_mm, double y_mm) {
+ assert(cur->state->layout);
- if (wlr_geometry_empty(constraints)) {
- goto out;
+ struct wlr_geometry *mapping = get_mapping(cur, dev);
+ if (!mapping) {
+ mapping = wlr_output_layout_get_geometry(cur->state->layout, NULL);
}
- double x = constraints->width * x_mm + constraints->x;
- double y = constraints->height * y_mm + constraints->y;
+ double x = mapping->width * x_mm + mapping->x;
+ double y = mapping->height * y_mm + mapping->y;
wlr_cursor_warp_unchecked(cur, x, y);
-
-out:
- if (constraints) {
- free(constraints);
- }
}
void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev,
double delta_x, double delta_y) {
assert(cur->state->layout);
- struct wlr_output *mapped_output = NULL;
- struct wlr_cursor_device *c_device = get_cursor_device(cur, dev);
-
- if (c_device && c_device->mapped_output) {
- mapped_output = c_device->mapped_output;
- } else {
- mapped_output = cur->state->mapped_output;
- }
double x = cur->x + delta_x;
double y = cur->y + delta_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));
+ struct wlr_geometry *mapping = get_mapping(cur, dev);
- if (!wlr_geometry_intersection(cur->state->mapped_geometry,
- c_device->mapped_geometry, &constraints)) {
- // TODO handle no possible movement
- goto out;
+ if (mapping) {
+ int boundary_x, boundary_y;
+ if (!wlr_geometry_contains_point(mapping, x, y)) {
+ wlr_geometry_closest_boundary(mapping, x, y, &boundary_x,
+ &boundary_y, NULL);
+ x = boundary_x;
+ y = boundary_y;
+ }
+ } else {
+ if (!wlr_output_layout_contains_point(cur->state->layout, NULL, x, y)) {
+ double boundary_x, boundary_y;
+ wlr_output_layout_closest_boundary(cur->state->layout, NULL, x, y,
+ &boundary_x, &boundary_y);
+ x = boundary_x;
+ y = boundary_y;
}
-
- int closest_x, closest_y;
- wlr_geometry_closest_boundary(constraints, x, y,
- &closest_x, &closest_y, NULL);
- x = closest_x;
- y = closest_y;
- }
-
- // layout constraints
- struct wlr_output *output;
- output = wlr_output_layout_output_at(cur->state->layout, x, y);
-
- if (!output || (mapped_output && mapped_output != output)) {
- double closest_x, closest_y;
- wlr_output_layout_closest_boundary(cur->state->layout, mapped_output, x,
- y, &closest_x, &closest_y);
- x = closest_x;
- y = closest_y;
- }
-
- if (constraints && !wlr_geometry_contains_point(constraints, x, y)) {
- // TODO handle no possible movement
- goto out;
}
wlr_cursor_warp_unchecked(cur, x, y);
cur->x = x;
cur->y = y;
-
-out:
- if (constraints) {
- free(constraints);
- }
}
static void handle_pointer_motion(struct wl_listener *listener, void *data) {
@@ -416,15 +383,28 @@ void wlr_cursor_map_input_to_output(struct wlr_cursor *cur,
}
void wlr_cursor_map_to_region(struct wlr_cursor *cur, struct wlr_geometry *geo) {
+ if (geo && wlr_geometry_empty(geo)) {
+ wlr_log(L_ERROR, "cannot map cursor to an empty region");
+ return;
+ }
+
cur->state->mapped_geometry = geo;
}
void wlr_cursor_map_input_to_region(struct wlr_cursor *cur,
struct wlr_input_device *dev, struct wlr_geometry *geo) {
+ if (geo && wlr_geometry_empty(geo)) {
+ wlr_log(L_ERROR, "cannot map device \"%s\" input to an empty region",
+ dev->name);
+ return;
+ }
+
struct wlr_cursor_device *c_device = get_cursor_device(cur, dev);
if (!c_device) {
- wlr_log(L_ERROR, "Cannot map device \"%s\" to geometry (not found in this cursor)", dev->name);
+ wlr_log(L_ERROR, "Cannot map device \"%s\" to geometry (not found in"
+ "this cursor)", dev->name);
return;
}
+
c_device->mapped_geometry = geo;
}
diff --git a/types/wlr_geometry.c b/types/wlr_geometry.c
index 32dbb81f..4f532d6f 100644
--- a/types/wlr_geometry.c
+++ b/types/wlr_geometry.c
@@ -77,6 +77,10 @@ bool wlr_geometry_intersection(struct wlr_geometry *geo_a,
}
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;
+ if (wlr_geometry_empty(geo)) {
+ return false;
+ } else {
+ return x >= geo->x && x <= geo->x + geo->width &&
+ y >= geo->y && y <= geo->y + geo->height;
+ }
}
diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c
index 0b5e0411..4062c107 100644
--- a/types/wlr_output_layout.c
+++ b/types/wlr_output_layout.c
@@ -76,10 +76,14 @@ static bool output_contains_point( struct wlr_output_layout_output *l_output,
bool wlr_output_layout_contains_point(struct wlr_output_layout *layout,
struct wlr_output *reference, int x, int y) {
- struct wlr_output_layout_output *layout_output = wlr_output_layout_get(layout, reference);
- int width, height;
- wlr_output_effective_resolution(layout_output->output, &width, &height);
- return output_contains_point(layout_output, x, y, width, height);
+ if (reference) {
+ struct wlr_output_layout_output *layout_output = wlr_output_layout_get(layout, reference);
+ int width, height;
+ wlr_output_effective_resolution(layout_output->output, &width, &height);
+ return output_contains_point(layout_output, x, y, width, height);
+ } else {
+ return !!wlr_output_layout_output_at(layout, x, y);
+ }
}
bool wlr_output_layout_intersects(struct wlr_output_layout *layout,