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().
dev
Ander Conselvan de Oliveira 12 years ago committed by Kristian Høgsberg
parent 5c38ef4d4a
commit 2bbb2b8bac
  1. 34
      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;
}

Loading…
Cancel
Save