aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/pointer.c20
-rw-r--r--include/wlr/types/wlr_cursor.h3
-rw-r--r--include/wlr/types/wlr_geometry.h2
-rw-r--r--include/wlr/types/wlr_output_layout.h13
-rw-r--r--types/wlr_cursor.c92
-rw-r--r--types/wlr_geometry.c22
-rw-r--r--types/wlr_output_layout.c89
7 files changed, 189 insertions, 52 deletions
diff --git a/examples/pointer.c b/examples/pointer.c
index bae205f5..98b4735a 100644
--- a/examples/pointer.c
+++ b/examples/pointer.c
@@ -58,12 +58,20 @@ struct touch_point {
double x, y;
};
-static void warp_to_touch(struct sample_state *sample) {
- wlr_log(L_DEBUG, "TODO: warp to touch");
+static void warp_to_touch(struct sample_state *sample, struct wlr_input_device *dev) {
+ if (sample->touch_points->length == 0) {
+ return;
+ }
+
+ double x = 0, y = 0;
for (size_t i = 0; i < sample->touch_points->length; ++i) {
struct touch_point *point = sample->touch_points->items[i];
- wlr_log(L_DEBUG, "have point x=%f,y=%f", point->x, point->y);
+ x += point->x;
+ y += point->y;
}
+ x /= sample->touch_points->length;
+ y /= sample->touch_points->length;
+ wlr_cursor_warp_absolute(sample->cursor, dev, x, y);
}
static void handle_output_frame(struct output_state *output, struct timespec *ts) {
@@ -248,7 +256,7 @@ static void handle_touch_up(struct wl_listener *listener, void *data) {
}
}
- warp_to_touch(sample);
+ warp_to_touch(sample, event->device);
}
static void handle_touch_down(struct wl_listener *listener, void *data) {
@@ -262,7 +270,7 @@ static void handle_touch_down(struct wl_listener *listener, void *data) {
free(point);
}
- warp_to_touch(sample);
+ warp_to_touch(sample, event->device);
}
static void handle_touch_motion(struct wl_listener *listener, void *data) {
@@ -277,7 +285,7 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) {
}
}
- warp_to_touch(sample);
+ warp_to_touch(sample, event->device);
}
static void handle_touch_cancel(struct wl_listener *listener, void *data) {
diff --git a/include/wlr/types/wlr_cursor.h b/include/wlr/types/wlr_cursor.h
index ad5c52a4..4ba7b25f 100644
--- a/include/wlr/types/wlr_cursor.h
+++ b/include/wlr/types/wlr_cursor.h
@@ -46,6 +46,9 @@ void wlr_cursor_set_xcursor(struct wlr_cursor *cur, struct wlr_xcursor *xcur);
bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev,
double x, double y);
+void wlr_cursor_warp_absolute(struct wlr_cursor *cur,
+ struct wlr_input_device *dev, double x_mm, double y_mm);
+
/**
* Move the cursor in the direction of the given x and y coordinates.
*
diff --git a/include/wlr/types/wlr_geometry.h b/include/wlr/types/wlr_geometry.h
index 7ac2f843..cac75431 100644
--- a/include/wlr/types/wlr_geometry.h
+++ b/include/wlr/types/wlr_geometry.h
@@ -15,4 +15,6 @@ bool wlr_geometry_intersection(struct wlr_geometry *geo_a,
bool wlr_geometry_contains_point(struct wlr_geometry *geo, int x, int y);
+bool wlr_geometry_empty(struct wlr_geometry *geo);
+
#endif
diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h
index 144c2d5a..0d157f56 100644
--- a/include/wlr/types/wlr_output_layout.h
+++ b/include/wlr/types/wlr_output_layout.h
@@ -4,14 +4,20 @@
#include <wayland-util.h>
#include <stdbool.h>
+struct wlr_output_layout_state;
+
struct wlr_output_layout {
struct wl_list outputs;
+ struct wlr_output_layout_state *state;
};
+struct wlr_output_layout_output_state;
+
struct wlr_output_layout_output {
struct wlr_output *output;
int x, y;
struct wl_list link;
+ struct wlr_output_layout_output_state *state;
};
struct wlr_output_layout *wlr_output_layout_init();
@@ -55,4 +61,11 @@ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout,
struct wlr_output *reference, double x, double y, double *dest_x,
double *dest_y);
+/**
+ * Get the geometry of the layout for the given reference output. If `reference`
+ * is NULL, the geometry will be for the extents of the entire layout.
+ */
+struct wlr_geometry *wlr_output_layout_get_geometry(
+ struct wlr_output_layout *layout, struct wlr_output *reference);
+
#endif
diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c
index f9e1fcc9..f315727f 100644
--- a/types/wlr_cursor.c
+++ b/types/wlr_cursor.c
@@ -1,6 +1,7 @@
#include <wlr/types/wlr_cursor.h>
#include <stdlib.h>
#include <assert.h>
+#include <limits.h>
#include <wlr/util/log.h>
#include <wayland-server.h>
#include <wlr/types/wlr_output.h>
@@ -95,6 +96,29 @@ static struct wlr_cursor_device *get_cursor_device(struct wlr_cursor *cur,
return ret;
}
+static void wlr_cursor_warp_unchecked(struct wlr_cursor *cur, double x, double y) {
+ int hotspot_x = 0;
+ int hotspot_y = 0;
+
+ if (cur->state->xcursor && cur->state->xcursor->image_count > 0) {
+ struct wlr_xcursor_image *image = cur->state->xcursor->images[0];
+ hotspot_x = image->hotspot_x;
+ hotspot_y = image->hotspot_y;
+ }
+
+
+ struct wlr_output_layout_output *l_output;
+ wl_list_for_each(l_output, &cur->state->layout->outputs, link) {
+ double output_x = x;
+ double output_y = y;
+
+ wlr_output_layout_output_coords(cur->state->layout,
+ l_output->output, &output_x, &output_y);
+ wlr_output_move_cursor(l_output->output, output_x - hotspot_x,
+ output_y - hotspot_y);
+ }
+}
+
bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev,
double x, double y) {
assert(cur->state->layout);
@@ -120,28 +144,59 @@ bool wlr_cursor_warp(struct wlr_cursor *cur, struct wlr_input_device *dev,
return false;
}
- int hotspot_x = 0;
- int hotspot_y = 0;
+ wlr_cursor_warp_unchecked(cur, x, y);
+ return true;
+}
- if (cur->state->xcursor && cur->state->xcursor->image_count > 0) {
- struct wlr_xcursor_image *image = cur->state->xcursor->images[0];
- hotspot_x = image->hotspot_x;
- hotspot_y = image->hotspot_y;
+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
+ 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;
}
+ 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;
- struct wlr_output_layout_output *l_output;
- wl_list_for_each(l_output, &cur->state->layout->outputs, link) {
- double output_x = x;
- double output_y = y;
+ 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);
- wlr_output_layout_output_coords(cur->state->layout,
- l_output->output, &output_x, &output_y);
- wlr_output_move_cursor(l_output->output, output_x - hotspot_x,
- output_y - hotspot_y);
+ if (wlr_geometry_empty(constraints)) {
+ goto out;
}
- return true;
+ double x = constraints->width * x_mm + constraints->x;
+ double y = constraints->height * y_mm + constraints->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,
@@ -195,10 +250,9 @@ void wlr_cursor_move(struct wlr_cursor *cur, struct wlr_input_device *dev,
goto out;
}
- if (wlr_cursor_warp(cur, dev, x, y)) {
- cur->x = x;
- cur->y = y;
- }
+ wlr_cursor_warp_unchecked(cur, x, y);
+ cur->x = x;
+ cur->y = y;
out:
if (constraints) {
diff --git a/types/wlr_geometry.c b/types/wlr_geometry.c
index be4a80eb..32dbb81f 100644
--- a/types/wlr_geometry.c
+++ b/types/wlr_geometry.c
@@ -45,8 +45,8 @@ void wlr_geometry_closest_boundary(struct wlr_geometry *geo, double x, double y,
#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_empty(struct wlr_geometry *geo) {
+ return geo == NULL || geo->width <= 0 || geo->height <= 0;
}
bool wlr_geometry_intersection(struct wlr_geometry *geo_a,
@@ -55,20 +55,12 @@ bool wlr_geometry_intersection(struct wlr_geometry *geo_a,
bool a_empty = wlr_geometry_empty(geo_a);
bool b_empty = wlr_geometry_empty(geo_b);
- if (a_empty && b_empty) {
+ if (a_empty || b_empty) {
+ dest->x = 0;
+ dest->y = 0;
+ dest->width = -100;
+ dest->height = -100;
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);
diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c
index 7dcb4651..0b5e0411 100644
--- a/types/wlr_output_layout.c
+++ b/types/wlr_output_layout.c
@@ -1,16 +1,35 @@
#include <wlr/util/log.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
+#include <wlr/types/wlr_geometry.h>
#include <limits.h>
#include <stdlib.h>
#include <assert.h>
+struct wlr_output_layout_state {
+ struct wlr_geometry *_geo;
+};
+
+struct wlr_output_layout_output_state {
+ struct wlr_geometry *_geo;
+};
+
struct wlr_output_layout *wlr_output_layout_init() {
struct wlr_output_layout *layout = calloc(1, sizeof(struct wlr_output_layout));
+ layout->state = calloc(1, sizeof(struct wlr_output_layout_state));
+ layout->state->_geo = calloc(1, sizeof(struct wlr_geometry));
wl_list_init(&layout->outputs);
return layout;
}
+static void wlr_output_layout_output_destroy(
+ struct wlr_output_layout_output *l_output) {
+ wl_list_remove(&l_output->link);
+ free(l_output->state->_geo);
+ free(l_output->state);
+ free(l_output);
+}
+
void wlr_output_layout_destroy(struct wlr_output_layout *layout) {
if (!layout) {
return;
@@ -18,20 +37,24 @@ void wlr_output_layout_destroy(struct wlr_output_layout *layout) {
struct wlr_output_layout_output *_output, *temp = NULL;
wl_list_for_each_safe(_output, temp, &layout->outputs, link) {
- wl_list_remove(&_output->link);
- free(_output);
+ wlr_output_layout_output_destroy(_output);
}
+ free(layout->state->_geo);
+ free(layout->state);
free(layout);
}
void wlr_output_layout_add(struct wlr_output_layout *layout,
struct wlr_output *output, int x, int y) {
- struct wlr_output_layout_output *layout_output = calloc(1, sizeof(struct wlr_output_layout_output));
- layout_output->output = output;
- layout_output->x = x;
- layout_output->y = y;
- wl_list_insert(&layout->outputs, &layout_output->link);
+ struct wlr_output_layout_output *l_output;
+ l_output= calloc(1, sizeof(struct wlr_output_layout_output));
+ l_output->state = calloc(1, sizeof(struct wlr_output_layout_output_state));
+ l_output->state->_geo = calloc(1, sizeof(struct wlr_geometry));
+ l_output->output = output;
+ l_output->x = x;
+ l_output->y = y;
+ wl_list_insert(&layout->outputs, &l_output->link);
}
struct wlr_output_layout_output *wlr_output_layout_get(
@@ -104,11 +127,10 @@ void wlr_output_layout_move(struct wlr_output_layout *layout,
void wlr_output_layout_remove(struct wlr_output_layout *layout,
struct wlr_output *output) {
- struct wlr_output_layout_output *layout_output =
- wlr_output_layout_get(layout, output);
- if (layout_output) {
- wl_list_remove(&layout_output->link);
- free(layout_output);
+ struct wlr_output_layout_output *l_output;
+ l_output= wlr_output_layout_get(layout, output);
+ if (l_output) {
+ wlr_output_layout_output_destroy(l_output);
}
}
@@ -179,3 +201,46 @@ void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout,
*dest_x = min_x;
*dest_y = min_y;
}
+
+struct wlr_geometry *wlr_output_layout_get_geometry(
+ struct wlr_output_layout *layout, struct wlr_output *reference) {
+ struct wlr_output_layout_output *l_output;
+ if (reference) {
+ // output extents
+ l_output= wlr_output_layout_get(layout, reference);
+ l_output->state->_geo->x = l_output->x;
+ l_output->state->_geo->y = l_output->y;
+ wlr_output_effective_resolution(reference,
+ &l_output->state->_geo->width, &l_output->state->_geo->height);
+ return l_output->state->_geo;
+ } else {
+ // layout extents
+ int min_x = INT_MAX, min_y = INT_MAX;
+ int max_x = INT_MIN, max_y = INT_MIN;
+ wl_list_for_each(l_output, &layout->outputs, link) {
+ int width, height;
+ wlr_output_effective_resolution(l_output->output, &width, &height);
+ if (l_output->x < min_x) {
+ min_x = l_output->x;
+ }
+ if (l_output->y < min_y) {
+ min_y = l_output->y;
+ }
+ if (l_output->x + width > max_x) {
+ max_x = l_output->x + width;
+ }
+ if (l_output->y + height > max_y) {
+ max_y = l_output->y + height;
+ }
+ }
+
+ layout->state->_geo->x = min_x;
+ layout->state->_geo->y = min_y;
+ layout->state->_geo->width = max_x - min_x;
+ layout->state->_geo->height = max_y - min_y;
+
+ return layout->state->_geo;
+ }
+
+ // not reached
+}