Blame SOURCES/0009-xwayland-add-tablet-pad-support.patch

0c8e57
From 6f79f4993d351a891a715e994ab9574542e64b35 Mon Sep 17 00:00:00 2001
0c8e57
From: Peter Hutterer <peter.hutterer@who-t.net>
0c8e57
Date: Tue, 7 Feb 2017 15:04:46 +1000
0c8e57
Subject: [PATCH xserver 09/12] xwayland: add tablet pad support
0c8e57
0c8e57
Hooked up a bit differently to the other tools. Those tools can be static for
0c8e57
all and be re-used. The wacom driver initializes the pad with the correct
0c8e57
number of buttons though and we can't do this until we have the pad done event.
0c8e57
0c8e57
If the tablet is removed and we plug a different one in, we should initialize
0c8e57
that correctly, so unlike the other tools the pad is properly removed and
0c8e57
re-initialized on plug.
0c8e57
0c8e57
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
0c8e57
Acked-by: Ping Cheng <ping.cheng@wacom.com>
0c8e57
(cherry picked from commit 8475e6360ce31551d50fd63a26f7a44d1e8928f2)
0c8e57
---
0c8e57
 hw/xwayland/xwayland-input.c | 417 +++++++++++++++++++++++++++++++++++++++++++
0c8e57
 hw/xwayland/xwayland.h       |  28 +++
0c8e57
 2 files changed, 445 insertions(+)
0c8e57
0c8e57
diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
0c8e57
index 77cd42789..8011b965c 100644
0c8e57
--- a/hw/xwayland/xwayland-input.c
0c8e57
+++ b/hw/xwayland/xwayland-input.c
0c8e57
@@ -1341,6 +1341,7 @@ tablet_handle_removed(void *data, struct zwp_tablet_v2 *tablet)
0c8e57
             DisableDevice(xwl_seat->eraser, TRUE);
0c8e57
         if (xwl_seat->puck)
0c8e57
             DisableDevice(xwl_seat->puck, TRUE);
0c8e57
+        /* pads are removed separately */
0c8e57
     }
0c8e57
 
0c8e57
     zwp_tablet_v2_destroy(tablet);
0c8e57
@@ -1701,6 +1702,418 @@ static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
0c8e57
 };
0c8e57
 
0c8e57
 static void
0c8e57
+tablet_pad_ring_destroy(struct xwl_tablet_pad_ring *ring)
0c8e57
+{
0c8e57
+    zwp_tablet_pad_ring_v2_destroy(ring->ring);
0c8e57
+    xorg_list_del(&ring->link);
0c8e57
+    free(ring);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_ring_source(void *data,
0c8e57
+                       struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
0c8e57
+                       uint32_t source)
0c8e57
+{
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_ring_angle(void *data,
0c8e57
+                      struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
0c8e57
+                      wl_fixed_t degrees)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad_ring *ring = data;
0c8e57
+    struct xwl_tablet_pad *pad = ring->group->pad;
0c8e57
+    double deg = wl_fixed_to_double(degrees);
0c8e57
+    ValuatorMask mask;
0c8e57
+
0c8e57
+    valuator_mask_zero(&mask);
0c8e57
+    valuator_mask_set(&mask, 5 + ring->index, deg/360.0  * 71);
0c8e57
+    QueuePointerEvents(pad->xdevice, MotionNotify, 0, 0, &mask);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_ring_stop(void *data,
0c8e57
+                     struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2)
0c8e57
+{
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_ring_frame(void *data,
0c8e57
+                      struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
0c8e57
+                      uint32_t time)
0c8e57
+{
0c8e57
+}
0c8e57
+
0c8e57
+static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = {
0c8e57
+    tablet_pad_ring_source,
0c8e57
+    tablet_pad_ring_angle,
0c8e57
+    tablet_pad_ring_stop,
0c8e57
+    tablet_pad_ring_frame,
0c8e57
+};
0c8e57
+
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_strip_destroy(struct xwl_tablet_pad_strip *strip)
0c8e57
+{
0c8e57
+    zwp_tablet_pad_strip_v2_destroy(strip->strip);
0c8e57
+    xorg_list_del(&strip->link);
0c8e57
+    free(strip);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_strip_source(void *data,
0c8e57
+                        struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
0c8e57
+                        uint32_t source)
0c8e57
+{
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_strip_position(void *data,
0c8e57
+                          struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
0c8e57
+                          uint32_t position)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad_strip *strip = data;
0c8e57
+    struct xwl_tablet_pad *pad = strip->group->pad;
0c8e57
+    ValuatorMask mask;
0c8e57
+
0c8e57
+    valuator_mask_zero(&mask);
0c8e57
+    valuator_mask_set(&mask, 3 + strip->index, position/65535.0 * 2048);
0c8e57
+    QueuePointerEvents(pad->xdevice, MotionNotify, 0, 0, &mask);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_strip_stop(void *data,
0c8e57
+                      struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2)
0c8e57
+{
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_strip_frame(void *data,
0c8e57
+                       struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
0c8e57
+                       uint32_t time)
0c8e57
+{
0c8e57
+}
0c8e57
+
0c8e57
+static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = {
0c8e57
+    tablet_pad_strip_source,
0c8e57
+    tablet_pad_strip_position,
0c8e57
+    tablet_pad_strip_stop,
0c8e57
+    tablet_pad_strip_frame,
0c8e57
+};
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_group_destroy(struct xwl_tablet_pad_group *group)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad_ring *r, *tr;
0c8e57
+    struct xwl_tablet_pad_strip *s, *ts;
0c8e57
+
0c8e57
+    xorg_list_for_each_entry_safe(r, tr,
0c8e57
+                                  &group->pad_group_ring_list,
0c8e57
+                                  link)
0c8e57
+        tablet_pad_ring_destroy(r);
0c8e57
+
0c8e57
+    xorg_list_for_each_entry_safe(s, ts,
0c8e57
+                                  &group->pad_group_strip_list,
0c8e57
+                                  link)
0c8e57
+        tablet_pad_strip_destroy(s);
0c8e57
+
0c8e57
+    zwp_tablet_pad_group_v2_destroy(group->group);
0c8e57
+    xorg_list_del(&group->link);
0c8e57
+    free(group);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_group_buttons(void *data,
0c8e57
+                         struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
0c8e57
+                         struct wl_array *buttons)
0c8e57
+{
0c8e57
+
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_group_ring(void *data,
0c8e57
+                      struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
0c8e57
+                      struct zwp_tablet_pad_ring_v2 *wp_ring)
0c8e57
+{
0c8e57
+    static unsigned int ring_index = 0;
0c8e57
+    struct xwl_tablet_pad_group *group = data;
0c8e57
+    struct xwl_tablet_pad_ring *ring;
0c8e57
+
0c8e57
+    ring = calloc(1, sizeof *ring);
0c8e57
+    if (ring == NULL) {
0c8e57
+        ErrorF("%s ENOMEM\n", __func__);
0c8e57
+        return;
0c8e57
+    }
0c8e57
+
0c8e57
+    ring->index = ring_index++;
0c8e57
+    ring->group = group;
0c8e57
+    ring->ring = wp_ring;
0c8e57
+
0c8e57
+    xorg_list_add(&ring->link, &group->pad_group_ring_list);
0c8e57
+
0c8e57
+    zwp_tablet_pad_ring_v2_add_listener(wp_ring, &tablet_pad_ring_listener,
0c8e57
+                                        ring);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_group_strip(void *data,
0c8e57
+                       struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
0c8e57
+                       struct zwp_tablet_pad_strip_v2 *wp_strip)
0c8e57
+{
0c8e57
+    static unsigned int strip_index = 0;
0c8e57
+    struct xwl_tablet_pad_group *group = data;
0c8e57
+    struct xwl_tablet_pad_strip *strip;
0c8e57
+
0c8e57
+    strip = calloc(1, sizeof *strip);
0c8e57
+    if (strip == NULL) {
0c8e57
+        ErrorF("%s ENOMEM\n", __func__);
0c8e57
+        return;
0c8e57
+    }
0c8e57
+
0c8e57
+    strip->index = strip_index++;
0c8e57
+    strip->group = group;
0c8e57
+    strip->strip = wp_strip;
0c8e57
+
0c8e57
+    xorg_list_add(&strip->link, &group->pad_group_strip_list);
0c8e57
+
0c8e57
+    zwp_tablet_pad_strip_v2_add_listener(wp_strip, &tablet_pad_strip_listener,
0c8e57
+                                         strip);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_group_modes(void *data,
0c8e57
+                       struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
0c8e57
+                       uint32_t modes)
0c8e57
+{
0c8e57
+
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_group_done(void *data,
0c8e57
+                      struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2)
0c8e57
+{
0c8e57
+
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_group_mode_switch(void *data,
0c8e57
+                             struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
0c8e57
+                             uint32_t time,
0c8e57
+                             uint32_t serial,
0c8e57
+                             uint32_t mode)
0c8e57
+{
0c8e57
+
0c8e57
+}
0c8e57
+
0c8e57
+static struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = {
0c8e57
+    tablet_pad_group_buttons,
0c8e57
+    tablet_pad_group_ring,
0c8e57
+    tablet_pad_group_strip,
0c8e57
+    tablet_pad_group_modes,
0c8e57
+    tablet_pad_group_done,
0c8e57
+    tablet_pad_group_mode_switch,
0c8e57
+};
0c8e57
+
0c8e57
+static int
0c8e57
+xwl_tablet_pad_proc(DeviceIntPtr device, int what)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad *pad = device->public.devicePrivate;
0c8e57
+    /* Axis layout mirrors that of xf86-input-wacom to have better
0c8e57
+       compatibility with existing clients */
0c8e57
+#define NAXES 7
0c8e57
+    Atom axes_labels[NAXES] = { 0 };
0c8e57
+    BYTE map[MAX_BUTTONS + 1];
0c8e57
+    int i = 0;
0c8e57
+    Atom btn_labels[MAX_BUTTONS] = { 0 }; /* btn labels are meaningless */
0c8e57
+    int nbuttons;
0c8e57
+
0c8e57
+    switch (what) {
0c8e57
+    case DEVICE_INIT:
0c8e57
+        device->public.on = FALSE;
0c8e57
+
0c8e57
+        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_X);
0c8e57
+        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_Y);
0c8e57
+        /* The others have no good mapping */
0c8e57
+
0c8e57
+        if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels,
0c8e57
+                                           GetMotionHistorySize(), Absolute))
0c8e57
+            return BadValue;
0c8e57
+
0c8e57
+        for (i = 1; i <= MAX_BUTTONS; i++)
0c8e57
+            map[i] = i;
0c8e57
+
0c8e57
+        /* We need at least 7 buttons to allow scrolling */
0c8e57
+        nbuttons = min(max(pad->nbuttons + 4, 7), MAX_BUTTONS);
0c8e57
+
0c8e57
+        if (!InitButtonClassDeviceStruct(device, nbuttons,
0c8e57
+                                         btn_labels, map))
0c8e57
+            return BadValue;
0c8e57
+
0c8e57
+        /* Valuators */
0c8e57
+        InitValuatorAxisStruct(device, 0, axes_labels[0],
0c8e57
+                               0, 100, 1, 0, 1, Absolute);
0c8e57
+        InitValuatorAxisStruct(device, 1, axes_labels[1],
0c8e57
+                               0, 100, 1, 0, 1, Absolute);
0c8e57
+        /* Pressure - unused, for backwards compat only */
0c8e57
+        InitValuatorAxisStruct(device, 2, axes_labels[2],
0c8e57
+                               0, 2048, 1, 0, 1, Absolute);
0c8e57
+        /* strip x */
0c8e57
+        InitValuatorAxisStruct(device, 3, axes_labels[3],
0c8e57
+                               0, 2048, 1, 0, 1, Absolute);
0c8e57
+        /* strip y */
0c8e57
+        InitValuatorAxisStruct(device, 4, axes_labels[4],
0c8e57
+                               0, 2048, 1, 0, 1, Absolute);
0c8e57
+        /* ring */
0c8e57
+        InitValuatorAxisStruct(device, 5, axes_labels[5],
0c8e57
+                               0, 71, 1, 0, 1, Absolute);
0c8e57
+        /* ring2 */
0c8e57
+        InitValuatorAxisStruct(device, 6, axes_labels[6],
0c8e57
+                               0, 71, 1, 0, 1, Absolute);
0c8e57
+
0c8e57
+        if (!InitPtrFeedbackClassDeviceStruct(device, xwl_pointer_control))
0c8e57
+            return BadValue;
0c8e57
+
0c8e57
+        return Success;
0c8e57
+
0c8e57
+    case DEVICE_ON:
0c8e57
+        device->public.on = TRUE;
0c8e57
+        return Success;
0c8e57
+
0c8e57
+    case DEVICE_OFF:
0c8e57
+    case DEVICE_CLOSE:
0c8e57
+        device->public.on = FALSE;
0c8e57
+        return Success;
0c8e57
+    }
0c8e57
+
0c8e57
+    return BadMatch;
0c8e57
+#undef NAXES
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_group(void *data,
0c8e57
+                 struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
0c8e57
+                 struct zwp_tablet_pad_group_v2 *pad_group)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad *pad = data;
0c8e57
+    struct xwl_tablet_pad_group *group;
0c8e57
+
0c8e57
+    group = calloc(1, sizeof *group);
0c8e57
+    if (pad == NULL) {
0c8e57
+        ErrorF("%s ENOMEM\n", __func__);
0c8e57
+        return;
0c8e57
+    }
0c8e57
+
0c8e57
+    group->pad = pad;
0c8e57
+    group->group = pad_group;
0c8e57
+    xorg_list_init(&group->pad_group_ring_list);
0c8e57
+    xorg_list_init(&group->pad_group_strip_list);
0c8e57
+
0c8e57
+    xorg_list_add(&group->link, &pad->pad_group_list);
0c8e57
+
0c8e57
+    zwp_tablet_pad_group_v2_add_listener(pad_group,
0c8e57
+                                         &tablet_pad_group_listener,
0c8e57
+                                         group);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_path(void *data,
0c8e57
+                struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
0c8e57
+                const char *path)
0c8e57
+{
0c8e57
+
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_buttons(void *data,
0c8e57
+                   struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
0c8e57
+                   uint32_t buttons)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad *pad = data;
0c8e57
+
0c8e57
+    pad->nbuttons = buttons;
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_done(void *data,
0c8e57
+                struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad *pad = data;
0c8e57
+
0c8e57
+    pad->xdevice = add_device(pad->seat, "xwayland-pad",
0c8e57
+                              xwl_tablet_pad_proc);
0c8e57
+    pad->xdevice->public.devicePrivate = pad;
0c8e57
+    ActivateDevice(pad->xdevice, TRUE);
0c8e57
+    EnableDevice(pad->xdevice, TRUE);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_button(void *data,
0c8e57
+                  struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
0c8e57
+                  uint32_t time,
0c8e57
+                  uint32_t button,
0c8e57
+                  uint32_t state)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad *pad = data;
0c8e57
+    ValuatorMask mask;
0c8e57
+
0c8e57
+    button++; /* wayland index vs X's 1-offset */
0c8e57
+    /* skip scroll wheel buttons 4-7 */
0c8e57
+    button = button > 3 ? button + 4 : button;
0c8e57
+
0c8e57
+    valuator_mask_zero(&mask);
0c8e57
+    QueuePointerEvents(pad->xdevice,
0c8e57
+                       state ? ButtonPress : ButtonRelease, button, 0, &mask);
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_enter(void *data,
0c8e57
+                 struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
0c8e57
+                 uint32_t serial,
0c8e57
+                 struct zwp_tablet_v2 *tablet,
0c8e57
+                 struct wl_surface *surface)
0c8e57
+{
0c8e57
+    /* pairs the pad with the tablet but also to set the focus. We
0c8e57
+     * don't care about the pairing and always use X's focus */
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_leave(void *data,
0c8e57
+                 struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
0c8e57
+                 uint32_t serial,
0c8e57
+                 struct wl_surface *surface)
0c8e57
+{
0c8e57
+    /* pairs the pad with the tablet but also to set the focus. We
0c8e57
+     * don't care about the pairing and always use X's focus */
0c8e57
+}
0c8e57
+
0c8e57
+static void
0c8e57
+tablet_pad_removed(void *data,
0c8e57
+                   struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2)
0c8e57
+{
0c8e57
+    struct xwl_tablet_pad *pad = data;
0c8e57
+    struct xwl_tablet_pad_group *g, *tg;
0c8e57
+
0c8e57
+    xorg_list_for_each_entry_safe(g, tg, &pad->pad_group_list, link)
0c8e57
+        tablet_pad_group_destroy(g);
0c8e57
+
0c8e57
+    RemoveDevice(pad->xdevice, TRUE);
0c8e57
+    xorg_list_del(&pad->link);
0c8e57
+    zwp_tablet_pad_v2_destroy(pad->pad);
0c8e57
+    free(pad);
0c8e57
+}
0c8e57
+
0c8e57
+static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = {
0c8e57
+    tablet_pad_group,
0c8e57
+    tablet_pad_path,
0c8e57
+    tablet_pad_buttons,
0c8e57
+    tablet_pad_done,
0c8e57
+    tablet_pad_button,
0c8e57
+    tablet_pad_enter,
0c8e57
+    tablet_pad_leave,
0c8e57
+    tablet_pad_removed,
0c8e57
+};
0c8e57
+
0c8e57
+static void
0c8e57
 tablet_seat_handle_add_tablet(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
0c8e57
                               struct zwp_tablet_v2 *tablet)
0c8e57
 {
0c8e57
@@ -1769,8 +2182,12 @@ tablet_seat_handle_add_pad(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
0c8e57
 
0c8e57
     xwl_tablet_pad->pad = pad;
0c8e57
     xwl_tablet_pad->seat = xwl_seat;
0c8e57
+    xorg_list_init(&xwl_tablet_pad->pad_group_list);
0c8e57
 
0c8e57
     xorg_list_add(&xwl_tablet_pad->link, &xwl_seat->tablet_pads);
0c8e57
+
0c8e57
+    zwp_tablet_pad_v2_add_listener(pad, &tablet_pad_listener,
0c8e57
+                                   xwl_tablet_pad);
0c8e57
 }
0c8e57
 
0c8e57
 static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
0c8e57
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
0c8e57
index 02a218c43..250564f73 100644
0c8e57
--- a/hw/xwayland/xwayland.h
0c8e57
+++ b/hw/xwayland/xwayland.h
0c8e57
@@ -216,10 +216,38 @@ struct xwl_tablet_tool {
0c8e57
     struct xwl_cursor cursor;
0c8e57
 };
0c8e57
 
0c8e57
+struct xwl_tablet_pad_ring {
0c8e57
+    unsigned int index;
0c8e57
+    struct xorg_list link;
0c8e57
+    struct xwl_tablet_pad_group *group;
0c8e57
+    struct zwp_tablet_pad_ring_v2 *ring;
0c8e57
+};
0c8e57
+
0c8e57
+struct xwl_tablet_pad_strip {
0c8e57
+    unsigned int index;
0c8e57
+    struct xorg_list link;
0c8e57
+    struct xwl_tablet_pad_group *group;
0c8e57
+    struct zwp_tablet_pad_strip_v2 *strip;
0c8e57
+};
0c8e57
+
0c8e57
+struct xwl_tablet_pad_group {
0c8e57
+    struct xorg_list link;
0c8e57
+    struct xwl_tablet_pad *pad;
0c8e57
+    struct zwp_tablet_pad_group_v2 *group;
0c8e57
+
0c8e57
+    struct xorg_list pad_group_ring_list;
0c8e57
+    struct xorg_list pad_group_strip_list;
0c8e57
+};
0c8e57
+
0c8e57
 struct xwl_tablet_pad {
0c8e57
     struct xorg_list link;
0c8e57
     struct zwp_tablet_pad_v2 *pad;
0c8e57
     struct xwl_seat *seat;
0c8e57
+
0c8e57
+    DeviceIntPtr xdevice;
0c8e57
+
0c8e57
+    unsigned int nbuttons;
0c8e57
+    struct xorg_list pad_group_list;
0c8e57
 };
0c8e57
 
0c8e57
 struct xwl_output {
0c8e57
-- 
0c8e57
2.13.5
0c8e57