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().
This commit is contained in:
committed by
Kristian Høgsberg
parent
5c38ef4d4a
commit
2bbb2b8bac
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user