Blame SOURCES/0005-xwayland-Handle-tablet_tool-events.patch

c40fb2
From 4354336014ca0c29270a6cdf83e9f9e5fe16080e Mon Sep 17 00:00:00 2001
c40fb2
From: Jason Gerecke <killertofu@gmail.com>
c40fb2
Date: Fri, 14 Oct 2016 14:31:46 -0700
c40fb2
Subject: [PATCH xserver 05/12] xwayland: Handle tablet_tool events
c40fb2
c40fb2
Translates Wayland tablet events into corresponding X11 tablet events. As
c40fb2
with the prior commit, these events are modeled after those created by the
c40fb2
xf86-input-wacom driver to maximize compatibility with existing applications.
c40fb2
c40fb2
Signed-off-by: Jason Gerecke <jason.gerecke@wacom.com>
c40fb2
Signed-off-by: Carlos Garnacho <carlosg@gnome.org>
c40fb2
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
c40fb2
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
c40fb2
Acked-by: Ping Cheng <ping.cheng@wacom.com>
c40fb2
(cherry picked from commit 8a1defcc634daddbb3570519d69ec5c9e39a8b56)
c40fb2
---
c40fb2
 hw/xwayland/xwayland-input.c | 313 +++++++++++++++++++++++++++++++++++++++++++
c40fb2
 hw/xwayland/xwayland.h       |   9 ++
c40fb2
 2 files changed, 322 insertions(+)
c40fb2
c40fb2
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
c40fb2
index 64655de5f..142862f7e 100644
c40fb2
--- a/hw/xwayland/xwayland-input.c
c40fb2
+++ b/hw/xwayland/xwayland-input.c
c40fb2
@@ -1331,6 +1331,317 @@ static const struct zwp_tablet_v2_listener tablet_listener = {
c40fb2
 };
c40fb2
 
c40fb2
 static void
c40fb2
+tablet_tool_receive_type(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                         uint32_t type)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+
c40fb2
+    switch (type) {
c40fb2
+        case ZWP_TABLET_TOOL_V2_TYPE_ERASER:
c40fb2
+            xwl_tablet_tool->xdevice = xwl_seat->eraser;
c40fb2
+            break;
c40fb2
+        case ZWP_TABLET_TOOL_V2_TYPE_MOUSE:
c40fb2
+        case ZWP_TABLET_TOOL_V2_TYPE_LENS:
c40fb2
+            xwl_tablet_tool->xdevice = xwl_seat->puck;
c40fb2
+            break;
c40fb2
+        default:
c40fb2
+            xwl_tablet_tool->xdevice = xwl_seat->stylus;
c40fb2
+            break;
c40fb2
+    }
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_receive_hardware_serial(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                                    uint32_t hi, uint32_t low)
c40fb2
+{
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_receive_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                                      uint32_t hi, uint32_t low)
c40fb2
+{
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_receive_capability(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                               uint32_t capability)
c40fb2
+{
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_receive_done(void *data, struct zwp_tablet_tool_v2 *tool)
c40fb2
+{
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_receive_removed(void *data, struct zwp_tablet_tool_v2 *tool)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+
c40fb2
+    xorg_list_del(&xwl_tablet_tool->link);
c40fb2
+    zwp_tablet_tool_v2_destroy(tool);
c40fb2
+    free(xwl_tablet_tool);
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                         uint32_t serial, struct zwp_tablet_v2 *tablet,
c40fb2
+                         struct wl_surface *wl_surface)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+
c40fb2
+    /* There's a race here where if we create and then immediately
c40fb2
+     * destroy a surface, we might end up in a state where the Wayland
c40fb2
+     * compositor sends us an event for a surface that doesn't exist.
c40fb2
+     *
c40fb2
+     * Don't process enter events in this case.
c40fb2
+     *
c40fb2
+     * see pointer_handle_enter()
c40fb2
+     */
c40fb2
+    if (wl_surface == NULL)
c40fb2
+        return;
c40fb2
+
c40fb2
+    xwl_seat->focus_window = wl_surface_get_user_data(wl_surface);
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *tool)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+
c40fb2
+    xwl_seat->focus_window = NULL;
c40fb2
+
c40fb2
+    xwl_tablet_tool->pressure = 0;
c40fb2
+    xwl_tablet_tool->tilt_x = 0;
c40fb2
+    xwl_tablet_tool->tilt_y = 0;
c40fb2
+    xwl_tablet_tool->rotation = 0;
c40fb2
+    xwl_tablet_tool->slider = 0;
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+    ValuatorMask mask;
c40fb2
+
c40fb2
+    xwl_seat->xwl_screen->serial = serial;
c40fb2
+
c40fb2
+    valuator_mask_zero(&mask);
c40fb2
+    QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonPress, 1, 0, &mask);
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *tool)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    ValuatorMask mask;
c40fb2
+
c40fb2
+    valuator_mask_zero(&mask);
c40fb2
+    QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonRelease, 1, 0, &mask);
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                   wl_fixed_t x, wl_fixed_t y)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+    int32_t dx, dy;
c40fb2
+    int sx = wl_fixed_to_int(x);
c40fb2
+    int sy = wl_fixed_to_int(y);
c40fb2
+
c40fb2
+    if (!xwl_seat->focus_window)
c40fb2
+        return;
c40fb2
+
c40fb2
+    dx = xwl_seat->focus_window->window->drawable.x;
c40fb2
+    dy = xwl_seat->focus_window->window->drawable.y;
c40fb2
+
c40fb2
+    xwl_tablet_tool->x = dx + sx;
c40fb2
+    xwl_tablet_tool->y = dy + sy;
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_pressure(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                     uint32_t pressure)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+
c40fb2
+    if (!xwl_seat->focus_window)
c40fb2
+        return;
c40fb2
+
c40fb2
+    /* normalized to 65535 already */
c40fb2
+    xwl_tablet_tool->pressure = pressure;
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_distance(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                     uint32_t distance_raw)
c40fb2
+{
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                 wl_fixed_t tilt_x, wl_fixed_t tilt_y)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+
c40fb2
+    if (!xwl_seat->focus_window)
c40fb2
+        return;
c40fb2
+
c40fb2
+    xwl_tablet_tool->tilt_x = wl_fixed_to_double(tilt_x);
c40fb2
+    xwl_tablet_tool->tilt_y = wl_fixed_to_double(tilt_y);
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_rotation(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                     wl_fixed_t angle)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+    double rotation = wl_fixed_to_double(angle);
c40fb2
+
c40fb2
+    if (!xwl_seat->focus_window)
c40fb2
+        return;
c40fb2
+
c40fb2
+    /* change origin (buttons facing right [libinput +90 degrees]) and
c40fb2
+     * scaling (5 points per degree) to match wacom driver behavior
c40fb2
+     */
c40fb2
+    rotation = remainderf(rotation + 90.0f, 360.0f);
c40fb2
+    rotation *= 5.0f;
c40fb2
+    xwl_tablet_tool->rotation = rotation;
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                   int32_t position_raw)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+    float position = position_raw / 65535.0;
c40fb2
+
c40fb2
+    if (!xwl_seat->focus_window)
c40fb2
+        return;
c40fb2
+
c40fb2
+    xwl_tablet_tool->slider = (position * 1799.0f) - 900.0f;
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                  wl_fixed_t degrees, int32_t clicks)
c40fb2
+{
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_button_state(void *data, struct zwp_tablet_tool_v2 *tool,
c40fb2
+                         uint32_t serial, uint32_t button, uint32_t state)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->seat;
c40fb2
+    int xbtn = 0;
c40fb2
+    ValuatorMask mask;
c40fb2
+
c40fb2
+    /* BTN_0 .. BTN_9 */
c40fb2
+    if (button >= 0x100 && button <= 0x109) {
c40fb2
+        xbtn = button - 0x100 + 1;
c40fb2
+    }
c40fb2
+    /* BTN_A .. BTN_Z */
c40fb2
+    else if (button >= 0x130 && button <= 0x135) {
c40fb2
+        xbtn = button - 0x130 + 10;
c40fb2
+    }
c40fb2
+    /* BTN_BASE .. BTN_BASE6 */
c40fb2
+    else if (button >= 0x126 && button <= 0x12b) {
c40fb2
+        xbtn = button - 0x126 + 16;
c40fb2
+    }
c40fb2
+    else {
c40fb2
+        switch (button) {
c40fb2
+        case 0x110: /* BTN_LEFT    */
c40fb2
+        case 0x14a: /* BTN_TOUCH   */
c40fb2
+            xbtn = 1;
c40fb2
+            break;
c40fb2
+
c40fb2
+        case 0x112: /* BTN_MIDDLE  */
c40fb2
+        case 0x14b: /* BTN_STYLUS  */
c40fb2
+            xbtn = 2;
c40fb2
+            break;
c40fb2
+
c40fb2
+        case 0x111: /* BTN_RIGHT   */
c40fb2
+        case 0x14c: /* BTN_STYLUS2 */
c40fb2
+            xbtn = 3;
c40fb2
+            break;
c40fb2
+
c40fb2
+        case 0x113: /* BTN_SIDE    */
c40fb2
+        case 0x116: /* BTN_BACK    */
c40fb2
+            xbtn = 8;
c40fb2
+            break;
c40fb2
+
c40fb2
+        case 0x114: /* BTN_EXTRA   */
c40fb2
+        case 0x115: /* BTN_FORWARD */
c40fb2
+            xbtn = 9;
c40fb2
+            break;
c40fb2
+        }
c40fb2
+    }
c40fb2
+
c40fb2
+    if (!xbtn) {
c40fb2
+        ErrorF("unknown tablet button number %d\n", button);
c40fb2
+        return;
c40fb2
+    }
c40fb2
+
c40fb2
+    xwl_seat->xwl_screen->serial = serial;
c40fb2
+
c40fb2
+    valuator_mask_zero(&mask);
c40fb2
+    QueuePointerEvents(xwl_tablet_tool->xdevice,
c40fb2
+                       state ? ButtonPress : ButtonRelease, xbtn, 0, &mask);
c40fb2
+}
c40fb2
+
c40fb2
+static void
c40fb2
+tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t time)
c40fb2
+{
c40fb2
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
c40fb2
+    ValuatorMask mask;
c40fb2
+
c40fb2
+    valuator_mask_zero(&mask);
c40fb2
+    valuator_mask_set(&mask, 0, xwl_tablet_tool->x);
c40fb2
+    valuator_mask_set(&mask, 1, xwl_tablet_tool->y);
c40fb2
+    valuator_mask_set(&mask, 2, xwl_tablet_tool->pressure);
c40fb2
+    valuator_mask_set(&mask, 3, xwl_tablet_tool->tilt_x);
c40fb2
+    valuator_mask_set(&mask, 4, xwl_tablet_tool->tilt_y);
c40fb2
+    valuator_mask_set(&mask, 5, xwl_tablet_tool->rotation + xwl_tablet_tool->slider);
c40fb2
+
c40fb2
+    /* FIXME: Store button mask in xwl_tablet_tool and send events *HERE* if
c40fb2
+       changed */
c40fb2
+    QueuePointerEvents(xwl_tablet_tool->xdevice, MotionNotify, 0,
c40fb2
+               POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
c40fb2
+}
c40fb2
+
c40fb2
+static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
c40fb2
+    tablet_tool_receive_type,
c40fb2
+    tablet_tool_receive_hardware_serial,
c40fb2
+    tablet_tool_receive_hardware_id_wacom,
c40fb2
+    tablet_tool_receive_capability,
c40fb2
+    tablet_tool_receive_done,
c40fb2
+    tablet_tool_receive_removed,
c40fb2
+    tablet_tool_proximity_in,
c40fb2
+    tablet_tool_proximity_out,
c40fb2
+    tablet_tool_down,
c40fb2
+    tablet_tool_up,
c40fb2
+    tablet_tool_motion,
c40fb2
+    tablet_tool_pressure,
c40fb2
+    tablet_tool_distance,
c40fb2
+    tablet_tool_tilt,
c40fb2
+    tablet_tool_rotation,
c40fb2
+    tablet_tool_slider,
c40fb2
+    tablet_tool_wheel,
c40fb2
+    tablet_tool_button_state,
c40fb2
+    tablet_tool_frame
c40fb2
+};
c40fb2
+
c40fb2
+static void
c40fb2
 tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
c40fb2
                               struct zwp_tablet_v2 *tablet)
c40fb2
 {
c40fb2
@@ -1368,6 +1679,8 @@ tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
c40fb2
     xwl_tablet_tool->seat = xwl_seat;
c40fb2
 
c40fb2
     xorg_list_add(&xwl_tablet_tool->link, &xwl_seat->tablet_tools);
c40fb2
+
c40fb2
+    zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, xwl_tablet_tool);
c40fb2
 }
c40fb2
 
c40fb2
 static void
c40fb2
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
c40fb2
index e7e62882b..fb9ac4804 100644
c40fb2
--- a/hw/xwayland/xwayland.h
c40fb2
+++ b/hw/xwayland/xwayland.h
c40fb2
@@ -193,6 +193,15 @@ struct xwl_tablet_tool {
c40fb2
     struct xorg_list link;
c40fb2
     struct zwp_tablet_tool_v2 *tool;
c40fb2
     struct xwl_seat *seat;
c40fb2
+
c40fb2
+    DeviceIntPtr xdevice;
c40fb2
+    uint32_t x;
c40fb2
+    uint32_t y;
c40fb2
+    uint32_t pressure;
c40fb2
+    float tilt_x;
c40fb2
+    float tilt_y;
c40fb2
+    float rotation;
c40fb2
+    float slider;
c40fb2
 };
c40fb2
 
c40fb2
 struct xwl_tablet_pad {
c40fb2
-- 
c40fb2
2.13.5
c40fb2