aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/wlr/types/wlr_output_layout.h6
-rw-r--r--types/wlr_cursor.c34
-rw-r--r--types/wlr_output_layout.c46
3 files changed, 71 insertions, 15 deletions
diff --git a/include/wlr/types/wlr_output_layout.h b/include/wlr/types/wlr_output_layout.h
index f6a1efdd..52cc9423 100644
--- a/include/wlr/types/wlr_output_layout.h
+++ b/include/wlr/types/wlr_output_layout.h
@@ -46,4 +46,10 @@ bool wlr_output_layout_contains_point(struct wlr_output_layout *layout,
bool wlr_output_layout_intersects(struct wlr_output_layout *layout,
struct wlr_output *reference, int x1, int y1, int x2, int y2);
+/**
+ * Get the closest boundary point of this layout from the given point.
+ */
+void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout,
+ int x, int y, int *dest_x, int *dest_y);
+
#endif
diff --git a/types/wlr_cursor.c b/types/wlr_cursor.c
index af977632..84224ac9 100644
--- a/types/wlr_cursor.c
+++ b/types/wlr_cursor.c
@@ -73,7 +73,7 @@ void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) {
// TODO handle no layout
assert(cur->state->layout);
- // TODO handle layout boundaries
+
double new_x = cur->x + delta_x;
double new_y = cur->y + delta_y;
int hotspot_x = 0;
@@ -85,24 +85,28 @@ void wlr_cursor_move(struct wlr_cursor *cur, double delta_x, double delta_y) {
hotspot_y = image->hotspot_y;
}
- if (wlr_output_layout_output_at(cur->state->layout, new_x, new_y)) {
- //struct wlr_output *output;
- //output = wlr_output_layout_output_at(cur->state->layout, new_x, new_y);
- struct wlr_output_layout_output *l_output;
- wl_list_for_each(l_output, &cur->state->layout->outputs, link) {
- int output_x = new_x;
- int output_y = new_y;
+ if (!wlr_output_layout_output_at(cur->state->layout, new_x, new_y)) {
+ int closest_x, closest_y;
+ wlr_output_layout_closest_boundary(cur->state->layout, new_x, new_y,
+ &closest_x, &closest_y);
+ new_x = closest_x;
+ new_y = closest_y;
+ }
+
+ struct wlr_output_layout_output *l_output;
+ wl_list_for_each(l_output, &cur->state->layout->outputs, link) {
+ int output_x = new_x;
+ int output_y = new_y;
- // TODO fix double to int rounding issues
- wlr_output_layout_output_coords(cur->state->layout,
+ // TODO fix double to int rounding issues
+ 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,
+ wlr_output_move_cursor(l_output->output, output_x - hotspot_x,
output_y - hotspot_y);
- }
-
- cur->x = new_x;
- cur->y = new_y;
}
+
+ cur->x = new_x;
+ cur->y = new_y;
}
static void handle_pointer_motion(struct wl_listener *listener, void *data) {
diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c
index 2e2032b3..3593eae6 100644
--- a/types/wlr_output_layout.c
+++ b/types/wlr_output_layout.c
@@ -1,6 +1,7 @@
#include <wlr/util/log.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_output_layout.h>
+#include <limits.h>
#include <stdlib.h>
#include <assert.h>
@@ -126,3 +127,48 @@ void wlr_output_layout_output_coords(struct wlr_output_layout *layout,
}
}
}
+
+static double get_distance(double x1, double y1, double x2, double y2) {
+ double distance;
+ distance = sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+ return distance;
+}
+
+void wlr_output_layout_closest_boundary(struct wlr_output_layout *layout,
+ int x, int y, int *dest_x, int *dest_y) {
+ int min_x = INT_MAX, min_y = INT_MAX, min_distance = INT_MAX;
+ struct wlr_output_layout_output *l_output;
+ wl_list_for_each(l_output, &layout->outputs, link) {
+ int width, height, output_x, output_y, output_distance;
+ wlr_output_effective_resolution(l_output->output, &width, &height);
+
+ // find the closest x point
+ if (x < l_output->x) {
+ output_x = l_output->x;
+ } else if (x > l_output->x + width) {
+ output_x = l_output->x + width;
+ } else {
+ output_x = x;
+ }
+
+ // find closest y point
+ if (y < l_output->y) {
+ output_y = l_output->y;
+ } else if (y > l_output->y + height) {
+ output_y = l_output->y + height;
+ } else {
+ output_y = y;
+ }
+
+ // calculate distance
+ output_distance = get_distance(output_x, output_y, x, y);
+ if (output_distance < min_distance) {
+ min_x = output_x;
+ min_y = output_y;
+ min_distance = output_distance;
+ }
+ }
+
+ *dest_x = min_x;
+ *dest_y = min_y;
+}