summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonas Ådahl <jadahl@gmail.com>2016-09-13 15:17:04 +0800
committerAdam Jackson <ajax@redhat.com>2016-10-05 13:46:30 -0400
commitb4644ce8d3420447a8e5a2339238968da0a59de7 (patch)
treecd6eacbd9bbbb69ff28ed8a81184b5f9035f29f5
parentaa9634d03bc2434dfd25476529eccb14e46fcfdc (diff)
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>
-rw-r--r--hw/xwayland/xwayland-input.c90
-rw-r--r--hw/xwayland/xwayland.h7
2 files changed, 82 insertions, 15 deletions
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index 355e69ae5..48f129431 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -347,30 +347,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
@@ -387,7 +404,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
@@ -452,7 +469,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
@@ -485,6 +502,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)
{
@@ -905,6 +948,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",
@@ -917,6 +972,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 4d5de76ec..e07b850c9 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -126,6 +126,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;
@@ -151,6 +152,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;
};