If there was an relative pointer motion within the same frame as an absolute pointer motion, provide both the absolute coordinate and the unaccelerated delta when setting the valuator mask.
If a frame contained only a relative motion, queue an absolute motion with an unchanged position, but still pass the unaccelerated motion event. If the wl_seat advertised by the compositor is not new enough, assume each relative and absolute pointer motion arrives within their own separate frames. Signed-off-by: Jonas Ådahl <jad...@gmail.com> --- hw/xwayland/xwayland-input.c | 90 ++++++++++++++++++++++++++++++++++++-------- hw/xwayland/xwayland.h | 7 ++++ 2 files changed, 82 insertions(+), 15 deletions(-) diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 19cfd93..e1d751c 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -336,30 +336,47 @@ pointer_handle_leave(void *data, struct wl_pointer *pointer, } static void -dispatch_pointer_event(struct xwl_seat *xwl_seat) +dispatch_pointer_motion_event(struct xwl_seat *xwl_seat) { ValuatorMask mask; - if (xwl_seat->pending_pointer_event.has_absolute) { - int sx; - int sy; - int dx; - int dy; - - sx = wl_fixed_to_int(xwl_seat->pending_pointer_event.x); - sy = wl_fixed_to_int(xwl_seat->pending_pointer_event.y); - dx = xwl_seat->focus_window->window->drawable.x; - dy = xwl_seat->focus_window->window->drawable.y; + 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_absolute) { + 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; + + x = dx + sx; + y = dy + sy; + } else { + miPointerGetPosition(xwl_seat->pointer, &x, &y); + } valuator_mask_zero(&mask); - valuator_mask_set(&mask, 0, dx + sx); - valuator_mask_set(&mask, 1, dy + sy); + 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_set(&mask, 0, x); + valuator_mask_set(&mask, 1, y); + } QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0, POINTER_ABSOLUTE | POINTER_SCREEN, &mask); } xwl_seat->pending_pointer_event.has_absolute = FALSE; + xwl_seat->pending_pointer_event.has_relative = FALSE; } static void @@ -376,7 +393,7 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer, xwl_seat->pending_pointer_event.y = sy_w; if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5) - dispatch_pointer_event(xwl_seat); + dispatch_pointer_motion_event(xwl_seat); } static void @@ -441,7 +458,7 @@ pointer_handle_frame(void *data, struct wl_pointer *wl_pointer) { struct xwl_seat *xwl_seat = data; - dispatch_pointer_event(xwl_seat); + dispatch_pointer_motion_event(xwl_seat); } static void @@ -474,6 +491,32 @@ static const struct wl_pointer_listener pointer_listener = { }; static void +relative_pointer_handle_relative_motion(void *data, + struct zwp_relative_pointer_v1 *zwp_relative_pointer_v1, + uint32_t utime_hi, + uint32_t utime_lo, + wl_fixed_t dxf, + wl_fixed_t dyf, + wl_fixed_t dx_unaccelf, + wl_fixed_t dy_unaccelf) +{ + struct xwl_seat *xwl_seat = data; + + xwl_seat->pending_pointer_event.has_relative = TRUE; + xwl_seat->pending_pointer_event.dx = wl_fixed_to_double(dxf); + xwl_seat->pending_pointer_event.dy = wl_fixed_to_double(dyf); + xwl_seat->pending_pointer_event.dx_unaccel = wl_fixed_to_double(dx_unaccelf); + xwl_seat->pending_pointer_event.dy_unaccel = wl_fixed_to_double(dy_unaccelf); + + if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5) + dispatch_pointer_motion_event(xwl_seat); +} + +static const struct zwp_relative_pointer_v1_listener relative_pointer_listener = { + relative_pointer_handle_relative_motion, +}; + +static void keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state) { @@ -891,6 +934,18 @@ release_pointer(struct xwl_seat *xwl_seat) static void init_relative_pointer(struct xwl_seat *xwl_seat) { + struct zwp_relative_pointer_manager_v1 *relative_pointer_manager = + xwl_seat->xwl_screen->relative_pointer_manager; + + if (relative_pointer_manager) { + xwl_seat->wp_relative_pointer = + zwp_relative_pointer_manager_v1_get_relative_pointer( + relative_pointer_manager, xwl_seat->wl_pointer); + zwp_relative_pointer_v1_add_listener(xwl_seat->wp_relative_pointer, + &relative_pointer_listener, + xwl_seat); + } + if (xwl_seat->relative_pointer == NULL) { xwl_seat->relative_pointer = add_device(xwl_seat, "xwayland-relative-pointer", @@ -903,6 +958,11 @@ init_relative_pointer(struct xwl_seat *xwl_seat) static void release_relative_pointer(struct xwl_seat *xwl_seat) { + if (xwl_seat->wp_relative_pointer) { + zwp_relative_pointer_v1_destroy(xwl_seat->wp_relative_pointer); + xwl_seat->wp_relative_pointer = NULL; + } + if (xwl_seat->relative_pointer) DisableDevice(xwl_seat->relative_pointer, TRUE); } diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h index 1fbae15..24b3e91 100644 --- a/hw/xwayland/xwayland.h +++ b/hw/xwayland/xwayland.h @@ -125,6 +125,7 @@ struct xwl_seat { struct xwl_screen *xwl_screen; struct wl_seat *seat; struct wl_pointer *wl_pointer; + struct zwp_relative_pointer_v1 *wp_relative_pointer; struct wl_keyboard *wl_keyboard; struct wl_touch *wl_touch; struct wl_array keys; @@ -150,6 +151,12 @@ struct xwl_seat { Bool has_absolute; wl_fixed_t x; wl_fixed_t y; + + Bool has_relative; + double dx; + double dy; + double dx_unaccel; + double dy_unaccel; } pending_pointer_event; }; -- 2.7.4 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: https://lists.x.org/mailman/listinfo/xorg-devel