[mutter/wip/wayland] wayland: Add basic mouse input support



commit 05ae560445a8e68263c8cd32b8eab80819cbe5cc
Author: Neil Roberts <neil linux intel com>
Date:   Wed Jan 11 18:33:13 2012 +0000

    wayland: Add basic mouse input support
    
    This copies the basic mouse support from the test-wayland-surface demo
    in the Clutter source. It adds a basic wl_input_device implementation
    which can convert Clutter mouse events to Wayland events. For this to
    work all of the wayland surface actors need to be made reactive.

 src/Makefile.am                         |    4 +-
 src/wayland/meta-wayland-input-device.c |  293 +++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-input-device.h |   32 ++++
 src/wayland/meta-wayland-private.h      |    4 +
 src/wayland/meta-wayland.c              |   16 ++
 5 files changed, 348 insertions(+), 1 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 172bed7..0b64175 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -169,7 +169,9 @@ libmutter_la_SOURCES =				\
 if HAVE_WAYLAND
 libmutter_la_SOURCES +=				\
 	wayland/meta-wayland.c			\
-	wayland/meta-wayland-private.h
+	wayland/meta-wayland-private.h		\
+	wayland/meta-wayland-input-device.h	\
+	wayland/meta-wayland-input-device.c
 endif
 
 libmutter_la_LDFLAGS = -no-undefined
diff --git a/src/wayland/meta-wayland-input-device.c b/src/wayland/meta-wayland-input-device.c
new file mode 100644
index 0000000..89b71dc
--- /dev/null
+++ b/src/wayland/meta-wayland-input-device.c
@@ -0,0 +1,293 @@
+/*
+ * Wayland Support
+ *
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#include <config.h>
+
+#include <clutter/clutter.h>
+#include <clutter/wayland/clutter-wayland-compositor.h>
+#include <clutter/wayland/clutter-wayland-surface.h>
+#include <stdlib.h>
+#include <linux/input.h>
+#include "meta-wayland-input-device.h"
+#include "meta-wayland-private.h"
+
+struct _MetaWaylandInputDevice
+{
+  struct wl_input_device parent;
+
+  /* Last position of the pointer */
+  float pointer_x, pointer_y;
+
+  /* Position of the pointer within the surface */
+  int32_t pointer_sx, pointer_sy;
+};
+
+static void
+implicit_grab_motion (struct wl_grab *grab,
+                      uint32_t time,
+                      int32_t x,
+                      int32_t y)
+{
+  struct wl_resource *resource;
+
+  resource = grab->input_device->pointer_focus_resource;
+
+  if (resource)
+    {
+      MetaWaylandSurface *surface =
+        (MetaWaylandSurface *) grab->input_device->pointer_focus;
+      float sx, sy;
+
+      clutter_actor_transform_stage_point (surface->actor,
+                                           x,
+                                           y,
+                                           &sx,
+                                           &sy);
+
+      wl_resource_post_event (resource, WL_INPUT_DEVICE_MOTION,
+                              time, x, y, (int32_t) sx, (int32_t) sy);
+    }
+}
+
+static void
+implicit_grab_button (struct wl_grab *grab,
+                      uint32_t time,
+                      int32_t button,
+                      int32_t state)
+{
+  struct wl_resource *resource;
+
+  resource = grab->input_device->pointer_focus_resource;
+
+  if (resource)
+    wl_resource_post_event (resource, WL_INPUT_DEVICE_BUTTON,
+                            time, button, state);
+}
+
+static void
+implicit_grab_end(struct wl_grab *grab, uint32_t time)
+{
+}
+
+static const struct wl_grab_interface implicit_grab_interface = {
+  implicit_grab_motion,
+  implicit_grab_button,
+  implicit_grab_end
+};
+
+static void
+input_device_attach (struct wl_client *client,
+                     struct wl_resource *resource,
+                     uint32_t time,
+                     struct wl_resource *buffer_resource,
+                     int32_t hotspot_x,
+                     int32_t hotspot_y)
+{
+}
+
+const static struct wl_input_device_interface
+input_device_interface =
+  {
+    input_device_attach
+  };
+
+static void
+unbind_input_device (struct wl_resource *resource)
+{
+  wl_list_remove (&resource->link);
+  free (resource);
+}
+
+static void
+bind_input_device (struct wl_client *client,
+                   void *data,
+                   uint32_t version,
+                   uint32_t id)
+{
+  struct wl_input_device *device = data;
+  struct wl_resource *resource;
+
+  resource = wl_client_add_object (client,
+                                   &wl_input_device_interface,
+                                   &input_device_interface,
+                                   id,
+                                   data);
+
+  wl_list_insert (&device->resource_list, &resource->link);
+
+  resource->destroy = unbind_input_device;
+}
+
+MetaWaylandInputDevice *
+meta_wayland_input_device_new (struct wl_display *display)
+{
+  MetaWaylandInputDevice *device = g_new (MetaWaylandInputDevice, 1);
+
+  wl_input_device_init (&device->parent);
+
+  device->parent.implicit_grab.interface = &implicit_grab_interface;
+
+  wl_display_add_global (display,
+                         &wl_input_device_interface,
+                         device,
+                         bind_input_device);
+
+  return device;
+}
+
+static void
+set_pointer_focus_for_event (MetaWaylandInputDevice *input_device,
+                             const ClutterEvent *event)
+{
+  struct wl_input_device *device =
+    (struct wl_input_device *) input_device;
+  struct wl_surface *surface;
+
+  clutter_event_get_coords (event,
+                            &input_device->pointer_x,
+                            &input_device->pointer_y);
+
+  if (CLUTTER_WAYLAND_IS_SURFACE (event->any.source))
+    {
+      ClutterWaylandSurface *surface_actor =
+        CLUTTER_WAYLAND_SURFACE (event->any.source);
+      float fsx, fsy;
+
+      surface = clutter_wayland_surface_get_surface (surface_actor);
+
+      clutter_actor_transform_stage_point (event->any.source,
+                                           input_device->pointer_x,
+                                           input_device->pointer_y,
+                                           &fsx, &fsy);
+      input_device->pointer_sx = fsx;
+      input_device->pointer_sy = fsy;
+    }
+  else
+    {
+      surface = NULL;
+      input_device->pointer_sx = input_device->pointer_x;
+      input_device->pointer_sy = input_device->pointer_y;
+    }
+
+  wl_input_device_set_pointer_focus (device,
+                                     surface,
+                                     event->any.time,
+                                     input_device->pointer_x,
+                                     input_device->pointer_y,
+                                     input_device->pointer_sx,
+                                     input_device->pointer_sy);
+}
+
+static void
+handle_motion_event (MetaWaylandInputDevice *input_device,
+                     const ClutterMotionEvent *event)
+{
+  struct wl_input_device *device =
+    (struct wl_input_device *) input_device;
+
+  if (device->grab)
+    device->grab->interface->motion (device->grab,
+                                     event->time,
+                                     event->x,
+                                     event->y);
+  else
+    {
+      set_pointer_focus_for_event (input_device, (const ClutterEvent *) event);
+
+      if (device->pointer_focus_resource)
+        wl_resource_post_event (device->pointer_focus_resource,
+                                WL_INPUT_DEVICE_MOTION,
+                                time,
+                                (int32_t) input_device->pointer_x,
+                                (int32_t) input_device->pointer_y,
+                                input_device->pointer_sx,
+                                input_device->pointer_sy);
+    }
+}
+
+static void
+handle_button_event (MetaWaylandInputDevice *input_device,
+                     const ClutterButtonEvent *event)
+{
+  struct wl_input_device *device =
+    (struct wl_input_device *) input_device;
+  struct wl_surface *surface = device->pointer_focus;
+  gboolean state = event->type == CLUTTER_BUTTON_PRESS;
+  uint32_t button;
+
+  switch (event->button)
+    {
+      /* The evdev input right and middle button numbers are swapped
+         relative to how Clutter numbers them */
+    case 2:
+      button = BTN_MIDDLE;
+      break;
+
+    case 3:
+      button = BTN_RIGHT;
+      break;
+
+    default:
+      button = event->button + BTN_LEFT - 1;
+      break;
+    }
+
+  if (state && surface && device->grab == NULL)
+    wl_input_device_start_grab (device,
+                                &device->implicit_grab,
+                                button,
+                                event->time);
+
+  if (device->grab)
+    device->grab->interface->button (device->grab,
+                                     event->time,
+                                     button,
+                                     state);
+
+  if (!state && device->grab && device->grab_button == button)
+    {
+      wl_input_device_end_grab (device, event->time);
+
+      set_pointer_focus_for_event (input_device, (const ClutterEvent *) event);
+    }
+}
+
+void
+meta_wayland_input_device_handle_event (MetaWaylandInputDevice *input_device,
+                                        const ClutterEvent *event)
+{
+  switch (event->type)
+    {
+    case CLUTTER_MOTION:
+      handle_motion_event (input_device,
+                           (const ClutterMotionEvent *) event);
+      break;
+
+    case CLUTTER_BUTTON_PRESS:
+    case CLUTTER_BUTTON_RELEASE:
+      handle_button_event (input_device,
+                           (const ClutterButtonEvent *) event);
+      break;
+
+    default:
+      break;
+    }
+}
diff --git a/src/wayland/meta-wayland-input-device.h b/src/wayland/meta-wayland-input-device.h
new file mode 100644
index 0000000..bcb4068
--- /dev/null
+++ b/src/wayland/meta-wayland-input-device.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef META_WAYLAND_INPUT_H
+#define META_WAYLAND_INPUT_H
+
+#include <wayland-server.h>
+
+typedef struct _MetaWaylandInputDevice MetaWaylandInputDevice;
+
+MetaWaylandInputDevice *meta_wayland_input_device_new          (struct wl_display      *display);
+
+void                    meta_wayland_input_device_handle_event (MetaWaylandInputDevice *input_device,
+                                                                const ClutterEvent     *event);
+
+#endif /* META_WAYLAND_INPUT_H */
diff --git a/src/wayland/meta-wayland-private.h b/src/wayland/meta-wayland-private.h
index e12af3d..563b9a9 100644
--- a/src/wayland/meta-wayland-private.h
+++ b/src/wayland/meta-wayland-private.h
@@ -26,6 +26,8 @@
 
 #include <glib.h>
 
+#include "meta-wayland-input-device.h"
+
 typedef struct _MetaWaylandCompositor MetaWaylandCompositor;
 
 typedef struct
@@ -113,6 +115,8 @@ struct _MetaWaylandCompositor
   struct wl_client *xwayland_client;
   struct wl_resource *xserver_resource;
   GHashTable *window_surfaces;
+
+  MetaWaylandInputDevice *input_device;
 };
 
 void                    meta_wayland_init                   (void);
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 97594a4..fcd5d22 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -278,6 +278,7 @@ meta_wayland_surface_attach_buffer (struct wl_client *wayland_client,
   if (surface->actor)
     {
       surface_actor = CLUTTER_WAYLAND_SURFACE (surface->actor);
+      clutter_actor_set_reactive (surface->actor, TRUE);
       if (!clutter_wayland_surface_attach_buffer (surface_actor, wayland_buffer,
                                                   NULL))
         g_warning ("Failed to attach buffer to ClutterWaylandSurface");
@@ -995,6 +996,16 @@ stage_destroy_cb (void)
   meta_quit (META_EXIT_SUCCESS);
 }
 
+static gboolean
+event_cb (ClutterActor *stage,
+          const ClutterEvent *event,
+          MetaWaylandCompositor *compositor)
+{
+  meta_wayland_input_device_handle_event (compositor->input_device, event);
+
+  return FALSE;
+}
+
 void
 meta_wayland_init (void)
 {
@@ -1030,12 +1041,17 @@ meta_wayland_init (void)
   if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
     g_error ("Failed to initialize Clutter");
 
+  compositor->input_device =
+    meta_wayland_input_device_new (compositor->wayland_display);
+
   compositor->stage = clutter_stage_new ();
   clutter_stage_set_user_resizable (CLUTTER_STAGE (compositor->stage), FALSE);
   g_signal_connect_after (compositor->stage, "paint",
                           G_CALLBACK (paint_finished_cb), compositor);
   g_signal_connect (compositor->stage, "destroy",
                     G_CALLBACK (stage_destroy_cb), NULL);
+  g_signal_connect (compositor->stage, "event",
+                    G_CALLBACK (event_cb), compositor);
 
   meta_wayland_compositor_create_output (compositor, 0, 0, 800, 600);
 



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