diff --git a/src/compositor.c b/src/compositor.c index ed6548c6..af33fdae 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -3105,6 +3105,19 @@ weston_compositor_remove_output(struct weston_compositor *compositor, } } +static void +weston_compositor_verify_pointers(struct weston_compositor *ec) +{ + struct weston_seat *seat; + + wl_list_for_each(seat, &ec->seat_list, link) { + if (!seat->pointer) + continue; + + weston_pointer_verify(seat->pointer); + } +} + WL_EXPORT void weston_output_destroy(struct weston_output *output) { @@ -3113,6 +3126,8 @@ weston_output_destroy(struct weston_output *output) weston_compositor_remove_output(output->compositor, output); wl_list_remove(&output->link); + weston_compositor_verify_pointers(output->compositor); + wl_signal_emit(&output->destroy_signal, output); free(output->name); diff --git a/src/compositor.h b/src/compositor.h index 901366fb..d344e37e 100644 --- a/src/compositor.h +++ b/src/compositor.h @@ -375,6 +375,8 @@ weston_pointer_move(struct weston_pointer *pointer, void weston_pointer_set_default_grab(struct weston_pointer *pointer, const struct weston_pointer_grab_interface *interface); +void +weston_pointer_verify(struct weston_pointer *pointer); struct weston_keyboard * weston_keyboard_create(void); diff --git a/src/input.c b/src/input.c index f4944b6c..07e9d6cb 100644 --- a/src/input.c +++ b/src/input.c @@ -29,6 +29,7 @@ #include #include #include +#include #include "../shared/os-compatibility.h" #include "compositor.h" @@ -791,6 +792,28 @@ weston_touch_cancel_grab(struct weston_touch *touch) touch->grab->interface->cancel(touch->grab); } +static void +weston_pointer_clamp_for_output(struct weston_pointer *pointer, + struct weston_output *output, + wl_fixed_t *fx, wl_fixed_t *fy) +{ + int x, y; + + x = wl_fixed_to_int(*fx); + y = wl_fixed_to_int(*fy); + + if (x < output->x) + *fx = wl_fixed_from_int(output->x); + else if (x >= output->x + output->width) + *fx = wl_fixed_from_int(output->x + + output->width - 1); + if (y < output->y) + *fy = wl_fixed_from_int(output->y); + else if (y >= output->y + output->height) + *fy = wl_fixed_from_int(output->y + + output->height - 1); +} + WL_EXPORT void weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t *fy) { @@ -817,18 +840,8 @@ weston_pointer_clamp(struct weston_pointer *pointer, wl_fixed_t *fx, wl_fixed_t if (!prev) prev = pointer->seat->output; - if (prev && !valid) { - if (x < prev->x) - *fx = wl_fixed_from_int(prev->x); - else if (x >= prev->x + prev->width) - *fx = wl_fixed_from_int(prev->x + - prev->width - 1); - if (y < prev->y) - *fy = wl_fixed_from_int(prev->y); - else if (y >= prev->y + prev->height) - *fy = wl_fixed_from_int(prev->y + - prev->height - 1); - } + if (prev && !valid) + weston_pointer_clamp_for_output(pointer, prev, fx, fy); } /* Takes absolute values */ @@ -856,6 +869,45 @@ weston_pointer_move(struct weston_pointer *pointer, wl_fixed_t x, wl_fixed_t y) wl_signal_emit(&pointer->motion_signal, pointer); } +/** Verify if the pointer is in a valid position and move it if it isn't. + */ +WL_EXPORT void +weston_pointer_verify(struct weston_pointer *pointer) +{ + struct weston_compositor *ec = pointer->seat->compositor; + struct weston_output *output, *closest = NULL; + int x, y, distance, min = INT_MAX; + wl_fixed_t fx, fy; + + x = wl_fixed_to_int(pointer->x); + y = wl_fixed_to_int(pointer->y); + + wl_list_for_each(output, &ec->output_list, link) { + if (pixman_region32_contains_point(&output->region, + x, y, NULL)) + return; + + /* Aproximante the distance from the pointer to the center of + * the output. */ + distance = abs(output->x + output->width / 2 - x) + + abs(output->y + output->height / 2 - y); + if (distance < min) { + min = distance; + closest = output; + } + } + + /* Nothing to do if there's no output left. */ + if (!closest) + return; + + fx = pointer->x; + fy = pointer->y; + + weston_pointer_clamp_for_output(pointer, closest, &fx, &fy); + weston_pointer_move(pointer, fx, fy); +} + WL_EXPORT void notify_motion(struct weston_seat *seat, uint32_t time, wl_fixed_t dx, wl_fixed_t dy)