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