[PATCH xwayland 5/7] xwayland: Handle tablet_tool events

Carlos Garnacho carlosg at gnome.org
Fri Nov 4 20:15:15 UTC 2016


From: Jason Gerecke <killertofu at gmail.com>

Translates Wayland tablet events into corresponding X11 tablet events. As
with the prior commit, these events are modeled after those created by the
xf86-input-wacom driver to maximize compatibility with existing applications.

FIXME: Note the fixme in tablet_tool_proximity_in...

Signed-off-by: Jason Gerecke <jason.gerecke at wacom.com>
Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
---
 hw/xwayland/xwayland-input.c | 314 +++++++++++++++++++++++++++++++++++++++++++
 hw/xwayland/xwayland.h       |   9 ++
 2 files changed, 323 insertions(+)

diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index cdebfe0..041ac4b 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -1316,6 +1316,309 @@ static const struct zwp_tablet_v2_listener tablet_listener = {
     tablet_handle_removed
 };
 
+static void
+tablet_tool_handle_type(void *data, struct zwp_tablet_tool_v2 *tool,
+                        uint32_t type)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+
+    switch (type) {
+        case ZWP_TABLET_TOOL_V2_TYPE_ERASER:
+            xwl_tablet_tool->xdevice = xwl_seat->eraser;
+            break;
+        case ZWP_TABLET_TOOL_V2_TYPE_MOUSE:
+        case ZWP_TABLET_TOOL_V2_TYPE_LENS:
+            xwl_tablet_tool->xdevice = xwl_seat->puck;
+            break;
+        default:
+            xwl_tablet_tool->xdevice = xwl_seat->stylus;
+            break;
+    }
+}
+
+static void
+tablet_tool_handle_hardware_serial(void *data, struct zwp_tablet_tool_v2 *tool,
+                                   uint32_t hi, uint32_t low)
+{
+}
+
+static void
+tablet_tool_handle_hardware_id_wacom(void *data, struct zwp_tablet_tool_v2 *tool,
+                                     uint32_t hi, uint32_t low)
+{
+}
+
+static void
+tablet_tool_handle_capability(void *data, struct zwp_tablet_tool_v2 *tool,
+                               uint32_t capability)
+{
+}
+
+static void
+tablet_tool_handle_done(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+}
+
+static void
+tablet_tool_handle_removed(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+
+    xorg_list_del(&xwl_tablet_tool->link);
+    zwp_tablet_tool_v2_destroy(xwl_tablet_tool->tool);
+    free(xwl_tablet_tool);
+}
+
+static void
+tablet_tool_handle_proximity_in(void *data, struct zwp_tablet_tool_v2 *tool,
+                                uint32_t serial, struct zwp_tablet_v2 *tablet,
+                                struct wl_surface *wl_surface)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+
+    //FIXME: Do we need the same NULL check used by the pointer?
+    xwl_seat->focus_window = wl_surface_get_user_data(wl_surface);
+}
+
+static void
+tablet_tool_handle_proximity_out(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+
+    xwl_seat->focus_window = NULL;
+}
+
+static void
+tablet_tool_handle_down(void *data, struct zwp_tablet_tool_v2 *tool, uint32_t serial)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+    ValuatorMask mask;
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    valuator_mask_zero(&mask);
+    QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonPress, 1, 0, &mask);
+}
+
+static void
+tablet_tool_handle_up(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    ValuatorMask mask;
+
+    valuator_mask_zero(&mask);
+    QueuePointerEvents(xwl_tablet_tool->xdevice, ButtonRelease, 1, 0, &mask);
+
+    xwl_tablet_tool->pressure = 0;
+    xwl_tablet_tool->tilt_x = 0;
+    xwl_tablet_tool->tilt_y = 0;
+    xwl_tablet_tool->rotation = 0;
+    xwl_tablet_tool->slider = 0;
+}
+
+static void
+tablet_tool_handle_motion(void *data, struct zwp_tablet_tool_v2 *tool,
+                          wl_fixed_t x, wl_fixed_t y)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+    int32_t dx, dy;
+    int sx = wl_fixed_to_int(x);
+    int sy = wl_fixed_to_int(y);
+
+    if (!xwl_seat->focus_window)
+        return;
+
+    dx = xwl_seat->focus_window->window->drawable.x;
+    dy = xwl_seat->focus_window->window->drawable.y;
+
+    xwl_tablet_tool->x = dx + sx;
+    xwl_tablet_tool->y = dy + sy;
+}
+
+static void
+tablet_tool_handle_pressure(void *data, struct zwp_tablet_tool_v2 *tool,
+                            uint32_t pressure_raw)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+    float pressure = pressure_raw / 65535.0;
+
+    if (!xwl_seat->focus_window)
+        return;
+
+    xwl_tablet_tool->pressure = (pressure * 2047.0);
+}
+
+static void
+tablet_tool_handle_distance(void *data, struct zwp_tablet_tool_v2 *tool,
+                            uint32_t distance_raw)
+{
+}
+
+static void
+tablet_tool_handle_tilt(void *data, struct zwp_tablet_tool_v2 *tool,
+                        int32_t tilt_x, int32_t tilt_y)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+
+    if (!xwl_seat->focus_window)
+        return;
+
+    xwl_tablet_tool->tilt_x = tilt_x / 100.0f;
+    xwl_tablet_tool->tilt_y = tilt_y / 100.0f;
+}
+
+static void
+tablet_tool_handle_rotation(void *data, struct zwp_tablet_tool_v2 *tool,
+                            int32_t angle)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+    float rotation = angle / 100.0f;
+
+    if (!xwl_seat->focus_window)
+        return;
+
+    /* change origin (buttons facing right [libinput +90 degrees]) and
+     * scaling (5 points per degree) to match wacom driver behavior
+     */
+    rotation = remainderf(rotation + 90.0f, 360.0f);
+    rotation *= 5.0f;
+    xwl_tablet_tool->rotation = rotation;
+}
+
+static void
+tablet_tool_handle_slider(void *data, struct zwp_tablet_tool_v2 *tool,
+                          int32_t position_raw)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+    float position = position_raw / 65535.0;
+
+    if (!xwl_seat->focus_window)
+        return;
+
+    xwl_tablet_tool->slider = (position * 1799.0f) - 900.0f;
+}
+
+static void
+tablet_tool_handle_wheel(void *data, struct zwp_tablet_tool_v2 *tool,
+                         int32_t degrees, int32_t clicks)
+{
+}
+
+static void
+tablet_tool_handle_button_state(void *data, struct zwp_tablet_tool_v2 *tool,
+                                uint32_t serial, uint32_t button,
+                                uint32_t state)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    struct xwl_seat *xwl_seat = xwl_tablet_tool->xwl_seat;
+    int xbtn = 0;
+    ValuatorMask mask;
+
+    if (button >= BTN_0 && button <= BTN_9)
+    {
+        xbtn = button - BTN_0 + 1;
+    }
+    else if (button >= BTN_A && button <= BTN_Z)
+    {
+        xbtn = button - BTN_A + 10;
+    }
+    else if (button >= BTN_BASE && button <= BTN_BASE6)
+    {
+        xbtn = button - BTN_BASE + 16;
+    }
+    else
+    {
+        switch (button)
+        {
+        case BTN_LEFT:
+        case BTN_TOUCH:
+            xbtn = 1;
+            break;
+
+        case BTN_MIDDLE:
+        case BTN_STYLUS:
+            xbtn = 2;
+            break;
+
+        case BTN_RIGHT:
+        case BTN_STYLUS2:
+            xbtn = 3;
+            break;
+
+        case BTN_SIDE:
+        case BTN_BACK:
+            xbtn = 8;
+            break;
+
+        case BTN_EXTRA:
+        case BTN_FORWARD:
+            xbtn = 9;
+            break;
+        }
+    }
+
+    if (!xbtn)
+    {
+        ErrorF("unknown tablet button number %d\n", button);
+        return;
+    }
+
+    xwl_seat->xwl_screen->serial = serial;
+
+    valuator_mask_zero(&mask);
+    QueuePointerEvents(xwl_tablet_tool->xdevice, state ? ButtonPress : ButtonRelease, xbtn, 0, &mask);
+}
+
+static void
+tablet_tool_handle_frame(void *data, struct zwp_tablet_tool_v2 *tool,
+                         uint32_t time)
+{
+    struct xwl_tablet_tool *xwl_tablet_tool = data;
+    ValuatorMask mask;
+
+    valuator_mask_zero(&mask);
+    valuator_mask_set(&mask, 0, xwl_tablet_tool->x);
+    valuator_mask_set(&mask, 1, xwl_tablet_tool->y);
+    valuator_mask_set(&mask, 2, xwl_tablet_tool->pressure);
+    valuator_mask_set(&mask, 3, xwl_tablet_tool->tilt_x);
+    valuator_mask_set(&mask, 4, xwl_tablet_tool->tilt_y);
+    valuator_mask_set(&mask, 5, xwl_tablet_tool->rotation + xwl_tablet_tool->slider);
+
+    //FIXME: Store button mask in xwl_tablet_tool and send events *HERE* if changed
+    QueuePointerEvents(xwl_tablet_tool->xdevice, MotionNotify, 0,
+               POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
+}
+
+static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
+    tablet_tool_handle_type,
+    tablet_tool_handle_hardware_serial,
+    tablet_tool_handle_hardware_id_wacom,
+    tablet_tool_handle_capability,
+    tablet_tool_handle_done,
+    tablet_tool_handle_removed,
+    tablet_tool_handle_proximity_in,
+    tablet_tool_handle_proximity_out,
+    tablet_tool_handle_down,
+    tablet_tool_handle_up,
+    tablet_tool_handle_motion,
+    tablet_tool_handle_pressure,
+    tablet_tool_handle_distance,
+    tablet_tool_handle_tilt,
+    tablet_tool_handle_rotation,
+    tablet_tool_handle_slider,
+    tablet_tool_handle_wheel,
+    tablet_tool_handle_button_state,
+    tablet_tool_handle_frame
+};
 
 static void
 tablet_seat_handle_add_tablet(void *data,
@@ -1354,11 +1657,22 @@ tablet_seat_handle_add_tool(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
     xwl_tablet_tool->xwl_seat = xwl_seat;
 
     xorg_list_add(&xwl_tablet_tool->link, &xwl_seat->tablet_tools);
+
+    zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, xwl_tablet_tool);
+}
+
+static void
+tablet_seat_handle_add_pad(void *data, struct zwp_tablet_seat_v2 *tablet_seat,
+                           struct zwp_tablet_pad_v2 *pad)
+{
+    /* FIXME: handle pads, probably unused by clients themselves anyway */
+    zwp_tablet_pad_v2_destroy (pad);
 }
 
 static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = {
     tablet_seat_handle_add_tablet,
     tablet_seat_handle_add_tool,
+    tablet_seat_handle_add_pad,
 };
 
 static void
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 7ee57c1..d3d8f1d 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -193,6 +193,15 @@ struct xwl_tablet_tool {
     struct xorg_list link;
     struct zwp_tablet_tool_v2 *tool;
     struct xwl_seat *xwl_seat;
+
+    DeviceIntPtr xdevice;
+    uint32_t x;
+    uint32_t y;
+    float pressure;
+    float tilt_x;
+    float tilt_y;
+    float rotation;
+    float slider;
 };
 
 struct xwl_output {
-- 
2.9.3



More information about the xorg-devel mailing list