diff options
author | Olivier Fourdan <ofourdan@redhat.com> | 2021-02-09 13:04:59 +0100 |
---|---|---|
committer | Olivier Fourdan <ofourdan@redhat.com> | 2021-02-15 09:42:00 +0100 |
commit | c5c5322ad69b0751f16c785a479b2989b8794235 (patch) | |
tree | 61d2711cdd9f545c6b802657cf32df8f8bee2540 /hw | |
parent | ebdb2e264676c3b27a708328348efe73e0d3c8c2 (diff) |
xwayland: Use relative values for raw events
Xwayland supports relative motion events from the Wayland compositor via
the relative-pointer protocol, and converts those to the absolute range
in device units for raw events.
Some X11 clients however wrongly assume relative values in the axis
values even for devices explicitly labeled as absolute. While this is a
bug in the client, such applications would work fine in plain Xorg but
not with Xwayland.
To avoid that issue, use the relative values for raw events without
conversion, so that such application continue to work in Xwayland.
Thanks Peter for figuring out the root cause.
v2: Don't duplicate relative and absolute events (Peter)
v3: Use POINTER_RAWONLY (Peter)
Suggested-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Olivier Fourdan <ofourdan@redhat.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Closes: https://gitlab.freedesktop.org/xorg/xserver/-/issues/1130
Diffstat (limited to 'hw')
-rw-r--r-- | hw/xwayland/xwayland-input.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 2e4b20024..48216c548 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -497,14 +497,33 @@ dispatch_pointer_motion_event(struct xwl_seat *xwl_seat) dx_unaccel, dy_unaccel); } else if (xwl_seat->pending_pointer_event.has_absolute || xwl_seat->pending_pointer_event.has_relative) { - int x; - int y; + if (xwl_seat->pending_pointer_event.has_relative) { + double dx, dx_unaccel; + double dy, dy_unaccel; + + dx = xwl_seat->pending_pointer_event.dx; + dy = xwl_seat->pending_pointer_event.dy; + dx_unaccel = xwl_seat->pending_pointer_event.dx_unaccel; + dy_unaccel = xwl_seat->pending_pointer_event.dy_unaccel; + + valuator_mask_zero(&mask); + valuator_mask_set_unaccelerated(&mask, 0, dx, dx_unaccel); + valuator_mask_set_unaccelerated(&mask, 1, dy, dy_unaccel); + + QueuePointerEvents(xwl_seat->relative_pointer, MotionNotify, 0, + POINTER_RAWONLY, &mask); + } if (xwl_seat->pending_pointer_event.has_absolute) { + ValuatorMask mask; + DeviceIntPtr device; + int flags; int sx = wl_fixed_to_int(xwl_seat->pending_pointer_event.x); int sy = wl_fixed_to_int(xwl_seat->pending_pointer_event.y); int dx = xwl_seat->focus_window->window->drawable.x; int dy = xwl_seat->focus_window->window->drawable.y; + int x; + int y; if (xwl_window_has_viewport_enabled(xwl_seat->focus_window)) { sx *= xwl_seat->focus_window->scale_x; @@ -513,26 +532,21 @@ dispatch_pointer_motion_event(struct xwl_seat *xwl_seat) x = dx + sx; y = dy + sy; - } else { - miPointerGetPosition(xwl_seat->pointer, &x, &y); - } - valuator_mask_zero(&mask); - if (xwl_seat->pending_pointer_event.has_relative) { - double dx_unaccel; - double dy_unaccel; - - dx_unaccel = xwl_seat->pending_pointer_event.dx_unaccel; - dy_unaccel = xwl_seat->pending_pointer_event.dy_unaccel; - valuator_mask_set_absolute_unaccelerated(&mask, 0, x, dx_unaccel); - valuator_mask_set_absolute_unaccelerated(&mask, 1, y, dy_unaccel); - } else { + valuator_mask_zero(&mask); valuator_mask_set(&mask, 0, x); valuator_mask_set(&mask, 1, y); - } - QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0, - POINTER_ABSOLUTE | POINTER_SCREEN, &mask); + if (xwl_seat->pending_pointer_event.has_relative) { + flags = POINTER_ABSOLUTE | POINTER_SCREEN | POINTER_NORAW; + device = xwl_seat->relative_pointer; + } else { + flags = POINTER_ABSOLUTE | POINTER_SCREEN; + device = xwl_seat->pointer; + } + + QueuePointerEvents(device, MotionNotify, 0, flags, &mask); + } } xwl_seat->pending_pointer_event.has_absolute = FALSE; |