[mutter] wayland: Implement the server side bits of wl_touch_interface



commit 2250865eb61f3110914e09cd50010f8e695c1aeb
Author: Carlos Garnacho <carlosg gnome org>
Date:   Thu Apr 24 14:50:47 2014 +0200

    wayland: Implement the server side bits of wl_touch_interface
    
    Clutter touch events are translated into events being sent down
    the interface resource, with the exception of FRAME/CANCEL events,
    which are handled directly via an evdev event filter.
    
    The seat now announces invariably the WL_SEAT_CAPABILITY_TOUCH
    capability, this should be eventually updated as devices come and
    go.
    
    The creation of MetaWaylandTouchSurface structs is dynamic, attached
    to the lifetime of first/last touch on the client surface, and only
    if the surface requests the wl_touch interface. MetaWaylandTouchInfo
    structs are created to track individual touches, and are locked to
    a single MetaWaylandTouchSurface (the implicit grab surface) determined
    on CLUTTER_TOUCH_BEGIN.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=724442

 src/Makefile.am                     |    2 +
 src/wayland/meta-wayland-seat.c     |   20 ++-
 src/wayland/meta-wayland-seat.h     |    2 +
 src/wayland/meta-wayland-touch.c    |  548 +++++++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-touch.h    |   62 ++++
 src/wayland/meta-wayland-types.h    |    1 +
 src/wayland/meta-wayland-versions.h |    2 +-
 7 files changed, 634 insertions(+), 3 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 6d2920b..9867be4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -222,6 +222,8 @@ libmutter_la_SOURCES =                              \
        wayland/meta-wayland-pointer.h          \
        wayland/meta-wayland-seat.c             \
        wayland/meta-wayland-seat.h             \
+       wayland/meta-wayland-touch.c            \
+       wayland/meta-wayland-touch.h            \
        wayland/meta-wayland-surface.c          \
        wayland/meta-wayland-surface.h          \
        wayland/meta-wayland-types.h            \
diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c
index 2dedf7e..82ceeb5 100644
--- a/src/wayland/meta-wayland-seat.c
+++ b/src/wayland/meta-wayland-seat.c
@@ -59,7 +59,10 @@ seat_get_touch (struct wl_client *client,
                 struct wl_resource *resource,
                 uint32_t id)
 {
-  /* Touch not supported */
+  MetaWaylandSeat *seat = wl_resource_get_user_data (resource);
+  MetaWaylandTouch *touch = &seat->touch;
+
+  meta_wayland_touch_create_new_resource (touch, client, resource, id);
 }
 
 static const struct wl_seat_interface seat_interface = {
@@ -84,7 +87,8 @@ bind_seat (struct wl_client *client,
 
   wl_seat_send_capabilities (resource,
                              WL_SEAT_CAPABILITY_POINTER |
-                             WL_SEAT_CAPABILITY_KEYBOARD);
+                             WL_SEAT_CAPABILITY_KEYBOARD |
+                             WL_SEAT_CAPABILITY_TOUCH);
 
   if (version >= WL_SEAT_NAME_SINCE_VERSION)
     wl_seat_send_name (resource, "seat0");
@@ -101,6 +105,7 @@ meta_wayland_seat_new (struct wl_display *display)
 
   meta_wayland_pointer_init (&seat->pointer, display);
   meta_wayland_keyboard_init (&seat->keyboard, display);
+  meta_wayland_touch_init (&seat->touch, display);
 
   seat->display = display;
 
@@ -120,6 +125,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
 {
   meta_wayland_pointer_release (&seat->pointer);
   meta_wayland_keyboard_release (&seat->keyboard);
+  meta_wayland_touch_release (&seat->touch);
 
   g_slice_free (MetaWaylandSeat, seat);
 }
@@ -142,6 +148,12 @@ meta_wayland_seat_update (MetaWaylandSeat    *seat,
       meta_wayland_keyboard_update (&seat->keyboard, (const ClutterKeyEvent *) event);
       break;
 
+    case CLUTTER_TOUCH_BEGIN:
+    case CLUTTER_TOUCH_UPDATE:
+    case CLUTTER_TOUCH_END:
+      meta_wayland_touch_update (&seat->touch, event);
+      break;
+
     default:
       break;
     }
@@ -163,6 +175,10 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat,
     case CLUTTER_KEY_RELEASE:
       return meta_wayland_keyboard_handle_event (&seat->keyboard,
                                                  (const ClutterKeyEvent *) event);
+    case CLUTTER_TOUCH_BEGIN:
+    case CLUTTER_TOUCH_UPDATE:
+    case CLUTTER_TOUCH_END:
+      return meta_wayland_touch_handle_event (&seat->touch, event);
 
     default:
       break;
diff --git a/src/wayland/meta-wayland-seat.h b/src/wayland/meta-wayland-seat.h
index d220174..e471ea1 100644
--- a/src/wayland/meta-wayland-seat.h
+++ b/src/wayland/meta-wayland-seat.h
@@ -28,6 +28,7 @@
 #include "meta-wayland-types.h"
 #include "meta-wayland-keyboard.h"
 #include "meta-wayland-pointer.h"
+#include "meta-wayland-touch.h"
 
 struct _MetaWaylandDataOffer
 {
@@ -53,6 +54,7 @@ struct _MetaWaylandSeat
   struct wl_list data_device_resource_list;
   MetaWaylandPointer pointer;
   MetaWaylandKeyboard keyboard;
+  MetaWaylandTouch touch;
 
   struct wl_display *display;
 };
diff --git a/src/wayland/meta-wayland-touch.c b/src/wayland/meta-wayland-touch.c
new file mode 100644
index 0000000..a91ee24
--- /dev/null
+++ b/src/wayland/meta-wayland-touch.c
@@ -0,0 +1,548 @@
+/*
+ * Wayland Support
+ *
+ * Copyright (C) 2014 Red Hat
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#define _GNU_SOURCE
+
+#include "config.h"
+
+#include <glib.h>
+#include <string.h>
+#include <clutter/evdev/clutter-evdev.h>
+
+#include "meta-surface-actor-wayland.h"
+#include "meta-wayland-private.h"
+
+struct _MetaWaylandTouchSurface
+{
+  MetaWaylandSurface *surface;
+  MetaWaylandTouch *touch;
+  struct wl_listener surface_destroy_listener;
+  struct wl_list resource_list;
+  gint touch_count;
+};
+
+struct _MetaWaylandTouchInfo
+{
+  MetaWaylandTouchSurface *touch_surface;
+  guint32 slot_serial;
+  gint32 slot;
+  gfloat x;
+  gfloat y;
+  guint updated : 1;
+};
+
+static void
+move_resources (struct wl_list *destination, struct wl_list *source)
+{
+  wl_list_insert_list (destination, source);
+  wl_list_init (source);
+}
+
+static void
+move_resources_for_client (struct wl_list   *destination,
+                          struct wl_list   *source,
+                          struct wl_client *client)
+{
+  struct wl_resource *resource, *tmp;
+  wl_resource_for_each_safe (resource, tmp, source)
+    {
+      if (wl_resource_get_client (resource) == client)
+        {
+          wl_list_remove (wl_resource_get_link (resource));
+          wl_list_insert (destination, wl_resource_get_link (resource));
+        }
+    }
+}
+
+static void
+touch_surface_free (gpointer data)
+{
+  MetaWaylandTouchSurface *touch_surface = data;
+  MetaWaylandTouch *touch = touch_surface->touch;
+
+  move_resources (&touch->resource_list,
+                  &touch_surface->resource_list);
+  wl_list_remove (&touch_surface->surface_destroy_listener.link);
+  g_free (touch_surface);
+}
+
+static MetaWaylandTouchSurface *
+touch_surface_increment_touch (MetaWaylandTouchSurface *surface)
+{
+  surface->touch_count++;
+  return surface;
+}
+
+static void
+touch_surface_decrement_touch (MetaWaylandTouchSurface *touch_surface)
+{
+  touch_surface->touch_count--;
+
+  if (touch_surface->touch_count == 0)
+    {
+      /* Now that there are no touches on the surface, free the
+       * MetaWaylandTouchSurface, the memory is actually owned by
+       * the touch_surface->touch_surfaces hashtable, so remove the
+       * item from there.
+       */
+      MetaWaylandTouch *touch = touch_surface->touch;
+      g_hash_table_remove (touch->touch_surfaces, touch_surface->surface);
+    }
+}
+
+static void
+touch_handle_surface_destroy (struct wl_listener *listener, void *data)
+{
+  MetaWaylandTouchSurface *touch_surface = wl_container_of (listener, touch_surface, 
surface_destroy_listener);
+  MetaWaylandSurface *surface = touch_surface->surface;
+  MetaWaylandTouch *touch = touch_surface->touch;
+  MetaWaylandTouchInfo *touch_info;
+  GHashTableIter iter;
+
+  g_hash_table_iter_init (&iter, touch->touches);
+
+  /* Destroy all touches on the surface, this indirectly drops touch_count
+   * on the touch_surface to 0, also freeing touch_surface and removing
+   * from the touch_surfaces hashtable.
+   */
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
+    {
+      if (touch_info->touch_surface == touch_surface)
+        g_hash_table_iter_remove (&iter);
+    }
+
+  /* Ensure the surface no longer exists */
+  g_assert (g_hash_table_remove (touch->touch_surfaces, surface) == FALSE);
+}
+
+static MetaWaylandTouchSurface *
+touch_surface_get (MetaWaylandTouch   *touch,
+                   MetaWaylandSurface *surface)
+{
+  MetaWaylandTouchSurface *touch_surface;
+
+  touch_surface = g_hash_table_lookup (touch->touch_surfaces, surface);
+
+  if (touch_surface)
+    return touch_surface_increment_touch (touch_surface);
+
+  /* Create a new one for this surface */
+  touch_surface = g_new0 (MetaWaylandTouchSurface, 1);
+  touch_surface->touch = touch;
+  touch_surface->surface = surface;
+  touch_surface->touch_count = 1;
+  touch_surface->surface_destroy_listener.notify = touch_handle_surface_destroy;
+  wl_resource_add_destroy_listener (touch_surface->surface->resource,
+                                    &touch_surface->surface_destroy_listener);
+
+  wl_list_init (&touch_surface->resource_list);
+  move_resources_for_client (&touch_surface->resource_list,
+                             &touch->resource_list,
+                             wl_resource_get_client (touch_surface->surface->resource));
+
+  g_hash_table_insert (touch->touch_surfaces, surface, touch_surface);
+
+  return touch_surface;
+}
+
+static MetaWaylandTouchInfo *
+touch_get_info (MetaWaylandTouch     *touch,
+                ClutterEventSequence *sequence,
+                gboolean              create)
+{
+  MetaWaylandTouchInfo *touch_info;
+
+  touch_info = g_hash_table_lookup (touch->touches, sequence);
+
+  if (!touch_info && create)
+    {
+      touch_info = g_new0 (MetaWaylandTouchInfo, 1);
+      touch_info->slot = clutter_evdev_event_sequence_get_slot (sequence);
+      g_hash_table_insert (touch->touches, sequence, touch_info);
+    }
+
+  return touch_info;
+}
+
+static void
+touch_get_relative_coordinates (MetaWaylandTouch   *touch,
+                                MetaWaylandSurface *surface,
+                                const ClutterEvent *event,
+                                gfloat             *x,
+                                gfloat             *y)
+{
+  gfloat event_x, event_y;
+
+  clutter_event_get_coords (event, &event_x, &event_y);
+
+  if (surface->surface_actor)
+    {
+      clutter_actor_transform_stage_point (CLUTTER_ACTOR (surface->surface_actor),
+                                           event_x, event_y,
+                                           &event_x, &event_y);
+    }
+
+  *x = event_x;
+  *y = event_y;
+}
+
+
+void
+meta_wayland_touch_update (MetaWaylandTouch   *touch,
+                           const ClutterEvent *event)
+{
+  MetaWaylandTouchInfo *touch_info;
+  ClutterEventSequence *sequence;
+
+  sequence = clutter_event_get_event_sequence (event);
+
+  if (event->type == CLUTTER_TOUCH_BEGIN)
+    {
+      MetaWaylandSurface *surface = NULL;
+      ClutterActor *actor;
+
+      actor = clutter_event_get_source (event);
+
+      if (META_IS_SURFACE_ACTOR_WAYLAND (actor))
+        surface = meta_surface_actor_wayland_get_surface (META_SURFACE_ACTOR_WAYLAND (actor));
+
+      if (!surface)
+        return;
+
+      touch_info = touch_get_info (touch, sequence, TRUE);
+      touch_info->touch_surface = touch_surface_get (touch, surface);
+    }
+  else
+    touch_info = touch_get_info (touch, sequence, FALSE);
+
+  if (!touch_info)
+    return;
+
+  if (event->type == CLUTTER_TOUCH_BEGIN ||
+      event->type == CLUTTER_TOUCH_END)
+    {
+      MetaWaylandSurface *surface = touch_info->touch_surface->surface;
+      struct wl_client *client = wl_resource_get_client (surface->resource);
+      struct wl_display *display = wl_client_get_display (client);
+
+      touch_info->slot_serial = wl_display_next_serial (display);
+    }
+
+  touch_get_relative_coordinates (touch, touch_info->touch_surface->surface,
+                                  event, &touch_info->x, &touch_info->y);
+  touch_info->updated = TRUE;
+}
+
+static void
+handle_touch_begin (MetaWaylandTouch   *touch,
+                    const ClutterEvent *event)
+{
+  MetaWaylandTouchInfo *touch_info;
+  ClutterEventSequence *sequence;
+  struct wl_resource *resource;
+  struct wl_list *l;
+
+  sequence = clutter_event_get_event_sequence (event);
+  touch_info = touch_get_info (touch, sequence, FALSE);
+
+  if (!touch_info)
+    return;
+
+  l = &touch_info->touch_surface->resource_list;
+  wl_resource_for_each(resource, l)
+    {
+      wl_touch_send_down (resource, touch_info->slot_serial,
+                          clutter_event_get_time (event),
+                          touch_info->touch_surface->surface->resource,
+                          touch_info->slot,
+                          wl_fixed_from_double (touch_info->x),
+                          wl_fixed_from_double (touch_info->y));
+    }
+}
+
+static void
+handle_touch_update (MetaWaylandTouch   *touch,
+                     const ClutterEvent *event)
+{
+  MetaWaylandTouchInfo *touch_info;
+  ClutterEventSequence *sequence;
+  struct wl_resource *resource;
+  struct wl_list *l;
+
+  sequence = clutter_event_get_event_sequence (event);
+  touch_info = touch_get_info (touch, sequence, FALSE);
+
+  if (!touch_info)
+    return;
+
+  l = &touch_info->touch_surface->resource_list;
+  wl_resource_for_each(resource, l)
+    {
+      wl_touch_send_motion (resource,
+                            clutter_event_get_time (event),
+                            touch_info->slot,
+                            wl_fixed_from_double (touch_info->x),
+                            wl_fixed_from_double (touch_info->y));
+    }
+}
+
+static void
+handle_touch_end (MetaWaylandTouch   *touch,
+                  const ClutterEvent *event)
+{
+  MetaWaylandTouchInfo *touch_info;
+  ClutterEventSequence *sequence;
+  struct wl_resource *resource;
+  struct wl_list *l;
+
+  sequence = clutter_event_get_event_sequence (event);
+  touch_info = touch_get_info (touch, sequence, FALSE);
+
+  if (!touch_info)
+    return;
+
+  l = &touch_info->touch_surface->resource_list;
+  wl_resource_for_each(resource, l)
+    {
+      wl_touch_send_up (resource, touch_info->slot_serial,
+                        clutter_event_get_time (event),
+                        touch_info->slot);
+    }
+
+  g_hash_table_remove (touch->touches, sequence);
+}
+
+static GList *
+touch_get_surfaces (MetaWaylandTouch *touch,
+                    gboolean          only_updated)
+{
+  MetaWaylandTouchInfo *touch_info;
+  GList *surfaces = NULL;
+  GHashTableIter iter;
+
+  g_hash_table_iter_init (&iter, touch->touches);
+
+  while (g_hash_table_iter_next (&iter, NULL, (gpointer*) &touch_info))
+    {
+      if (only_updated && !touch_info->updated)
+        continue;
+      if (g_list_find (surfaces, touch_info->touch_surface))
+        continue;
+
+      surfaces = g_list_prepend (surfaces, touch_info->touch_surface);
+      touch_info->updated = FALSE;
+    }
+
+  return g_list_reverse (surfaces);
+}
+
+static void
+touch_send_frame_event (MetaWaylandTouch *touch)
+{
+  GList *surfaces, *s;
+
+  surfaces = s = touch_get_surfaces (touch, TRUE);
+
+  for (s = surfaces; s; s = s->next)
+    {
+      MetaWaylandTouchSurface *touch_surface = s->data;
+      struct wl_resource *resource;
+      struct wl_list *l;
+
+      l = &touch_surface->resource_list;
+      wl_resource_for_each(resource, l)
+        {
+          wl_touch_send_frame (resource);
+        }
+    }
+
+  g_list_free (surfaces);
+}
+
+static void
+check_send_frame_event (MetaWaylandTouch   *touch,
+                        const ClutterEvent *event)
+{
+  ClutterEventSequence *sequence;
+  gint32 slot;
+
+  sequence = clutter_event_get_event_sequence (event);
+  slot = clutter_evdev_event_sequence_get_slot (sequence);
+  touch->frame_slots &= ~(1 << slot);
+
+  if (touch->frame_slots == 0)
+    touch_send_frame_event (touch);
+}
+
+gboolean
+meta_wayland_touch_handle_event (MetaWaylandTouch   *touch,
+                                 const ClutterEvent *event)
+{
+  switch (event->type)
+    {
+    case CLUTTER_TOUCH_BEGIN:
+      handle_touch_begin (touch, event);
+      break;
+
+    case CLUTTER_TOUCH_UPDATE:
+      handle_touch_update (touch, event);
+      break;
+
+    case CLUTTER_TOUCH_END:
+      handle_touch_end (touch, event);
+      break;
+
+    default:
+      return FALSE;
+    }
+
+  check_send_frame_event (touch, event);
+  return FALSE;
+}
+
+static void
+unbind_resource (struct wl_resource *resource)
+{
+  wl_list_remove (wl_resource_get_link (resource));
+}
+
+static void
+touch_release (struct wl_client   *client,
+               struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static const struct wl_touch_interface touch_interface = {
+  touch_release,
+};
+
+static void
+touch_info_free (MetaWaylandTouchInfo *touch_info)
+{
+  touch_surface_decrement_touch (touch_info->touch_surface);
+  g_free (touch_info);
+}
+
+static void
+touch_handle_cancel_event (MetaWaylandTouch      *touch,
+                           struct libinput_event *event)
+{
+  GList *surfaces, *s;
+
+  surfaces = s = touch_get_surfaces (touch, FALSE);
+
+  while (s)
+    {
+      MetaWaylandTouchSurface *touch_surface = s->data;
+      struct wl_resource *resource;
+      struct wl_list *l;
+
+      l = &touch_surface->resource_list;
+      wl_resource_for_each(resource, l)
+        wl_touch_send_cancel (resource);
+    }
+
+  g_hash_table_remove_all (touch->touches);
+  g_list_free (surfaces);
+}
+
+static gboolean
+evdev_filter_func (struct libinput_event *event,
+                   gpointer               data)
+{
+  MetaWaylandTouch *touch = data;
+
+  switch (libinput_event_get_type (event))
+    {
+    case LIBINPUT_EVENT_TOUCH_DOWN:
+    case LIBINPUT_EVENT_TOUCH_UP:
+    case LIBINPUT_EVENT_TOUCH_MOTION: {
+      struct libinput_event_touch *touch_event;
+      int32_t slot;
+
+      touch_event = libinput_event_get_touch_event (event);
+      slot = libinput_event_touch_get_slot (touch_event);
+
+      /* XXX: Could theoretically overflow, 64 slots should be
+       * enough for most hw/usecases though.
+       */
+      touch->frame_slots |= (1 << slot);
+      break;
+    }
+    case LIBINPUT_EVENT_TOUCH_CANCEL:
+      /* Clutter translates this into individual CLUTTER_TOUCH_CANCEL events,
+       * which are not so useful when sending a global signal as the protocol
+       * requires.
+       */
+      touch_handle_cancel_event (touch, event);
+      break;
+    default:
+      break;
+    }
+
+  return CLUTTER_EVENT_PROPAGATE;
+}
+
+void
+meta_wayland_touch_init (MetaWaylandTouch  *touch,
+                         struct wl_display *display)
+{
+  ClutterDeviceManager *manager;
+
+  memset (touch, 0, sizeof *touch);
+
+  touch->display = display;
+  touch->touch_surfaces = g_hash_table_new_full (NULL, NULL, NULL,
+                                                 (GDestroyNotify) touch_surface_free);
+  touch->touches = g_hash_table_new_full (NULL, NULL, NULL,
+                                          (GDestroyNotify) touch_info_free);
+
+  wl_list_init (&touch->resource_list);
+
+  manager = clutter_device_manager_get_default ();
+  touch->device = clutter_device_manager_get_core_device (manager, CLUTTER_TOUCHSCREEN_DEVICE);
+  clutter_evdev_add_filter (evdev_filter_func, touch, NULL);
+}
+
+void
+meta_wayland_touch_release (MetaWaylandTouch *touch)
+{
+  clutter_evdev_remove_filter (evdev_filter_func, touch);
+  g_hash_table_unref (touch->touch_surfaces);
+  g_hash_table_unref (touch->touches);
+}
+
+void
+meta_wayland_touch_create_new_resource (MetaWaylandTouch   *touch,
+                                        struct wl_client   *client,
+                                        struct wl_resource *seat_resource,
+                                        uint32_t            id)
+{
+  struct wl_resource *cr;
+
+  cr = wl_resource_create (client, &wl_touch_interface,
+                          MIN (META_WL_TOUCH_VERSION, wl_resource_get_version (seat_resource)), id);
+  wl_resource_set_implementation (cr, NULL, touch, unbind_resource);
+  wl_list_insert (&touch->resource_list, wl_resource_get_link (cr));
+}
diff --git a/src/wayland/meta-wayland-touch.h b/src/wayland/meta-wayland-touch.h
new file mode 100644
index 0000000..e98d8b4
--- /dev/null
+++ b/src/wayland/meta-wayland-touch.h
@@ -0,0 +1,62 @@
+/*
+ * Wayland Support
+ *
+ * Copyright (C) 2014 Red Hat
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Carlos Garnacho <carlosg gnome org>
+ */
+
+#ifndef META_WAYLAND_TOUCH_H
+#define META_WAYLAND_TOUCH_H
+
+#include <wayland-server.h>
+
+#include <glib.h>
+
+#include "meta-wayland-types.h"
+
+typedef struct _MetaWaylandTouchSurface MetaWaylandTouchSurface;
+typedef struct _MetaWaylandTouchInfo MetaWaylandTouchInfo;
+
+struct _MetaWaylandTouch
+{
+  struct wl_display *display;
+  struct wl_list resource_list;
+
+  GHashTable *touch_surfaces; /* HT of MetaWaylandSurface->MetaWaylandTouchSurface */
+  GHashTable *touches; /* HT of sequence->MetaWaylandTouchInfo */
+
+  ClutterInputDevice *device;
+  guint64 frame_slots;
+};
+
+void meta_wayland_touch_init (MetaWaylandTouch  *touch,
+                              struct wl_display *display);
+
+void meta_wayland_touch_release (MetaWaylandTouch *touch);
+
+void meta_wayland_touch_create_new_resource (MetaWaylandTouch   *touch,
+                                             struct wl_client   *client,
+                                             struct wl_resource *seat_resource,
+                                             uint32_t            id);
+
+void meta_wayland_touch_update (MetaWaylandTouch   *touch,
+                                const ClutterEvent *event);
+
+gboolean meta_wayland_touch_handle_event (MetaWaylandTouch   *touch,
+                                          const ClutterEvent *event);
+
+#endif /* META_WAYLAND_TOUCH_H */
diff --git a/src/wayland/meta-wayland-types.h b/src/wayland/meta-wayland-types.h
index 177519d..dd51c61 100644
--- a/src/wayland/meta-wayland-types.h
+++ b/src/wayland/meta-wayland-types.h
@@ -29,6 +29,7 @@ typedef struct _MetaWaylandPointerGrabInterface MetaWaylandPointerGrabInterface;
 typedef struct _MetaWaylandKeyboard MetaWaylandKeyboard;
 typedef struct _MetaWaylandDataOffer MetaWaylandDataOffer;
 typedef struct _MetaWaylandDataSource MetaWaylandDataSource;
+typedef struct _MetaWaylandTouch MetaWaylandTouch;
 
 typedef struct _MetaWaylandBuffer MetaWaylandBuffer;
 typedef struct _MetaWaylandBufferReference MetaWaylandBufferReference;
diff --git a/src/wayland/meta-wayland-versions.h b/src/wayland/meta-wayland-versions.h
index bd61c7a..1dc9fbe 100644
--- a/src/wayland/meta-wayland-versions.h
+++ b/src/wayland/meta-wayland-versions.h
@@ -51,7 +51,7 @@
 #define META_WL_SURFACE_VERSION             3 /* from wl_compositor */
 #define META_WL_POINTER_VERSION             3 /* from wl_seat */
 #define META_WL_KEYBOARD_VERSION            3 /* from wl_seat */
-#define META_WL_TOUCH_VERSION               0 /* from wl_seat; wl_touch not supported */
+#define META_WL_TOUCH_VERSION               3 /* from wl_seat */
 #define META_WL_REGION_VERSION              1 /* from wl_compositor */
 #define META_XDG_SURFACE_VERSION            1 /* from xdg_shell */
 #define META_XDG_POPUP_VERSION              1 /* from xdg_shell */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]