[mutter/wip/wayland] wayland: Add basic mouse input support
- From: Neil Roberts <nroberts src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [mutter/wip/wayland] wayland: Add basic mouse input support
- Date: Wed, 11 Jan 2012 20:04:22 +0000 (UTC)
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]