[PATCH 4/8] compositor: Don't let pointers get outside of an output on mode switch

Ander Conselvan de Oliveira conselvan2 at gmail.com
Fri Dec 14 07:37:26 PST 2012


From: Ander Conselvan de Oliveira <ander.conselvan.de.oliveira at intel.com>

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().
---
 src/compositor.c |   34 ++++++++++++++++++++++++++++++++++
 1 file changed, 34 insertions(+)

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;
 }
 
-- 
1.7.9.5



More information about the wayland-devel mailing list