[weston,3/3] compositor-x11: Support relative mouse motion in fullscreen

Submitted by Marie Stephanie Alesna on Oct. 9, 2017, 10:12 p.m.

Details

Message ID 20171009221234.18237-3-istephielicious@gmail.com
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Wayland

Not browsing as part of any series.

Commit Message

Marie Stephanie Alesna Oct. 9, 2017, 10:12 p.m.
Wayland relative mouse clients require indefinite mouse moves.  Simulate them
by keeping invisible host mouse pointer in center of screen using mouse warps.

Also fix fullscreen mouse lock-up at invisible barrier when the invisible host
mouse pointer hits an edge of the screen.

Signed-off-by: Marie Stephanie Alesna <istephielicious@gmail.com>
---
 libweston/compositor-x11.c | 59 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 57 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/libweston/compositor-x11.c b/libweston/compositor-x11.c
index f9c9500d..aeb392d6 100644
--- a/libweston/compositor-x11.c
+++ b/libweston/compositor-x11.c
@@ -89,6 +89,15 @@  struct x11_backend {
 	double				 prev_x;
 	double				 prev_y;
 
+	/* Difference of physical vs. reported mouse pointer after XWarpPointer
+	 * calls. */
+	int32_t				 delta_x;
+	int32_t				 delta_y;
+	/* Difference to add to delta_x/delta_y after the currently pending
+	 * XWarpPointer gets reported in future motion event. */
+	int32_t				 delta_x_nextdiff;
+	int32_t				 delta_y_nextdiff;
+
 	struct {
 		xcb_atom_t		 wm_protocols;
 		xcb_atom_t		 wm_normal_hints;
@@ -1249,9 +1258,42 @@  x11_backend_deliver_motion_event(struct x11_backend *b,
 	if (!output)
 		return;
 
+	if (b->fullscreen) {
+		int32_t x = motion_notify->root_x;
+		int32_t y = motion_notify->root_y;
+		int32_t xc = output->mode.width / 2;
+		int32_t yc = output->mode.height / 2;
+		int32_t x3 = xc / 3;
+		int32_t y3 = yc / 3;
+		/* We have a pending XWarpPointer which got reported now as the
+		 * mouse pointer moved to the central third of the screen? */
+		if ((b->delta_x_nextdiff || b->delta_y_nextdiff)
+		    && xc - x3 <= x && x <= xc + x3
+		    && yc - y3 <= y && y <= yc + y3) {
+			b->delta_x += b->delta_x_nextdiff;
+			b->delta_y += b->delta_y_nextdiff;
+			b->delta_x_nextdiff = 0;
+			b->delta_y_nextdiff = 0;
+		}
+		/* No pending XWarpPointer and the mouse pointer got to the
+		 * outer third of the screen? */
+		if (!b->delta_x_nextdiff && !b->delta_y_nextdiff
+		    && (x < xc - 2 * x3 || xc + 2 * x3 < x
+			|| y < yc - 2 * y3 || yc + 2 * y3 < y)) {
+			b->delta_x_nextdiff = xc - x;
+			b->delta_y_nextdiff = yc - y;
+			/* Warp the mouse pointer relatively so we know the
+			 * exact future position difference despite we do not
+			 * know the exact mouse pointer position the time
+			 * XWarpPointer gets soon applied.  */
+			XWarpPointer(b->dpy, output->window, 0, 0, 0, 0, 0,
+				     b->delta_x_nextdiff, b->delta_y_nextdiff);
+		}
+	}
+
 	weston_output_transform_coordinate(&output->base,
-					   motion_notify->event_x,
-					   motion_notify->event_y,
+					   motion_notify->event_x - b->delta_x,
+					   motion_notify->event_y - b->delta_y,
 					   &x, &y);
 
 	motion_event = (struct weston_pointer_motion_event) {
@@ -1293,12 +1335,18 @@  x11_backend_deliver_enter_event(struct x11_backend *b,
 
 	b->prev_x = x;
 	b->prev_y = y;
+	b->delta_x = 0;
+	b->delta_y = 0;
+	b->delta_x_nextdiff = 0;
+	b->delta_y_nextdiff = 0;
 }
 
 static void
 x11_backend_deliver_leave_event(struct x11_backend *b,
 				xcb_generic_event_t *event)
 {
+	struct x11_output *output;
+
 	xcb_leave_notify_event_t *leave_notify =
 			(xcb_leave_notify_event_t *) event;
 	if (leave_notify->state >= Button1Mask)
@@ -1306,6 +1354,13 @@  x11_backend_deliver_leave_event(struct x11_backend *b,
 	if (!b->has_xkb)
 		update_xkb_state_from_core(b, leave_notify->state);
 	notify_pointer_focus(&b->core_seat, NULL, 0, 0);
+
+	output = x11_backend_find_output(b, leave_notify->event);
+	if (!output)
+		return;
+	if (b->fullscreen)
+		XWarpPointer(b->dpy, None, output->window, 0, 0, 0, 0,
+			     b->prev_x, b->prev_y);
 }
 
 static int