[PATCH 2/4] xwayland: Implement the wl_touch interface

Carlos Garnacho carlosg at gnome.org
Thu Oct 23 06:44:13 PDT 2014


A DeviceIntPtr with touch valuators is also created in order to deliver
the translated touch events. The lifetime of xwl_touch structs is tied
to the wayland ones, finishing in either wl_touch.up() or wl_touch.cancel()

Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
---
 hw/xwayland/xwayland-input.c | 206 ++++++++++++++++++++++++++++++++++++++++++-
 hw/xwayland/xwayland.h       |   2 +
 2 files changed, 205 insertions(+), 3 deletions(-)

diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c
index b661921..0aead8f 100644
--- a/hw/xwayland/xwayland-input.c
+++ b/hw/xwayland/xwayland-input.c
@@ -139,6 +139,61 @@ xwl_keyboard_proc(DeviceIntPtr device, int what)
     return BadMatch;
 }
 
+static int
+xwl_touch_proc(DeviceIntPtr device, int what)
+{
+#define NTOUCHPOINTS 20
+#define NBUTTONS 1
+#define NAXES 2
+    struct xwl_seat *xwl_seat = device->public.devicePrivate;
+    Atom btn_labels[NBUTTONS] = { 0 };
+    Atom axes_labels[NAXES] = { 0 };
+    BYTE map[NBUTTONS + 1] = { 0 };
+
+    switch (what) {
+    case DEVICE_INIT:
+        device->public.on = FALSE;
+
+        axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_X);
+        axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_ABS_MT_POSITION_Y);
+
+        if (!InitValuatorClassDeviceStruct(device, NAXES, axes_labels,
+                                           GetMotionHistorySize(), Absolute))
+            return BadValue;
+
+        if (!InitButtonClassDeviceStruct(device, NBUTTONS, btn_labels, map))
+            return BadValue;
+
+        if (!InitTouchClassDeviceStruct(device, NTOUCHPOINTS,
+                                        XIDirectTouch, NAXES))
+            return BadValue;
+
+        /* Valuators */
+        /* FIXME: devices might be mapped to a single wl_output */
+        InitValuatorAxisStruct(device, 0, axes_labels[0],
+                               0, xwl_seat->xwl_screen->width,
+                               10000, 0, 10000, Absolute);
+        InitValuatorAxisStruct(device, 1, axes_labels[1],
+                               0, xwl_seat->xwl_screen->height,
+                               10000, 0, 10000, Absolute);
+        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
+#undef NBUTTONS
+#undef NTOUCHPOINTS
+}
+
 static void
 pointer_handle_enter(void *data, struct wl_pointer *pointer,
                      uint32_t serial, struct wl_surface *surface,
@@ -471,6 +526,129 @@ static const struct wl_keyboard_listener keyboard_listener = {
     keyboard_handle_modifiers,
 };
 
+static struct xwl_touch *
+xwl_seat_lookup_touch(struct xwl_seat *xwl_seat, int32_t id)
+{
+    struct xwl_touch *xwl_touch, *next_xwl_touch;
+
+    xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch,
+                                  &xwl_seat->touches, link_touch) {
+        if (xwl_touch->id == id)
+            return xwl_touch;
+    }
+
+    return NULL;
+}
+
+static void
+xwl_touch_send_event(struct xwl_touch *xwl_touch,
+                     struct xwl_seat *xwl_seat, int type)
+{
+    int32_t dx, dy;
+    ValuatorMask mask;
+
+    dx = xwl_touch->window->window->drawable.x;
+    dy = xwl_touch->window->window->drawable.y;
+
+    valuator_mask_zero(&mask);
+    valuator_mask_set(&mask, 0, dx + xwl_touch->x);
+    valuator_mask_set(&mask, 1, dy + xwl_touch->y);
+    QueueTouchEvents(xwl_seat->touch, type, xwl_touch->id, 0, &mask);
+}
+
+static void
+touch_handle_down(void *data, struct wl_touch *wl_touch,
+                  uint32_t serial, uint32_t time,
+                  struct wl_surface *surface,
+                  int32_t id, wl_fixed_t sx_w, wl_fixed_t sy_w)
+{
+    struct xwl_seat *xwl_seat = data;
+    struct xwl_touch *xwl_touch;
+
+    if (surface == NULL)
+        return;
+
+    xwl_touch = calloc(sizeof *xwl_touch, 1);
+    if (xwl_touch == NULL) {
+        ErrorF("touch_handle_down ENOMEM");
+        return;
+    }
+
+    xwl_touch->window = wl_surface_get_user_data(surface);
+    xwl_touch->id = id;
+    xwl_touch->x = wl_fixed_to_int(sx_w);
+    xwl_touch->y = wl_fixed_to_int(sy_w);
+    xorg_list_add(&xwl_touch->link_touch, &xwl_seat->touches);
+
+    xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchBegin);
+}
+
+static void
+touch_handle_up(void *data, struct wl_touch *wl_touch,
+                uint32_t serial, uint32_t time, int32_t id)
+{
+    struct xwl_touch *xwl_touch;
+    struct xwl_seat *xwl_seat = data;
+
+    xwl_touch = xwl_seat_lookup_touch(xwl_seat, id);
+
+    if (!xwl_touch)
+        return;
+
+    xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchEnd);
+    xorg_list_del(&xwl_touch->link_touch);
+    free(xwl_touch);
+}
+
+static void
+touch_handle_motion(void *data, struct wl_touch *wl_touch,
+                    uint32_t time, int32_t id,
+                    wl_fixed_t sx_w, wl_fixed_t sy_w)
+{
+    struct xwl_seat *xwl_seat = data;
+    struct xwl_touch *xwl_touch;
+
+    xwl_touch = xwl_seat_lookup_touch(xwl_seat, id);
+
+    if (!xwl_touch)
+        return;
+
+    xwl_touch->x = wl_fixed_to_int(sx_w);
+    xwl_touch->y = wl_fixed_to_int(sy_w);
+    xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchUpdate);
+}
+
+static void
+touch_handle_frame(void *data, struct wl_touch *wl_touch)
+{
+}
+
+static void
+touch_handle_cancel(void *data, struct wl_touch *wl_touch)
+{
+    struct xwl_seat *xwl_seat = data;
+    struct xwl_touch *xwl_touch, *next_xwl_touch;
+
+    xorg_list_for_each_entry_safe(xwl_touch, next_xwl_touch,
+                                  &xwl_seat->touches, link_touch) {
+        /* We can't properly notify of cancellation to the X client
+         * once it thinks it has the ownership, send at least a
+         * TouchEnd event.
+         */
+        xwl_touch_send_event(xwl_touch, xwl_seat, XI_TouchEnd);
+        xorg_list_del(&xwl_touch->link_touch);
+        free(xwl_touch);
+    }
+}
+
+static const struct wl_touch_listener touch_listener = {
+    touch_handle_down,
+    touch_handle_up,
+    touch_handle_motion,
+    touch_handle_frame,
+    touch_handle_cancel
+};
+
 static DeviceIntPtr
 add_device(struct xwl_seat *xwl_seat,
            const char *driver, DeviceProc device_proc)
@@ -539,8 +717,26 @@ seat_handle_capabilities(void *data, struct wl_seat *seat,
             DisableDevice(xwl_seat->keyboard, TRUE);
     }
 
+    if (caps & WL_SEAT_CAPABILITY_TOUCH && xwl_seat->wl_touch == NULL) {
+        xwl_seat->wl_touch = wl_seat_get_touch(seat);
+        wl_touch_add_listener(xwl_seat->wl_touch,
+                              &touch_listener, xwl_seat);
+
+        if (xwl_seat->touch)
+            EnableDevice(xwl_seat->touch, TRUE);
+        else {
+            xwl_seat->touch =
+                add_device(xwl_seat, "xwayland-touch", xwl_touch_proc);
+        }
+    } else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && xwl_seat->wl_touch) {
+        wl_touch_release(xwl_seat->wl_touch);
+        xwl_seat->wl_touch = NULL;
+
+        if (xwl_seat->touch)
+            DisableDevice(xwl_seat->touch, TRUE);
+    }
+
     xwl_seat->xwl_screen->expecting_event--;
-    /* FIXME: Touch ... */
 }
 
 static void
@@ -591,8 +787,12 @@ xwl_seat_destroy(struct xwl_seat *xwl_seat)
         free(xwl_touch);
     }
 
-    RemoveDevice(xwl_seat->pointer, FALSE);
-    RemoveDevice(xwl_seat->keyboard, FALSE);
+    if (xwl_seat->pointer)
+        RemoveDevice(xwl_seat->pointer, FALSE);
+    if (xwl_seat->keyboard)
+        RemoveDevice(xwl_seat->keyboard, FALSE);
+    if (xwl_seat->touch)
+        RemoveDevice(xwl_seat->touch, FALSE);
     wl_seat_destroy(xwl_seat->seat);
     wl_surface_destroy(xwl_seat->cursor);
     wl_array_release(&xwl_seat->keys);
diff --git a/hw/xwayland/xwayland.h b/hw/xwayland/xwayland.h
index 3920e01..537cfbc 100644
--- a/hw/xwayland/xwayland.h
+++ b/hw/xwayland/xwayland.h
@@ -117,10 +117,12 @@ struct xwl_touch {
 struct xwl_seat {
     DeviceIntPtr pointer;
     DeviceIntPtr keyboard;
+    DeviceIntPtr touch;
     struct xwl_screen *xwl_screen;
     struct wl_seat *seat;
     struct wl_pointer *wl_pointer;
     struct wl_keyboard *wl_keyboard;
+    struct wl_touch *wl_touch;
     struct wl_array keys;
     struct wl_surface *cursor;
     struct xwl_window *focus_window;
-- 
2.1.0



More information about the xorg-devel mailing list