[mutter/wip/wayland] wayland: Add an actor for the cursor



commit e431031cdf74e559b146eb33210e2fe08e5bcaed
Author: Neil Roberts <neil linux intel com>
Date:   Wed Jan 18 23:03:23 2012 +0000

    wayland: Add an actor for the cursor
    
    When running Mutter under Cogl's KMS backend no cursor will be
    provided so instead this makes it so the cursor will be painted as a
    ClutterTexture that gets moved in respose to mouse motion events. The
    painting is done in a subclass of ClutterStage so that we can
    guarantee that the actor will be painted on top of all other actors.
    
    The image for the pointer is taken from Weston. It gets installed into
    a fixed data location for mutter.

 Makefile.am                      |    2 +-
 configure.in                     |    1 +
 data/Makefile.am                 |    7 ++
 data/left_ptr.png                |  Bin 0 -> 1046 bytes
 src/Makefile.am                  |    4 +-
 src/wayland/meta-wayland-stage.c |  179 ++++++++++++++++++++++++++++++++++++++
 src/wayland/meta-wayland-stage.h |   85 ++++++++++++++++++
 src/wayland/meta-wayland.c       |    7 ++-
 8 files changed, 282 insertions(+), 3 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index d9c9d31..bc1cd77 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,5 +1,5 @@
 
-SUBDIRS=src po doc
+SUBDIRS=src data po doc
 
 EXTRA_DIST = HACKING MAINTAINERS rationales.txt
 
diff --git a/configure.in b/configure.in
index 5dc71f0..320cb5f 100644
--- a/configure.in
+++ b/configure.in
@@ -552,6 +552,7 @@ src/libmutter.pc
 src/mutter-plugins.pc
 src/tools/Makefile
 src/compositor/plugins/Makefile
+data/Makefile
 po/Makefile.in
 ])
 
diff --git a/data/Makefile.am b/data/Makefile.am
new file mode 100644
index 0000000..0fbff45
--- /dev/null
+++ b/data/Makefile.am
@@ -0,0 +1,7 @@
+defaultcursordir = $(datadir)/mutter/cursors
+
+dist_defaultcursor_DATA =
+
+if HAVE_WAYLAND
+dist_defaultcursor_DATA += left_ptr.png
+endif
diff --git a/data/left_ptr.png b/data/left_ptr.png
new file mode 100644
index 0000000..c42ac55
Binary files /dev/null and b/data/left_ptr.png differ
diff --git a/src/Makefile.am b/src/Makefile.am
index 0b64175..c46c71f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -171,7 +171,9 @@ libmutter_la_SOURCES +=				\
 	wayland/meta-wayland.c			\
 	wayland/meta-wayland-private.h		\
 	wayland/meta-wayland-input-device.h	\
-	wayland/meta-wayland-input-device.c
+	wayland/meta-wayland-input-device.c	\
+	wayland/meta-wayland-stage.h		\
+	wayland/meta-wayland-stage.c
 endif
 
 libmutter_la_LDFLAGS = -no-undefined
diff --git a/src/wayland/meta-wayland-stage.c b/src/wayland/meta-wayland-stage.c
new file mode 100644
index 0000000..4956f09
--- /dev/null
+++ b/src/wayland/meta-wayland-stage.c
@@ -0,0 +1,179 @@
+/*
+ * 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>
+
+#define COGL_ENABLE_EXPERIMENTAL_2_0_API
+#include <clutter/clutter.h>
+
+#include "meta-wayland-stage.h"
+
+#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X 10
+#define META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y 5
+
+G_DEFINE_TYPE (MetaWaylandStage, meta_wayland_stage, CLUTTER_TYPE_STAGE);
+
+static void
+meta_wayland_stage_dispose (GObject *object)
+{
+  MetaWaylandStage *self = (MetaWaylandStage *) object;
+
+  if (self->cursor_texture)
+    {
+      clutter_actor_destroy (self->cursor_texture);
+      self->cursor_texture = NULL;
+    }
+
+  G_OBJECT_CLASS (meta_wayland_stage_parent_class)->dispose (object);
+}
+
+static void
+meta_wayland_stage_finalize (GObject *object)
+{
+  MetaWaylandStage *self = (MetaWaylandStage *) object;
+
+  if (self->default_cursor_image)
+    cogl_object_unref (self->default_cursor_image);
+
+  G_OBJECT_CLASS (meta_wayland_stage_parent_class)->finalize (object);
+}
+
+static void
+meta_wayland_stage_paint (ClutterActor *actor)
+{
+  MetaWaylandStage *self = META_WAYLAND_STAGE (actor);
+
+  CLUTTER_ACTOR_CLASS (meta_wayland_stage_parent_class)->paint (actor);
+
+  /* Make sure the cursor is always painted on top of all of the other
+     actors */
+  clutter_actor_paint (self->cursor_texture);
+}
+
+static void
+update_cursor_position (MetaWaylandStage *self)
+{
+  clutter_actor_set_position (self->cursor_texture,
+                              self->cursor_x - self->cursor_hotspot_x,
+                              self->cursor_y - self->cursor_hotspot_y);
+}
+
+static void
+meta_wayland_stage_allocate (ClutterActor           *actor,
+                             const ClutterActorBox  *allocation,
+                             ClutterAllocationFlags  flags)
+{
+  MetaWaylandStage *self = META_WAYLAND_STAGE (actor);
+
+  CLUTTER_ACTOR_CLASS (meta_wayland_stage_parent_class)->allocate (actor,
+                                                                   allocation,
+                                                                   flags);
+
+  if (self->cursor_texture)
+    clutter_actor_allocate_preferred_size (self->cursor_texture, flags);
+}
+
+static void
+meta_wayland_stage_class_init (MetaWaylandStageClass *klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  ClutterActorClass *actor_class = (ClutterActorClass *) klass;
+
+  gobject_class->dispose = meta_wayland_stage_dispose;
+  gobject_class->finalize = meta_wayland_stage_finalize;
+
+  actor_class->paint = meta_wayland_stage_paint;
+  actor_class->allocate = meta_wayland_stage_allocate;
+}
+
+static CoglTexture *
+load_default_cursor_image (void)
+{
+  CoglTexture *ret;
+  GError *error = NULL;
+  char *filename;
+
+  filename = g_build_filename (MUTTER_DATADIR,
+                               "mutter/cursors/left_ptr.png",
+                               NULL);
+
+  ret = cogl_texture_new_from_file (filename,
+                                    COGL_TEXTURE_NONE,
+                                    COGL_PIXEL_FORMAT_ANY,
+                                    &error);
+  if (ret == NULL)
+    {
+      g_warning ("Failed to load default cursor: %s",
+                 error->message);
+      g_clear_error (&error);
+    }
+
+  g_free (filename);
+
+  return ret;
+}
+
+static void
+meta_wayland_stage_init (MetaWaylandStage *self)
+{
+  self->cursor_texture = clutter_texture_new ();
+
+  /* We don't want to add this as a container child so that we can
+     paint it manually above all of the other actors */
+  clutter_actor_set_parent (self->cursor_texture, CLUTTER_ACTOR (self));
+
+  self->default_cursor_image = load_default_cursor_image ();
+
+  meta_wayland_stage_set_default_cursor (self);
+}
+
+ClutterActor *
+meta_wayland_stage_new (void)
+{
+  return g_object_new (META_WAYLAND_TYPE_STAGE,
+                       "cursor-visible", FALSE,
+                       NULL);
+}
+
+void
+meta_wayland_stage_set_cursor_position (MetaWaylandStage *self,
+                                        int               x,
+                                        int               y)
+{
+  self->cursor_x = x;
+  self->cursor_y = y;
+  update_cursor_position (self);
+}
+
+void
+meta_wayland_stage_set_default_cursor (MetaWaylandStage *self)
+{
+  ClutterTexture *cursor_texture =
+    CLUTTER_TEXTURE (self->cursor_texture);
+
+  self->cursor_hotspot_x = META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_X;
+  self->cursor_hotspot_y = META_WAYLAND_DEFAULT_CURSOR_HOTSPOT_Y;
+
+  clutter_texture_set_cogl_texture (cursor_texture,
+                                    self->default_cursor_image);
+
+  update_cursor_position (self);
+}
diff --git a/src/wayland/meta-wayland-stage.h b/src/wayland/meta-wayland-stage.h
new file mode 100644
index 0000000..05412b9
--- /dev/null
+++ b/src/wayland/meta-wayland-stage.h
@@ -0,0 +1,85 @@
+/*
+ * 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_STAGE_H
+#define META_WAYLAND_STAGE_H
+
+#include <clutter/clutter.h>
+
+G_BEGIN_DECLS
+
+#define META_WAYLAND_TYPE_STAGE                                         \
+  (meta_wayland_stage_get_type())
+#define META_WAYLAND_STAGE(obj)                                         \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj),                                   \
+                               META_WAYLAND_TYPE_STAGE,                 \
+                               MetaWaylandStage))
+#define META_WAYLAND_STAGE_CLASS(klass)                                 \
+  (G_TYPE_CHECK_CLASS_CAST ((klass),                                    \
+                            META_WAYLAND_TYPE_STAGE,                    \
+                            MetaWaylandStageClass))
+#define META_WAYLAND_IS_STAGE(obj)                                      \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj),                                   \
+                               META_WAYLAND_TYPE_STAGE))
+#define META_WAYLAND_IS_STAGE_CLASS(klass)                              \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass),                                    \
+                            META_WAYLAND_TYPE_STAGE))
+#define META_WAYLAND_STAGE_GET_CLASS(obj)                               \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj),                                    \
+                              META_WAYLAND_STAGE,                       \
+                              MetaWaylandStageClass))
+
+typedef struct _MetaWaylandStage      MetaWaylandStage;
+typedef struct _MetaWaylandStageClass MetaWaylandStageClass;
+
+struct _MetaWaylandStageClass
+{
+  ClutterStageClass parent_class;
+};
+
+struct _MetaWaylandStage
+{
+  ClutterStage parent;
+
+  /* The cursor image that will be used when the cursor is not over a
+     surface */
+  CoglTexture *default_cursor_image;
+
+  int cursor_x;
+  int cursor_y;
+
+  ClutterActor *cursor_texture;
+  int cursor_hotspot_x;
+  int cursor_hotspot_y;
+};
+
+GType             meta_wayland_stage_get_type            (void) G_GNUC_CONST;
+
+ClutterActor     *meta_wayland_stage_new                 (void);
+
+void              meta_wayland_stage_set_cursor_position (MetaWaylandStage *stage,
+                                                          int               x,
+                                                          int               y);
+
+void              meta_wayland_stage_set_default_cursor (MetaWaylandStage  *self);
+
+
+G_END_DECLS
+
+#endif /* META_WAYLAND_STAGE_H */
diff --git a/src/wayland/meta-wayland.c b/src/wayland/meta-wayland.c
index 8490017..0cc1399 100644
--- a/src/wayland/meta-wayland.c
+++ b/src/wayland/meta-wayland.c
@@ -43,6 +43,7 @@
 #include "xserver-server-protocol.h"
 
 #include "meta-wayland-private.h"
+#include "meta-wayland-stage.h"
 #include "meta-window-actor-private.h"
 #include "display-private.h"
 #include "window-private.h"
@@ -1072,6 +1073,10 @@ event_cb (ClutterActor *stage,
 
   meta_wayland_input_device_handle_event (compositor->input_device, event);
 
+  meta_wayland_stage_set_cursor_position (META_WAYLAND_STAGE (stage),
+                                          device->x,
+                                          device->y);
+
   display = meta_get_display ();
   if (!display)
     return FALSE;
@@ -1202,7 +1207,7 @@ meta_wayland_init (void)
   if (clutter_init (NULL, NULL) != CLUTTER_INIT_SUCCESS)
     g_error ("Failed to initialize Clutter");
 
-  compositor->stage = clutter_stage_new ();
+  compositor->stage = meta_wayland_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);



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