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 <[email protected]>
---
libweston/compositor-x11.c | 59 ++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 57 insertions(+), 2 deletions(-)
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
_______________________________________________
wayland-devel mailing list
[email protected]
https://lists.freedesktop.org/mailman/listinfo/wayland-devel