[mutter] wayland: Implement support for wp_relative_pointer



commit 5b0eabec51cbb08e2ded9133740cd1418afa75b7
Author: Jonas Ådahl <jadahl gmail com>
Date:   Tue Jun 2 16:26:34 2015 +0800

    wayland: Implement support for wp_relative_pointer
    
    Add support for sending relative pointer motion deltas to clients who
    request such events by creating wp_relative_pointer objects via
    wp_relative_pointer_manager.
    
    This currently implements the unstable version 1 from wayland-protocols.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=744104

 .gitignore                                |    2 +
 configure.ac                              |    2 +-
 src/Makefile.am                           |    2 +
 src/backends/meta-backend-private.h       |   14 +++
 src/backends/meta-backend.c               |   27 +++++
 src/backends/native/meta-backend-native.c |   14 +++
 src/wayland/meta-wayland-pointer.c        |  155 ++++++++++++++++++++++++++++-
 src/wayland/meta-wayland-pointer.h        |    3 +
 src/wayland/meta-wayland.c                |    1 +
 9 files changed, 218 insertions(+), 2 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 7a3d9d3..62a2743 100644
--- a/.gitignore
+++ b/.gitignore
@@ -68,6 +68,8 @@ src/xdg-shell-unstable-v*-protocol.c
 src/xdg-shell-unstable-v*-server-protocol.h
 src/pointer-gestures-unstable-v*-protocol.c
 src/pointer-gestures-unstable-v*-server-protocol.h
+src/relative-pointer-unstable-v*-protocol.c
+src/relative-pointer-unstable-v*-server-protocol.h
 src/meta/meta-version.h
 doc/reference/*.args
 doc/reference/*.bak
diff --git a/configure.ac b/configure.ac
index 8731079..412bb85 100644
--- a/configure.ac
+++ b/configure.ac
@@ -221,7 +221,7 @@ AS_IF([test "$have_wayland" = "yes"], [
   AC_SUBST([WAYLAND_SCANNER])
   AC_DEFINE([HAVE_WAYLAND],[1],[Define if you want to enable Wayland support])
 
-  PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.0],
+  PKG_CHECK_MODULES(WAYLAND_PROTOCOLS, [wayland-protocols >= 1.1],
                    [ac_wayland_protocols_pkgdatadir=`$PKG_CONFIG --variable=pkgdatadir wayland-protocols`])
   AC_SUBST(WAYLAND_PROTOCOLS_DATADIR, $ac_wayland_protocols_pkgdatadir)
 ])
diff --git a/src/Makefile.am b/src/Makefile.am
index 5468d47..71aa026 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -51,6 +51,8 @@ mutter_built_sources += \
        gtk-shell-server-protocol.h             \
        xdg-shell-unstable-v5-protocol.c                                \
        xdg-shell-unstable-v5-server-protocol.h                         \
+       relative-pointer-unstable-v1-protocol.c                         \
+       relative-pointer-unstable-v1-server-protocol.h                  \
        $(NULL)
 endif
 
diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h
index d2c6276..6fa468d 100644
--- a/src/backends/meta-backend-private.h
+++ b/src/backends/meta-backend-private.h
@@ -87,6 +87,13 @@ struct _MetaBackendClass
 
   void (* update_screen_size) (MetaBackend *backend, int width, int height);
   void (* select_stage_events) (MetaBackend *backend);
+
+  gboolean (* get_relative_motion_deltas) (MetaBackend *backend,
+                                           const        ClutterEvent *event,
+                                           double       *dx,
+                                           double       *dy,
+                                           double       *dx_unaccel,
+                                           double       *dy_unaccel);
 };
 
 MetaIdleMonitor * meta_backend_get_idle_monitor (MetaBackend *backend,
@@ -110,4 +117,11 @@ struct xkb_keymap * meta_backend_get_keymap (MetaBackend *backend);
 void meta_backend_update_last_device (MetaBackend *backend,
                                       int          device_id);
 
+gboolean meta_backend_get_relative_motion_deltas (MetaBackend *backend,
+                                                  const        ClutterEvent *event,
+                                                  double       *dx,
+                                                  double       *dy,
+                                                  double       *dx_unaccel,
+                                                  double       *dy_unaccel);
+
 #endif /* META_BACKEND_PRIVATE_H */
diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c
index 8197478..05d160d 100644
--- a/src/backends/meta-backend.c
+++ b/src/backends/meta-backend.c
@@ -353,6 +353,17 @@ meta_backend_real_select_stage_events (MetaBackend *backend)
   /* Do nothing */
 }
 
+static gboolean
+meta_backend_real_get_relative_motion_deltas (MetaBackend *backend,
+                                             const         ClutterEvent *event,
+                                             double        *dx,
+                                             double        *dy,
+                                             double        *dx_unaccel,
+                                             double        *dy_unaccel)
+{
+  return FALSE;
+}
+
 static void
 meta_backend_class_init (MetaBackendClass *klass)
 {
@@ -366,6 +377,7 @@ meta_backend_class_init (MetaBackendClass *klass)
   klass->ungrab_device = meta_backend_real_ungrab_device;
   klass->update_screen_size = meta_backend_real_update_screen_size;
   klass->select_stage_events = meta_backend_real_select_stage_events;
+  klass->get_relative_motion_deltas = meta_backend_real_get_relative_motion_deltas;
 
   g_signal_new ("keymap-changed",
                 G_TYPE_FROM_CLASS (object_class),
@@ -544,6 +556,21 @@ meta_backend_update_last_device (MetaBackend *backend,
     }
 }
 
+gboolean
+meta_backend_get_relative_motion_deltas (MetaBackend *backend,
+                                         const        ClutterEvent *event,
+                                         double       *dx,
+                                         double       *dy,
+                                         double       *dx_unaccel,
+                                         double       *dy_unaccel)
+{
+  MetaBackendClass *klass = META_BACKEND_GET_CLASS (backend);
+  return klass->get_relative_motion_deltas (backend,
+                                            event,
+                                            dx, dy,
+                                            dx_unaccel, dy_unaccel);
+}
+
 static GType
 get_backend_type (void)
 {
diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c
index d22bed1..5a1c1b4 100644
--- a/src/backends/native/meta-backend-native.c
+++ b/src/backends/native/meta-backend-native.c
@@ -306,6 +306,19 @@ meta_backend_native_lock_layout_group (MetaBackend *backend,
   g_signal_emit_by_name (backend, "keymap-layout-group-changed", idx, 0);
 }
 
+static gboolean
+meta_backend_native_get_relative_motion_deltas (MetaBackend *backend,
+                                                const        ClutterEvent *event,
+                                                double       *dx,
+                                                double       *dy,
+                                                double       *dx_unaccel,
+                                                double       *dy_unaccel)
+{
+  return clutter_evdev_event_get_relative_motion (event,
+                                                  dx, dy,
+                                                  dx_unaccel, dy_unaccel);
+}
+
 static void
 meta_backend_native_class_init (MetaBackendNativeClass *klass)
 {
@@ -323,6 +336,7 @@ meta_backend_native_class_init (MetaBackendNativeClass *klass)
   backend_class->set_keymap = meta_backend_native_set_keymap;
   backend_class->get_keymap = meta_backend_native_get_keymap;
   backend_class->lock_layout_group = meta_backend_native_lock_layout_group;
+  backend_class->get_relative_motion_deltas = meta_backend_native_get_relative_motion_deltas;
 }
 
 static void
diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c
index 92acffa..ef3228e 100644
--- a/src/wayland/meta-wayland-pointer.c
+++ b/src/wayland/meta-wayland-pointer.c
@@ -63,6 +63,8 @@
 #include "backends/meta-cursor-tracker-private.h"
 #include "backends/meta-cursor-renderer.h"
 
+#include "relative-pointer-unstable-v1-server-protocol.h"
+
 #ifdef HAVE_NATIVE_BACKEND
 #include "backends/native/meta-backend-native.h"
 #endif
@@ -96,6 +98,7 @@ meta_wayland_pointer_client_new (void)
   wl_list_init (&pointer_client->pointer_resources);
   wl_list_init (&pointer_client->swipe_gesture_resources);
   wl_list_init (&pointer_client->pinch_gesture_resources);
+  wl_list_init (&pointer_client->relative_pointer_resources);
 
   return pointer_client;
 }
@@ -124,6 +127,11 @@ meta_wayland_pointer_client_free (MetaWaylandPointerClient *pointer_client)
       wl_list_remove (wl_resource_get_link (resource));
       wl_list_init (wl_resource_get_link (resource));
     }
+  wl_resource_for_each_safe (resource, next, &pointer_client->relative_pointer_resources)
+    {
+      wl_list_remove (wl_resource_get_link (resource));
+      wl_list_init (wl_resource_get_link (resource));
+    }
 
   g_slice_free (MetaWaylandPointerClient, pointer_client);
 }
@@ -133,7 +141,8 @@ meta_wayland_pointer_client_is_empty (MetaWaylandPointerClient *pointer_client)
 {
   return (wl_list_empty (&pointer_client->pointer_resources) &&
           wl_list_empty (&pointer_client->swipe_gesture_resources) &&
-          wl_list_empty (&pointer_client->pinch_gesture_resources));
+          wl_list_empty (&pointer_client->pinch_gesture_resources) &&
+          wl_list_empty (&pointer_client->relative_pointer_resources));
 }
 
 MetaWaylandPointerClient *
@@ -264,6 +273,53 @@ meta_wayland_pointer_broadcast_frame (MetaWaylandPointer *pointer)
     }
 }
 
+static void
+meta_wayland_pointer_send_relative_motion (MetaWaylandPointer *pointer,
+                                           const ClutterEvent *event)
+{
+  struct wl_resource *resource;
+  double dx, dy;
+  double dx_unaccel, dy_unaccel;
+  uint64_t time_us;
+  uint32_t time_us_hi;
+  uint32_t time_us_lo;
+  wl_fixed_t dxf, dyf;
+  wl_fixed_t dx_unaccelf, dy_unaccelf;
+
+  if (!pointer->focus_client)
+    return;
+
+  if (!meta_backend_get_relative_motion_deltas (meta_get_backend (),
+                                                event,
+                                                &dx, &dy,
+                                                &dx_unaccel, &dy_unaccel))
+    return;
+
+#ifdef HAVE_NATIVE_BACKEND
+  time_us = clutter_evdev_event_get_time_usec (event);
+  if (time_us == 0)
+#endif
+    time_us = clutter_event_get_time (event) * 1000ULL;
+  time_us_hi = (uint32_t) (time_us >> 32);
+  time_us_lo = (uint32_t) time_us;
+  dxf = wl_fixed_from_double (dx);
+  dyf = wl_fixed_from_double (dy);
+  dx_unaccelf = wl_fixed_from_double (dx_unaccel);
+  dy_unaccelf = wl_fixed_from_double (dy_unaccel);
+
+  wl_resource_for_each (resource,
+                        &pointer->focus_client->relative_pointer_resources)
+    {
+      zwp_relative_pointer_v1_send_relative_motion (resource,
+                                                    time_us_hi,
+                                                    time_us_lo,
+                                                    dxf,
+                                                    dyf,
+                                                    dx_unaccelf,
+                                                    dy_unaccelf);
+    }
+}
+
 void
 meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
                                   const ClutterEvent *event)
@@ -285,6 +341,8 @@ meta_wayland_pointer_send_motion (MetaWaylandPointer *pointer,
       wl_pointer_send_motion (resource, time, sx, sy);
     }
 
+  meta_wayland_pointer_send_relative_motion (pointer, event);
+
   meta_wayland_pointer_broadcast_frame (pointer);
 }
 
@@ -1098,6 +1156,101 @@ meta_wayland_pointer_get_top_popup (MetaWaylandPointer *pointer)
 }
 
 static void
+relative_pointer_destroy (struct wl_client *client,
+                          struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static const struct zwp_relative_pointer_v1_interface relative_pointer_interface = {
+  relative_pointer_destroy
+};
+
+static void
+relative_pointer_manager_destroy (struct wl_client *client,
+                                  struct wl_resource *resource)
+{
+  wl_resource_destroy (resource);
+}
+
+static void
+relative_pointer_manager_get_relative_pointer (struct wl_client   *client,
+                                               struct wl_resource *resource,
+                                               uint32_t            id,
+                                               struct wl_resource *pointer_resource)
+{
+  MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource);
+  struct wl_resource *cr;
+  MetaWaylandPointerClient *pointer_client;
+
+  cr = wl_resource_create (client, &zwp_relative_pointer_v1_interface,
+                           wl_resource_get_version (resource), id);
+  if (cr == NULL)
+    {
+      wl_client_post_no_memory (client);
+      return;
+    }
+
+  wl_resource_set_implementation (cr, &relative_pointer_interface,
+                                  pointer,
+                                  meta_wayland_pointer_unbind_pointer_client_resource);
+
+  pointer_client = meta_wayland_pointer_ensure_pointer_client (pointer, client);
+
+  wl_list_insert (&pointer_client->relative_pointer_resources,
+                  wl_resource_get_link (cr));
+}
+
+static const struct zwp_relative_pointer_manager_v1_interface relative_pointer_manager = {
+  relative_pointer_manager_destroy,
+  relative_pointer_manager_get_relative_pointer,
+};
+
+static void
+bind_relative_pointer_manager (struct wl_client *client,
+                               void             *data,
+                               uint32_t          version,
+                               uint32_t          id)
+{
+  MetaWaylandCompositor *compositor = data;
+  struct wl_resource *resource;
+
+  resource = wl_resource_create (client,
+                                 &zwp_relative_pointer_manager_v1_interface,
+                                 1, id);
+
+  if (version != 1)
+    wl_resource_post_error (resource,
+                            WL_DISPLAY_ERROR_INVALID_OBJECT,
+                            "bound invalid version %u of "
+                            "wp_relative_pointer_manager",
+                            version);
+
+  wl_resource_set_implementation (resource, &relative_pointer_manager,
+                                  compositor,
+                                  NULL);
+}
+
+void
+meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor)
+{
+  /* Relative pointer events are currently only supported by the native backend
+   * so lets just advertise the extension when the native backend is used.
+   */
+#ifdef HAVE_NATIVE_BACKEND
+  if (!META_IS_BACKEND_NATIVE (meta_get_backend ()))
+    return;
+#else
+  return;
+#endif
+
+  if (!wl_global_create (compositor->wayland_display,
+                         &zwp_relative_pointer_manager_v1_interface, 1,
+                         compositor, bind_relative_pointer_manager))
+    g_error ("Could not create relative pointer manager global");
+}
+
+static void
 cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role)
 {
   MetaWaylandSurface *surface =
diff --git a/src/wayland/meta-wayland-pointer.h b/src/wayland/meta-wayland-pointer.h
index 7e31da9..cfe1b46 100644
--- a/src/wayland/meta-wayland-pointer.h
+++ b/src/wayland/meta-wayland-pointer.h
@@ -58,6 +58,7 @@ struct _MetaWaylandPointerClient
   struct wl_list pointer_resources;
   struct wl_list swipe_gesture_resources;
   struct wl_list pinch_gesture_resources;
+  struct wl_list relative_pointer_resources;
 };
 
 struct _MetaWaylandPointer
@@ -142,4 +143,6 @@ MetaWaylandPointerClient * meta_wayland_pointer_get_pointer_client (MetaWaylandP
                                                                     struct wl_client   *client);
 void meta_wayland_pointer_unbind_pointer_client_resource (struct wl_resource *resource);
 
+void meta_wayland_relative_pointer_init (MetaWaylandCompositor *compositor);
+
 #endif /* META_WAYLAND_POINTER_H */
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 523fbce..a878f32 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -328,6 +328,7 @@ meta_wayland_init (void)
   meta_wayland_shell_init (compositor);
   meta_wayland_pointer_gestures_init (compositor);
   meta_wayland_seat_init (compositor);
+  meta_wayland_relative_pointer_init (compositor);
 
   if (!meta_xwayland_start (&compositor->xwayland_manager, compositor->wayland_display))
     g_error ("Failed to start X Wayland");


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