[mutter] backends/cursor: Move out Xcursor functionality into own type



commit 3c538d4a92e67455d410308e110781dc0a9c28a6
Author: Jonas Ådahl <jadahl gmail com>
Date:   Fri Apr 27 15:43:37 2018 +0200

    backends/cursor: Move out Xcursor functionality into own type
    
    Introduce a new type MetaCursorSpriteXcursor that is a MetaCursorSprite
    implementation backed by Xcursor images. A plain MetaCursorSprite can
    still be created "bare bone", but must be manually provided with a
    texture. These usages will eventually be wrapped into new
    MetaCursorSprite types while turning MetaCursorSprite into an abstract
    type.
    
    https://gitlab.gnome.org/GNOME/mutter/issues/77

 src/Makefile.am                             |   2 +
 src/backends/meta-cursor-sprite-xcursor.c   | 304 ++++++++++++++++++++++++++++
 src/backends/meta-cursor-sprite-xcursor.h   |  40 ++++
 src/backends/meta-cursor.c                  | 248 ++---------------------
 src/backends/meta-cursor.h                  |  25 +--
 src/backends/x11/meta-cursor-renderer-x11.c |   8 +-
 src/core/screen.c                           |  33 +--
 src/wayland/meta-wayland-tablet-tool.c      |  15 +-
 src/wayland/meta-wayland-tablet-tool.h      |   3 +-
 9 files changed, 406 insertions(+), 272 deletions(-)
---
diff --git a/src/Makefile.am b/src/Makefile.am
index 84e2dc130..96dd01ebe 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -114,6 +114,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES =      \
        backends/meta-cursor-tracker-private.h  \
        backends/meta-cursor-renderer.c         \
        backends/meta-cursor-renderer.h         \
+       backends/meta-cursor-sprite-xcursor.c   \
+       backends/meta-cursor-sprite-xcursor.h   \
        backends/meta-dnd-private.h             \
        backends/meta-egl.c                     \
        backends/meta-egl.h                     \
diff --git a/src/backends/meta-cursor-sprite-xcursor.c b/src/backends/meta-cursor-sprite-xcursor.c
new file mode 100644
index 000000000..0b6e3f365
--- /dev/null
+++ b/src/backends/meta-cursor-sprite-xcursor.c
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2013, 2018 Red Hat, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "config.h"
+
+#include "backends/meta-cursor-sprite-xcursor.h"
+
+#include <X11/Xcursor/Xcursor.h>
+
+#include "backends/meta-backend-private.h"
+#include "backends/meta-cursor.h"
+#include "backends/meta-cursor-renderer.h"
+#include "clutter/clutter.h"
+#include "cogl/cogl.h"
+#include "meta/prefs.h"
+
+struct _MetaCursorSpriteXcursor
+{
+  MetaCursorSprite parent;
+
+  MetaCursor cursor;
+
+  int current_frame;
+  XcursorImages *xcursor_images;
+
+  int theme_scale;
+  gboolean theme_dirty;
+};
+
+G_DEFINE_TYPE (MetaCursorSpriteXcursor, meta_cursor_sprite_xcursor,
+               META_TYPE_CURSOR_SPRITE)
+
+static const char *
+translate_meta_cursor (MetaCursor cursor)
+{
+  switch (cursor)
+    {
+    case META_CURSOR_DEFAULT:
+      return "left_ptr";
+    case META_CURSOR_NORTH_RESIZE:
+      return "top_side";
+    case META_CURSOR_SOUTH_RESIZE:
+      return "bottom_side";
+    case META_CURSOR_WEST_RESIZE:
+      return "left_side";
+    case META_CURSOR_EAST_RESIZE:
+      return "right_side";
+    case META_CURSOR_SE_RESIZE:
+      return "bottom_right_corner";
+    case META_CURSOR_SW_RESIZE:
+      return "bottom_left_corner";
+    case META_CURSOR_NE_RESIZE:
+      return "top_right_corner";
+    case META_CURSOR_NW_RESIZE:
+      return "top_left_corner";
+    case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
+      return "fleur";
+    case META_CURSOR_BUSY:
+      return "watch";
+    case META_CURSOR_DND_IN_DRAG:
+      return "dnd-none";
+    case META_CURSOR_DND_MOVE:
+      return "dnd-move";
+    case META_CURSOR_DND_COPY:
+      return "dnd-copy";
+    case META_CURSOR_DND_UNSUPPORTED_TARGET:
+      return "dnd-none";
+    case META_CURSOR_POINTING_HAND:
+      return "hand2";
+    case META_CURSOR_CROSSHAIR:
+      return "crosshair";
+    case META_CURSOR_IBEAM:
+      return "xterm";
+    case META_CURSOR_NONE:
+    case META_CURSOR_LAST:
+      break;
+    }
+
+  g_assert_not_reached ();
+  return NULL;
+}
+
+MetaCursor
+meta_cursor_sprite_xcursor_get_cursor (MetaCursorSpriteXcursor *sprite_xcursor)
+{
+  return sprite_xcursor->cursor;
+}
+
+Cursor
+meta_create_x_cursor (Display    *xdisplay,
+                      MetaCursor  cursor)
+{
+  return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
+}
+
+static XcursorImages *
+load_cursor_on_client (MetaCursor cursor, int scale)
+{
+  return XcursorLibraryLoadImages (translate_meta_cursor (cursor),
+                                   meta_prefs_get_cursor_theme (),
+                                   meta_prefs_get_cursor_size () * scale);
+}
+
+static void
+load_from_xcursor_image (MetaCursorSprite *sprite,
+                         XcursorImage     *xc_image)
+{
+  MetaBackend *backend = meta_get_backend ();
+  MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
+  int width, height, rowstride;
+  CoglPixelFormat cogl_format;
+  ClutterBackend *clutter_backend;
+  CoglContext *cogl_context;
+  CoglTexture2D *texture;
+  CoglError *error = NULL;
+
+  g_assert (!meta_cursor_sprite_get_cogl_texture (sprite));
+
+  width = (int) xc_image->width;
+  height = (int) xc_image->height;
+  rowstride = width * 4;
+
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+  cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
+#else
+  cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
+#endif
+
+  clutter_backend = clutter_get_default_backend ();
+  cogl_context = clutter_backend_get_cogl_context (clutter_backend);
+  texture = cogl_texture_2d_new_from_data (cogl_context,
+                                           width, height,
+                                           cogl_format,
+                                           rowstride,
+                                           (uint8_t *) xc_image->pixels,
+                                           &error);
+
+  if (error)
+    {
+      meta_warning ("Failed to allocate cursor texture: %s\n", error->message);
+      cogl_error_free (error);
+    }
+
+  meta_cursor_sprite_set_texture (sprite, COGL_TEXTURE (texture),
+                                  xc_image->xhot, xc_image->yhot);
+
+  g_clear_pointer (&texture, cogl_object_unref);
+
+  meta_cursor_renderer_realize_cursor_from_xcursor (renderer, sprite, xc_image);
+}
+
+void
+meta_cursor_sprite_xcursor_set_theme_scale (MetaCursorSpriteXcursor *sprite_xcursor,
+                                            int                      theme_scale)
+{
+  if (sprite_xcursor->theme_scale != theme_scale)
+    sprite_xcursor->theme_dirty = TRUE;
+  sprite_xcursor->theme_scale = theme_scale;
+}
+
+static gboolean
+meta_cursor_sprite_xcursor_is_animated (MetaCursorSprite *sprite)
+{
+  MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite);
+
+  return (sprite_xcursor->xcursor_images &&
+          sprite_xcursor->xcursor_images->nimage > 1);
+}
+
+static XcursorImage *
+get_current_frame_image (MetaCursorSprite *sprite)
+{
+  MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite);
+
+  return sprite_xcursor->xcursor_images->images[sprite_xcursor->current_frame];
+}
+
+static void
+meta_cursor_sprite_xcursor_tick_frame (MetaCursorSprite *sprite)
+{
+  MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite);
+  XcursorImage *image;
+
+  if (!meta_cursor_sprite_is_animated (sprite))
+    return;
+
+  sprite_xcursor->current_frame++;
+
+  if (sprite_xcursor->current_frame >= sprite_xcursor->xcursor_images->nimage)
+    sprite_xcursor->current_frame = 0;
+
+  image = get_current_frame_image (sprite);
+
+  meta_cursor_sprite_clear_texture (sprite);
+  load_from_xcursor_image (sprite, image);
+}
+
+static unsigned int
+meta_cursor_sprite_xcursor_get_current_frame_time (MetaCursorSprite *sprite)
+{
+  MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite);
+  XcursorImages *xcursor_images;
+
+  g_return_val_if_fail (meta_cursor_sprite_is_animated (sprite), 0);
+
+  xcursor_images = sprite_xcursor->xcursor_images;
+  return xcursor_images->images[sprite_xcursor->current_frame]->delay;
+}
+
+static void
+load_cursor_from_theme (MetaCursorSprite *sprite)
+{
+  MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite);
+  XcursorImage *image;
+
+  g_assert (sprite_xcursor->cursor != META_CURSOR_NONE);
+
+  sprite_xcursor->theme_dirty = FALSE;
+
+  /* We might be reloading with a different scale. If so clear the old data. */
+  if (sprite_xcursor->xcursor_images)
+    {
+      meta_cursor_sprite_clear_texture (sprite);
+      XcursorImagesDestroy (sprite_xcursor->xcursor_images);
+    }
+
+  sprite_xcursor->current_frame = 0;
+  sprite_xcursor->xcursor_images =
+    load_cursor_on_client (sprite_xcursor->cursor,
+                           sprite_xcursor->theme_scale);
+  if (!sprite_xcursor->xcursor_images)
+    g_error ("Could not find cursor. Perhaps set XCURSOR_PATH?");
+
+  image = get_current_frame_image (sprite);
+  load_from_xcursor_image (sprite, image);
+}
+
+static void
+meta_cursor_sprite_xcursor_realize_texture (MetaCursorSprite *sprite)
+{
+  MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite);
+
+  if (sprite_xcursor->theme_dirty)
+    load_cursor_from_theme (sprite);
+}
+
+MetaCursorSpriteXcursor *
+meta_cursor_sprite_xcursor_new (MetaCursor cursor)
+{
+  MetaCursorSpriteXcursor *sprite_xcursor;
+
+  sprite_xcursor = g_object_new (META_TYPE_CURSOR_SPRITE_XCURSOR, NULL);
+  sprite_xcursor->cursor = cursor;
+
+  return sprite_xcursor;
+}
+
+static void
+meta_cursor_sprite_xcursor_finalize (GObject *object)
+{
+  MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (object);
+
+  g_clear_pointer (&sprite_xcursor->xcursor_images,
+                   XcursorImagesDestroy);
+
+  G_OBJECT_CLASS (meta_cursor_sprite_xcursor_parent_class)->finalize (object);
+}
+
+static void
+meta_cursor_sprite_xcursor_init (MetaCursorSpriteXcursor *sprite_xcursor)
+{
+  sprite_xcursor->theme_dirty = TRUE;
+}
+
+static void
+meta_cursor_sprite_xcursor_class_init (MetaCursorSpriteXcursorClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  MetaCursorSpriteClass *cursor_sprite_class = META_CURSOR_SPRITE_CLASS (klass);
+
+  object_class->finalize = meta_cursor_sprite_xcursor_finalize;
+
+  cursor_sprite_class->realize_texture =
+    meta_cursor_sprite_xcursor_realize_texture;
+  cursor_sprite_class->is_animated = meta_cursor_sprite_xcursor_is_animated;
+  cursor_sprite_class->tick_frame = meta_cursor_sprite_xcursor_tick_frame;
+  cursor_sprite_class->get_current_frame_time =
+    meta_cursor_sprite_xcursor_get_current_frame_time;
+}
diff --git a/src/backends/meta-cursor-sprite-xcursor.h b/src/backends/meta-cursor-sprite-xcursor.h
new file mode 100644
index 000000000..bc5a8c2e8
--- /dev/null
+++ b/src/backends/meta-cursor-sprite-xcursor.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2013, 2018 Red Hat, Inc.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef META_CURSOR_SPRITE_XCURSOR_H
+#define META_CURSOR_SPRITE_XCURSOR_H
+
+#include <glib-object.h>
+
+#include "backends/meta-cursor.h"
+
+#define META_TYPE_CURSOR_SPRITE_XCURSOR meta_cursor_sprite_xcursor_get_type ()
+G_DECLARE_FINAL_TYPE (MetaCursorSpriteXcursor, meta_cursor_sprite_xcursor,
+                      META, CURSOR_SPRITE_XCURSOR, MetaCursorSprite)
+
+MetaCursorSpriteXcursor * meta_cursor_sprite_xcursor_new (MetaCursor cursor);
+
+void meta_cursor_sprite_xcursor_set_theme_scale (MetaCursorSpriteXcursor *sprite_xcursor,
+                                                 int                      scale);
+
+MetaCursor meta_cursor_sprite_xcursor_get_cursor (MetaCursorSpriteXcursor *sprite_xcusror);
+
+Cursor meta_create_x_cursor (Display    *xdisplay,
+                             MetaCursor  cursor);
+
+#endif /* META_CURSOR_SPRITE_XCURSOR_H */
diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c
index ce0f20467..57f65236b 100644
--- a/src/backends/meta-cursor.c
+++ b/src/backends/meta-cursor.c
@@ -23,15 +23,9 @@
 
 #include "meta-cursor.h"
 
-#include <string.h>
-#include <X11/Xcursor/Xcursor.h>
-
 #include "backends/meta-backend-private.h"
-#include "backends/meta-cursor-renderer.h"
-#include "clutter/clutter.h"
 #include "cogl/cogl.h"
 #include "meta/common.h"
-#include "meta/prefs.h"
 
 enum
 {
@@ -47,185 +41,34 @@ typedef struct _MetaCursorSpritePrivate
 {
   GObject parent;
 
-  MetaCursor cursor;
-
   CoglTexture2D *texture;
   float texture_scale;
   int hot_x, hot_y;
-
-  int current_frame;
-  XcursorImages *xcursor_images;
-
-  int theme_scale;
-  gboolean theme_dirty;
 } MetaCursorSpritePrivate;
 
 G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT)
 
-static const char *
-translate_meta_cursor (MetaCursor cursor)
-{
-  switch (cursor)
-    {
-    case META_CURSOR_DEFAULT:
-      return "left_ptr";
-    case META_CURSOR_NORTH_RESIZE:
-      return "top_side";
-    case META_CURSOR_SOUTH_RESIZE:
-      return "bottom_side";
-    case META_CURSOR_WEST_RESIZE:
-      return "left_side";
-    case META_CURSOR_EAST_RESIZE:
-      return "right_side";
-    case META_CURSOR_SE_RESIZE:
-      return "bottom_right_corner";
-    case META_CURSOR_SW_RESIZE:
-      return "bottom_left_corner";
-    case META_CURSOR_NE_RESIZE:
-      return "top_right_corner";
-    case META_CURSOR_NW_RESIZE:
-      return "top_left_corner";
-    case META_CURSOR_MOVE_OR_RESIZE_WINDOW:
-      return "fleur";
-    case META_CURSOR_BUSY:
-      return "watch";
-    case META_CURSOR_DND_IN_DRAG:
-      return "dnd-none";
-    case META_CURSOR_DND_MOVE:
-      return "dnd-move";
-    case META_CURSOR_DND_COPY:
-      return "dnd-copy";
-    case META_CURSOR_DND_UNSUPPORTED_TARGET:
-      return "dnd-none";
-    case META_CURSOR_POINTING_HAND:
-      return "hand2";
-    case META_CURSOR_CROSSHAIR:
-      return "crosshair";
-    case META_CURSOR_IBEAM:
-      return "xterm";
-    default:
-      break;
-    }
-
-  g_assert_not_reached ();
-}
-
-Cursor
-meta_create_x_cursor (Display    *xdisplay,
-                      MetaCursor  cursor)
-{
-  return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor));
-}
-
-static XcursorImages *
-load_cursor_on_client (MetaCursor cursor, int scale)
-{
-  return XcursorLibraryLoadImages (translate_meta_cursor (cursor),
-                                   meta_prefs_get_cursor_theme (),
-                                   meta_prefs_get_cursor_size () * scale);
-}
-
-static void
-meta_cursor_sprite_load_from_xcursor_image (MetaCursorSprite *sprite,
-                                            XcursorImage     *xc_image)
-{
-  MetaCursorSpritePrivate *priv =
-    meta_cursor_sprite_get_instance_private (sprite);
-  MetaBackend *backend = meta_get_backend ();
-  MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (backend);
-  uint width, height, rowstride;
-  CoglPixelFormat cogl_format;
-  ClutterBackend *clutter_backend;
-  CoglContext *cogl_context;
-  CoglTexture2D *texture;
-  CoglError *error = NULL;
-
-  g_assert (priv->texture == NULL);
-
-  width           = xc_image->width;
-  height          = xc_image->height;
-  rowstride       = width * 4;
-
-#if G_BYTE_ORDER == G_LITTLE_ENDIAN
-  cogl_format = COGL_PIXEL_FORMAT_BGRA_8888;
-#else
-  cogl_format = COGL_PIXEL_FORMAT_ARGB_8888;
-#endif
-
-  clutter_backend = clutter_get_default_backend ();
-  cogl_context = clutter_backend_get_cogl_context (clutter_backend);
-  texture = cogl_texture_2d_new_from_data (cogl_context,
-                                           width, height,
-                                           cogl_format,
-                                           rowstride,
-                                           (uint8_t *) xc_image->pixels,
-                                           &error);
-
-  if (error)
-    {
-      meta_warning ("Failed to allocate cursor texture: %s\n", error->message);
-      cogl_error_free (error);
-    }
-
-  meta_cursor_sprite_set_texture (sprite, COGL_TEXTURE (texture),
-                                  xc_image->xhot, xc_image->yhot);
-
-  if (texture)
-    cogl_object_unref (texture);
-
-  meta_cursor_renderer_realize_cursor_from_xcursor (renderer, sprite, xc_image);
-}
-
-static XcursorImage *
-meta_cursor_sprite_get_current_frame_image (MetaCursorSprite *sprite)
+gboolean
+meta_cursor_sprite_is_animated (MetaCursorSprite *sprite)
 {
-  MetaCursorSpritePrivate *priv =
-    meta_cursor_sprite_get_instance_private (sprite);
+  MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite);
 
-  return priv->xcursor_images->images[priv->current_frame];
+  if (klass->is_animated)
+    return klass->is_animated (sprite);
+  else
+    return FALSE;
 }
 
 void
 meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite)
 {
-  MetaCursorSpritePrivate *priv =
-    meta_cursor_sprite_get_instance_private (sprite);
-  XcursorImage *image;
-
-  if (!meta_cursor_sprite_is_animated (sprite))
-    return;
-
-  priv->current_frame++;
-
-  if (priv->current_frame >= priv->xcursor_images->nimage)
-    priv->current_frame = 0;
-
-  image = meta_cursor_sprite_get_current_frame_image (sprite);
-
-  g_clear_pointer (&priv->texture, cogl_object_unref);
-  meta_cursor_sprite_load_from_xcursor_image (sprite, image);
+  return META_CURSOR_SPRITE_GET_CLASS (sprite)->tick_frame (sprite);
 }
 
-guint
+unsigned int
 meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite)
 {
-  MetaCursorSpritePrivate *priv =
-    meta_cursor_sprite_get_instance_private (sprite);
-
-  if (!meta_cursor_sprite_is_animated (sprite))
-    return 0;
-
-  return priv->xcursor_images->images[priv->current_frame]->delay;
-}
-
-gboolean
-meta_cursor_sprite_is_animated (MetaCursorSprite *sprite)
-{
-  MetaCursorSpritePrivate *priv =
-    meta_cursor_sprite_get_instance_private (sprite);
-
-  return (priv->xcursor_images &&
-          priv->xcursor_images->nimage > 1);
+  return META_CURSOR_SPRITE_GET_CLASS (sprite)->get_current_frame_time (sprite);
 }
 
 MetaCursorSprite *
@@ -234,47 +77,13 @@ meta_cursor_sprite_new (void)
   return g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
 }
 
-static void
-meta_cursor_sprite_load_from_theme (MetaCursorSprite *sprite)
+void
+meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite)
 {
   MetaCursorSpritePrivate *priv =
     meta_cursor_sprite_get_instance_private (sprite);
-  XcursorImage *image;
-
-  g_assert (priv->cursor != META_CURSOR_NONE);
-
-  priv->theme_dirty = FALSE;
-
-  /* We might be reloading with a different scale. If so clear the old data. */
-  if (priv->xcursor_images)
-    {
-      g_clear_pointer (&priv->texture, cogl_object_unref);
-      XcursorImagesDestroy (priv->xcursor_images);
-    }
-
-  priv->current_frame = 0;
-  priv->xcursor_images = load_cursor_on_client (priv->cursor,
-                                                priv->theme_scale);
-  if (!priv->xcursor_images)
-    meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?");
-
-  image = meta_cursor_sprite_get_current_frame_image (sprite);
-  meta_cursor_sprite_load_from_xcursor_image (sprite, image);
-}
-
-MetaCursorSprite *
-meta_cursor_sprite_from_theme (MetaCursor cursor)
-{
-  MetaCursorSprite *sprite;
-  MetaCursorSpritePrivate *priv;
 
-  sprite = meta_cursor_sprite_new ();
-  priv = meta_cursor_sprite_get_instance_private (sprite);
-
-  priv->cursor = cursor;
-  priv->theme_dirty = TRUE;
-
-  return sprite;
+  g_clear_pointer (&priv->texture, cogl_object_unref);
 }
 
 void
@@ -310,18 +119,6 @@ meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite,
   priv->texture_scale = scale;
 }
 
-void
-meta_cursor_sprite_set_theme_scale (MetaCursorSprite *sprite,
-                                    int               theme_scale)
-{
-  MetaCursorSpritePrivate *priv =
-    meta_cursor_sprite_get_instance_private (sprite);
-
-  if (priv->theme_scale != theme_scale)
-    priv->theme_dirty = TRUE;
-  priv->theme_scale = theme_scale;
-}
-
 CoglTexture *
 meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite)
 {
@@ -331,15 +128,6 @@ meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite)
   return COGL_TEXTURE (priv->texture);
 }
 
-MetaCursor
-meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *sprite)
-{
-  MetaCursorSpritePrivate *priv =
-    meta_cursor_sprite_get_instance_private (sprite);
-
-  return priv->cursor;
-}
-
 void
 meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite,
                                 int              *hot_x,
@@ -372,11 +160,10 @@ meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
 void
 meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite)
 {
-  MetaCursorSpritePrivate *priv =
-    meta_cursor_sprite_get_instance_private (sprite);
+  MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite);
 
-  if (priv->theme_dirty)
-    meta_cursor_sprite_load_from_theme (sprite);
+  if (klass->realize_texture)
+    klass->realize_texture (sprite);
 }
 
 static void
@@ -395,9 +182,6 @@ meta_cursor_sprite_finalize (GObject *object)
   MetaCursorSpritePrivate *priv =
     meta_cursor_sprite_get_instance_private (sprite);
 
-  if (priv->xcursor_images)
-    XcursorImagesDestroy (priv->xcursor_images);
-
   g_clear_pointer (&priv->texture, cogl_object_unref);
 
   G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object);
diff --git a/src/backends/meta-cursor.h b/src/backends/meta-cursor.h
index cd2ac1801..e9ba5c46a 100644
--- a/src/backends/meta-cursor.h
+++ b/src/backends/meta-cursor.h
@@ -25,29 +25,23 @@
 #include <meta/common.h>
 #include <meta/boxes.h>
 
-struct _MetaCursorSpriteClass
-{
-  GObjectClass parent_class;
-};
-
 #define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ())
 G_DECLARE_DERIVABLE_TYPE (MetaCursorSprite,
                           meta_cursor_sprite,
                           META, CURSOR_SPRITE,
                           GObject)
 
-MetaCursorSprite * meta_cursor_sprite_new (void);
-
-MetaCursorSprite * meta_cursor_sprite_from_theme  (MetaCursor cursor);
-
-
-void meta_cursor_sprite_set_theme_scale (MetaCursorSprite *sprite,
-                                         int               scale);
+struct _MetaCursorSpriteClass
+{
+  GObjectClass parent_class;
 
-MetaCursor meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *sprite);
+  void (* realize_texture) (MetaCursorSprite *sprite);
+  gboolean (* is_animated) (MetaCursorSprite *sprite);
+  void (* tick_frame) (MetaCursorSprite *sprite);
+  unsigned int (* get_current_frame_time) (MetaCursorSprite *sprite);
+};
 
-Cursor meta_create_x_cursor (Display    *xdisplay,
-                             MetaCursor  cursor);
+MetaCursorSprite * meta_cursor_sprite_new (void);
 
 void meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
                                     int               x,
@@ -55,6 +49,7 @@ void meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
 
 void meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite);
 
+void meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite);
 
 void meta_cursor_sprite_set_texture (MetaCursorSprite *sprite,
                                      CoglTexture      *texture,
diff --git a/src/backends/x11/meta-cursor-renderer-x11.c b/src/backends/x11/meta-cursor-renderer-x11.c
index 2b105cffb..bb3100a91 100644
--- a/src/backends/x11/meta-cursor-renderer-x11.c
+++ b/src/backends/x11/meta-cursor-renderer-x11.c
@@ -30,6 +30,7 @@
 
 #include "meta-backend-x11.h"
 #include "meta-stage-private.h"
+#include "backends/meta-cursor-sprite-xcursor.h"
 
 struct _MetaCursorRendererX11Private
 {
@@ -59,10 +60,13 @@ meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer,
 
   gboolean has_server_cursor = FALSE;
 
-  if (cursor_sprite)
+  if (cursor_sprite && META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite))
     {
-      MetaCursor cursor = meta_cursor_sprite_get_meta_cursor (cursor_sprite);
+      MetaCursorSpriteXcursor *sprite_xcursor =
+        META_CURSOR_SPRITE_XCURSOR (cursor_sprite);
+      MetaCursor cursor;
 
+      cursor = meta_cursor_sprite_xcursor_get_cursor (sprite_xcursor);
       if (cursor != META_CURSOR_NONE)
         {
           Cursor xcursor;
diff --git a/src/core/screen.c b/src/core/screen.c
index c14bba0cf..048104150 100644
--- a/src/core/screen.c
+++ b/src/core/screen.c
@@ -60,6 +60,7 @@
 #include "x11/xprops.h"
 
 #include "backends/x11/meta-backend-x11.h"
+#include "backends/meta-cursor-sprite-xcursor.h"
 
 static char* get_screen_name (MetaDisplay *display,
                               int          number);
@@ -1323,12 +1324,13 @@ find_highest_logical_monitor_scale (MetaBackend      *backend,
 }
 
 static void
-root_cursor_prepare_at (MetaCursorSprite *cursor_sprite,
-                        int               x,
-                        int               y,
-                        MetaScreen       *screen)
+root_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
+                        int                      x,
+                        int                      y,
+                        MetaScreen              *screen)
 {
   MetaBackend *backend = meta_get_backend ();
+  MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
 
   if (meta_is_stage_views_scaled ())
     {
@@ -1337,7 +1339,7 @@ root_cursor_prepare_at (MetaCursorSprite *cursor_sprite,
       scale = find_highest_logical_monitor_scale (backend, cursor_sprite);
       if (scale != 0.0)
         {
-          meta_cursor_sprite_set_theme_scale (cursor_sprite, scale);
+          meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor, scale);
           meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0 / scale);
         }
     }
@@ -1353,18 +1355,18 @@ root_cursor_prepare_at (MetaCursorSprite *cursor_sprite,
       /* Reload the cursor texture if the scale has changed. */
       if (logical_monitor)
         {
-          meta_cursor_sprite_set_theme_scale (cursor_sprite,
-                                              logical_monitor->scale);
+          meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor,
+                                                      logical_monitor->scale);
           meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0);
         }
     }
 }
 
 static void
-manage_root_cursor_sprite_scale (MetaScreen       *screen,
-                                 MetaCursorSprite *cursor_sprite)
+manage_root_cursor_sprite_scale (MetaScreen              *screen,
+                                 MetaCursorSpriteXcursor *sprite_xcursor)
 {
-  g_signal_connect_object (cursor_sprite,
+  g_signal_connect_object (sprite_xcursor,
                            "prepare-at",
                            G_CALLBACK (root_cursor_prepare_at),
                            screen,
@@ -1377,17 +1379,18 @@ meta_screen_update_cursor (MetaScreen *screen)
   MetaDisplay *display = screen->display;
   MetaCursor cursor = screen->current_cursor;
   Cursor xcursor;
-  MetaCursorSprite *cursor_sprite;
+  MetaCursorSpriteXcursor *sprite_xcursor;
   MetaBackend *backend = meta_get_backend ();
   MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
 
-  cursor_sprite = meta_cursor_sprite_from_theme (cursor);
+  sprite_xcursor = meta_cursor_sprite_xcursor_new (cursor);
 
   if (meta_is_wayland_compositor ())
-    manage_root_cursor_sprite_scale (screen, cursor_sprite);
+    manage_root_cursor_sprite_scale (screen, sprite_xcursor);
 
-  meta_cursor_tracker_set_root_cursor (cursor_tracker, cursor_sprite);
-  g_object_unref (cursor_sprite);
+  meta_cursor_tracker_set_root_cursor (cursor_tracker,
+                                       META_CURSOR_SPRITE (sprite_xcursor));
+  g_object_unref (sprite_xcursor);
 
   /* Set a cursor for X11 applications that don't specify their own */
   xcursor = meta_display_create_x_cursor (display, cursor);
diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c
index c1858d9c7..2d2cb2051 100644
--- a/src/wayland/meta-wayland-tablet-tool.c
+++ b/src/wayland/meta-wayland-tablet-tool.c
@@ -99,7 +99,7 @@ meta_wayland_tablet_tool_update_cursor_surface (MetaWaylandTabletTool *tool)
         cursor = NULL;
     }
   else if (tool->current_tablet)
-    cursor = tool->default_sprite;
+    cursor = META_CURSOR_SPRITE (tool->default_sprite);
   else
     cursor = NULL;
 
@@ -382,10 +382,10 @@ tablet_tool_handle_cursor_surface_destroy (struct wl_listener *listener,
 }
 
 static void
-tool_cursor_prepare_at (MetaCursorSprite      *cursor_sprite,
-                        int                    x,
-                        int                    y,
-                        MetaWaylandTabletTool *tool)
+tool_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
+                        int                      x,
+                        int                      y,
+                        MetaWaylandTabletTool   *tool)
 {
   MetaBackend *backend = meta_get_backend ();
   MetaMonitorManager *monitor_manager =
@@ -397,7 +397,8 @@ tool_cursor_prepare_at (MetaCursorSprite      *cursor_sprite,
 
   /* Reload the cursor texture if the scale has changed. */
   if (logical_monitor)
-    meta_cursor_sprite_set_theme_scale (cursor_sprite, logical_monitor->scale);
+    meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor,
+                                                logical_monitor->scale);
 }
 
 MetaWaylandTabletTool *
@@ -417,7 +418,7 @@ meta_wayland_tablet_tool_new (MetaWaylandTabletSeat  *seat,
   tool->focus_surface_destroy_listener.notify = tablet_tool_handle_focus_surface_destroy;
   tool->cursor_surface_destroy_listener.notify = tablet_tool_handle_cursor_surface_destroy;
 
-  tool->default_sprite = meta_cursor_sprite_from_theme (META_CURSOR_CROSSHAIR);
+  tool->default_sprite = meta_cursor_sprite_xcursor_new (META_CURSOR_CROSSHAIR);
   tool->prepare_at_signal_id =
     g_signal_connect (tool->default_sprite, "prepare-at",
                       G_CALLBACK (tool_cursor_prepare_at), tool);
diff --git a/src/wayland/meta-wayland-tablet-tool.h b/src/wayland/meta-wayland-tablet-tool.h
index 8cd930086..011972fc2 100644
--- a/src/wayland/meta-wayland-tablet-tool.h
+++ b/src/wayland/meta-wayland-tablet-tool.h
@@ -28,6 +28,7 @@
 
 #include "meta-wayland-types.h"
 #include "meta-cursor-renderer.h"
+#include "backends/meta-cursor-sprite-xcursor.h"
 
 struct _MetaWaylandTabletTool
 {
@@ -43,7 +44,7 @@ struct _MetaWaylandTabletTool
   MetaWaylandSurface *cursor_surface;
   struct wl_listener cursor_surface_destroy_listener;
   MetaCursorRenderer *cursor_renderer;
-  MetaCursorSprite *default_sprite;
+  MetaCursorSpriteXcursor *default_sprite;
   guint prepare_at_signal_id;
 
   MetaWaylandSurface *current;


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