xwayland: Set unaccelerated pointer motion delta if available

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 <jadahl@gmail.com>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
Jonas Ådahl 2016-09-13 15:17:04 +08:00 committed by Adam Jackson
parent aa9634d03b
commit b4644ce8d3
2 changed files with 81 additions and 14 deletions

View File

@ -347,30 +347,47 @@ pointer_handle_leave(void *data, struct wl_pointer *pointer,
} }
static void static void
dispatch_pointer_event(struct xwl_seat *xwl_seat) dispatch_pointer_motion_event(struct xwl_seat *xwl_seat)
{ {
ValuatorMask mask; ValuatorMask mask;
if (xwl_seat->pending_pointer_event.has_absolute) { if (xwl_seat->pending_pointer_event.has_absolute ||
int sx; xwl_seat->pending_pointer_event.has_relative) {
int sy; int x;
int dx; int y;
int dy;
sx = wl_fixed_to_int(xwl_seat->pending_pointer_event.x); if (xwl_seat->pending_pointer_event.has_absolute) {
sy = wl_fixed_to_int(xwl_seat->pending_pointer_event.y); int sx = wl_fixed_to_int(xwl_seat->pending_pointer_event.x);
dx = xwl_seat->focus_window->window->drawable.x; int sy = wl_fixed_to_int(xwl_seat->pending_pointer_event.y);
dy = xwl_seat->focus_window->window->drawable.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_zero(&mask);
valuator_mask_set(&mask, 0, dx + sx); if (xwl_seat->pending_pointer_event.has_relative) {
valuator_mask_set(&mask, 1, dy + sy); 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, QueuePointerEvents(xwl_seat->pointer, MotionNotify, 0,
POINTER_ABSOLUTE | POINTER_SCREEN, &mask); POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
} }
xwl_seat->pending_pointer_event.has_absolute = FALSE; xwl_seat->pending_pointer_event.has_absolute = FALSE;
xwl_seat->pending_pointer_event.has_relative = FALSE;
} }
static void static void
@ -387,7 +404,7 @@ pointer_handle_motion(void *data, struct wl_pointer *pointer,
xwl_seat->pending_pointer_event.y = sy_w; xwl_seat->pending_pointer_event.y = sy_w;
if (wl_proxy_get_version((struct wl_proxy *) xwl_seat->wl_pointer) < 5) 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 static void
@ -452,7 +469,7 @@ pointer_handle_frame(void *data, struct wl_pointer *wl_pointer)
{ {
struct xwl_seat *xwl_seat = data; struct xwl_seat *xwl_seat = data;
dispatch_pointer_event(xwl_seat); dispatch_pointer_motion_event(xwl_seat);
} }
static void static void
@ -484,6 +501,32 @@ static const struct wl_pointer_listener pointer_listener = {
pointer_handle_axis_discrete, pointer_handle_axis_discrete,
}; };
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 static void
keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial, keyboard_handle_key(void *data, struct wl_keyboard *keyboard, uint32_t serial,
uint32_t time, uint32_t key, uint32_t state) uint32_t time, uint32_t key, uint32_t state)
@ -905,6 +948,18 @@ release_pointer(struct xwl_seat *xwl_seat)
static void static void
init_relative_pointer(struct xwl_seat *xwl_seat) 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) { if (xwl_seat->relative_pointer == NULL) {
xwl_seat->relative_pointer = xwl_seat->relative_pointer =
add_device(xwl_seat, "xwayland-relative-pointer", add_device(xwl_seat, "xwayland-relative-pointer",
@ -917,6 +972,11 @@ init_relative_pointer(struct xwl_seat *xwl_seat)
static void static void
release_relative_pointer(struct xwl_seat *xwl_seat) 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) if (xwl_seat->relative_pointer)
DisableDevice(xwl_seat->relative_pointer, TRUE); DisableDevice(xwl_seat->relative_pointer, TRUE);
} }

View File

@ -126,6 +126,7 @@ struct xwl_seat {
struct xwl_screen *xwl_screen; struct xwl_screen *xwl_screen;
struct wl_seat *seat; struct wl_seat *seat;
struct wl_pointer *wl_pointer; struct wl_pointer *wl_pointer;
struct zwp_relative_pointer_v1 *wp_relative_pointer;
struct wl_keyboard *wl_keyboard; struct wl_keyboard *wl_keyboard;
struct wl_touch *wl_touch; struct wl_touch *wl_touch;
struct wl_array keys; struct wl_array keys;
@ -151,6 +152,12 @@ struct xwl_seat {
Bool has_absolute; Bool has_absolute;
wl_fixed_t x; wl_fixed_t x;
wl_fixed_t y; wl_fixed_t y;
Bool has_relative;
double dx;
double dy;
double dx_unaccel;
double dy_unaccel;
} pending_pointer_event; } pending_pointer_event;
}; };