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; - - // 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, - output_y - hotspot_y); - } - - cur->x = new_x; - cur->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, + l_output->output, &output_x, &output_y); + wlr_output_move_cursor(l_output->output, output_x - hotspot_x, + output_y - hotspot_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 #include #include +#include #include #include @@ -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; +}