From: Ander Conselvan de Oliveira Date: Fri, 14 Dec 2012 15:37:26 +0000 (-0200) Subject: compositor: Don't let pointers get outside of an output on mode switch X-Git-Tag: 1.0.90~209 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=2bbb2b8bac328bcc0c32271e80b5da857916f66b;p=platform%2Fupstream%2Fweston.git compositor: Don't let pointers get outside of an output on mode switch When an output suffers a mode switch, it is possible that a pointer was inside the old output area but falls outside of it with the new size. In that case, move the cursor to the output's bottom-right corner. Otherwise, there's a crash in clip_pointer_motion(). --- diff --git a/src/compositor.c b/src/compositor.c index 567105e..e556766 100644 --- a/src/compositor.c +++ b/src/compositor.c @@ -90,6 +90,8 @@ weston_output_transform_init(struct weston_output *output, uint32_t transform); WL_EXPORT int weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode) { + struct weston_seat *seat; + pixman_region32_t old_output_region; int ret; if (!output->switch_mode) @@ -99,6 +101,9 @@ weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode if (ret < 0) return ret; + pixman_region32_init(&old_output_region); + pixman_region32_copy(&old_output_region, &output->region); + /* Update output region and transformation matrix */ weston_output_transform_init(output, output->transform); @@ -108,6 +113,35 @@ weston_output_switch_mode(struct weston_output *output, struct weston_mode *mode weston_output_update_matrix(output); + /* If a pointer falls outside the outputs new geometry, move it to its + * lower-right corner */ + wl_list_for_each(seat, &output->compositor->seat_list, link) { + struct wl_pointer *pointer = seat->seat.pointer; + int32_t x, y; + + if (!pointer) + continue; + + x = wl_fixed_to_int(pointer->x); + y = wl_fixed_to_int(pointer->y); + + if (!pixman_region32_contains_point(&old_output_region, + x, y, NULL) || + pixman_region32_contains_point(&output->region, + x, y, NULL)) + continue; + + if (x >= output->x + output->width) + x = output->x + output->width - 1; + if (y >= output->y + output->height) + y = output->y + output->height - 1; + + pointer->x = wl_fixed_from_int(x); + pointer->y = wl_fixed_from_int(y); + } + + pixman_region32_fini(&old_output_region); + return ret; }