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
This commit is contained in:
Jonas Ådahl 2018-04-27 15:43:37 +02:00
parent 2fc978ca9d
commit 3c538d4a92
9 changed files with 407 additions and 273 deletions

View File

@ -114,6 +114,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \
backends/meta-cursor-tracker-private.h \ backends/meta-cursor-tracker-private.h \
backends/meta-cursor-renderer.c \ backends/meta-cursor-renderer.c \
backends/meta-cursor-renderer.h \ backends/meta-cursor-renderer.h \
backends/meta-cursor-sprite-xcursor.c \
backends/meta-cursor-sprite-xcursor.h \
backends/meta-dnd-private.h \ backends/meta-dnd-private.h \
backends/meta-egl.c \ backends/meta-egl.c \
backends/meta-egl.h \ backends/meta-egl.h \

View File

@ -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;
}

View File

@ -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 */

View File

@ -23,15 +23,9 @@
#include "meta-cursor.h" #include "meta-cursor.h"
#include <string.h>
#include <X11/Xcursor/Xcursor.h>
#include "backends/meta-backend-private.h" #include "backends/meta-backend-private.h"
#include "backends/meta-cursor-renderer.h"
#include "clutter/clutter.h"
#include "cogl/cogl.h" #include "cogl/cogl.h"
#include "meta/common.h" #include "meta/common.h"
#include "meta/prefs.h"
enum enum
{ {
@ -47,185 +41,34 @@ typedef struct _MetaCursorSpritePrivate
{ {
GObject parent; GObject parent;
MetaCursor cursor;
CoglTexture2D *texture; CoglTexture2D *texture;
float texture_scale; float texture_scale;
int hot_x, hot_y; int hot_x, hot_y;
int current_frame;
XcursorImages *xcursor_images;
int theme_scale;
gboolean theme_dirty;
} MetaCursorSpritePrivate; } MetaCursorSpritePrivate;
G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT) G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT)
static const char * gboolean
translate_meta_cursor (MetaCursor cursor) meta_cursor_sprite_is_animated (MetaCursorSprite *sprite)
{ {
switch (cursor) MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite);
{
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 (); if (klass->is_animated)
} return klass->is_animated (sprite);
else
Cursor return FALSE;
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)
{
MetaCursorSpritePrivate *priv =
meta_cursor_sprite_get_instance_private (sprite);
return priv->xcursor_images->images[priv->current_frame];
} }
void void
meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite) meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite)
{ {
MetaCursorSpritePrivate *priv = return META_CURSOR_SPRITE_GET_CLASS (sprite)->tick_frame (sprite);
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);
} }
guint unsigned int
meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite) meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite)
{ {
MetaCursorSpritePrivate *priv = return META_CURSOR_SPRITE_GET_CLASS (sprite)->get_current_frame_time (sprite);
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);
} }
MetaCursorSprite * MetaCursorSprite *
@ -234,47 +77,13 @@ meta_cursor_sprite_new (void)
return g_object_new (META_TYPE_CURSOR_SPRITE, NULL); return g_object_new (META_TYPE_CURSOR_SPRITE, NULL);
} }
static void void
meta_cursor_sprite_load_from_theme (MetaCursorSprite *sprite) meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite)
{ {
MetaCursorSpritePrivate *priv = MetaCursorSpritePrivate *priv =
meta_cursor_sprite_get_instance_private (sprite); meta_cursor_sprite_get_instance_private (sprite);
XcursorImage *image;
g_assert (priv->cursor != META_CURSOR_NONE); g_clear_pointer (&priv->texture, cogl_object_unref);
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;
} }
void void
@ -310,18 +119,6 @@ meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite,
priv->texture_scale = scale; 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 * CoglTexture *
meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite) 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); 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 void
meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite, meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite,
int *hot_x, int *hot_x,
@ -372,11 +160,10 @@ meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
void void
meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite) meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite)
{ {
MetaCursorSpritePrivate *priv = MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite);
meta_cursor_sprite_get_instance_private (sprite);
if (priv->theme_dirty) if (klass->realize_texture)
meta_cursor_sprite_load_from_theme (sprite); klass->realize_texture (sprite);
} }
static void static void
@ -395,9 +182,6 @@ meta_cursor_sprite_finalize (GObject *object)
MetaCursorSpritePrivate *priv = MetaCursorSpritePrivate *priv =
meta_cursor_sprite_get_instance_private (sprite); meta_cursor_sprite_get_instance_private (sprite);
if (priv->xcursor_images)
XcursorImagesDestroy (priv->xcursor_images);
g_clear_pointer (&priv->texture, cogl_object_unref); g_clear_pointer (&priv->texture, cogl_object_unref);
G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object); G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object);

View File

@ -25,36 +25,31 @@
#include <meta/common.h> #include <meta/common.h>
#include <meta/boxes.h> #include <meta/boxes.h>
struct _MetaCursorSpriteClass
{
GObjectClass parent_class;
};
#define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ()) #define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ())
G_DECLARE_DERIVABLE_TYPE (MetaCursorSprite, G_DECLARE_DERIVABLE_TYPE (MetaCursorSprite,
meta_cursor_sprite, meta_cursor_sprite,
META, CURSOR_SPRITE, META, CURSOR_SPRITE,
GObject) GObject)
struct _MetaCursorSpriteClass
{
GObjectClass parent_class;
void (* realize_texture) (MetaCursorSprite *sprite);
gboolean (* is_animated) (MetaCursorSprite *sprite);
void (* tick_frame) (MetaCursorSprite *sprite);
unsigned int (* get_current_frame_time) (MetaCursorSprite *sprite);
};
MetaCursorSprite * meta_cursor_sprite_new (void); 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);
MetaCursor meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *sprite);
Cursor meta_create_x_cursor (Display *xdisplay,
MetaCursor cursor);
void meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite, void meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite,
int x, int x,
int y); int y);
void meta_cursor_sprite_realize_texture (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, void meta_cursor_sprite_set_texture (MetaCursorSprite *sprite,
CoglTexture *texture, CoglTexture *texture,

View File

@ -30,6 +30,7 @@
#include "meta-backend-x11.h" #include "meta-backend-x11.h"
#include "meta-stage-private.h" #include "meta-stage-private.h"
#include "backends/meta-cursor-sprite-xcursor.h"
struct _MetaCursorRendererX11Private struct _MetaCursorRendererX11Private
{ {
@ -59,10 +60,13 @@ meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer,
gboolean has_server_cursor = FALSE; 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) if (cursor != META_CURSOR_NONE)
{ {
Cursor xcursor; Cursor xcursor;

View File

@ -60,6 +60,7 @@
#include "x11/xprops.h" #include "x11/xprops.h"
#include "backends/x11/meta-backend-x11.h" #include "backends/x11/meta-backend-x11.h"
#include "backends/meta-cursor-sprite-xcursor.h"
static char* get_screen_name (MetaDisplay *display, static char* get_screen_name (MetaDisplay *display,
int number); int number);
@ -1323,12 +1324,13 @@ find_highest_logical_monitor_scale (MetaBackend *backend,
} }
static void static void
root_cursor_prepare_at (MetaCursorSprite *cursor_sprite, root_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
int x, int x,
int y, int y,
MetaScreen *screen) MetaScreen *screen)
{ {
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor);
if (meta_is_stage_views_scaled ()) 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); scale = find_highest_logical_monitor_scale (backend, cursor_sprite);
if (scale != 0.0) 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); 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. */ /* Reload the cursor texture if the scale has changed. */
if (logical_monitor) if (logical_monitor)
{ {
meta_cursor_sprite_set_theme_scale (cursor_sprite, meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor,
logical_monitor->scale); logical_monitor->scale);
meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0); meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0);
} }
} }
} }
static void static void
manage_root_cursor_sprite_scale (MetaScreen *screen, manage_root_cursor_sprite_scale (MetaScreen *screen,
MetaCursorSprite *cursor_sprite) MetaCursorSpriteXcursor *sprite_xcursor)
{ {
g_signal_connect_object (cursor_sprite, g_signal_connect_object (sprite_xcursor,
"prepare-at", "prepare-at",
G_CALLBACK (root_cursor_prepare_at), G_CALLBACK (root_cursor_prepare_at),
screen, screen,
@ -1377,17 +1379,18 @@ meta_screen_update_cursor (MetaScreen *screen)
MetaDisplay *display = screen->display; MetaDisplay *display = screen->display;
MetaCursor cursor = screen->current_cursor; MetaCursor cursor = screen->current_cursor;
Cursor xcursor; Cursor xcursor;
MetaCursorSprite *cursor_sprite; MetaCursorSpriteXcursor *sprite_xcursor;
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (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 ()) 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); meta_cursor_tracker_set_root_cursor (cursor_tracker,
g_object_unref (cursor_sprite); META_CURSOR_SPRITE (sprite_xcursor));
g_object_unref (sprite_xcursor);
/* Set a cursor for X11 applications that don't specify their own */ /* Set a cursor for X11 applications that don't specify their own */
xcursor = meta_display_create_x_cursor (display, cursor); xcursor = meta_display_create_x_cursor (display, cursor);

View File

@ -99,7 +99,7 @@ meta_wayland_tablet_tool_update_cursor_surface (MetaWaylandTabletTool *tool)
cursor = NULL; cursor = NULL;
} }
else if (tool->current_tablet) else if (tool->current_tablet)
cursor = tool->default_sprite; cursor = META_CURSOR_SPRITE (tool->default_sprite);
else else
cursor = NULL; cursor = NULL;
@ -382,10 +382,10 @@ tablet_tool_handle_cursor_surface_destroy (struct wl_listener *listener,
} }
static void static void
tool_cursor_prepare_at (MetaCursorSprite *cursor_sprite, tool_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor,
int x, int x,
int y, int y,
MetaWaylandTabletTool *tool) MetaWaylandTabletTool *tool)
{ {
MetaBackend *backend = meta_get_backend (); MetaBackend *backend = meta_get_backend ();
MetaMonitorManager *monitor_manager = MetaMonitorManager *monitor_manager =
@ -397,7 +397,8 @@ tool_cursor_prepare_at (MetaCursorSprite *cursor_sprite,
/* Reload the cursor texture if the scale has changed. */ /* Reload the cursor texture if the scale has changed. */
if (logical_monitor) 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 * 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->focus_surface_destroy_listener.notify = tablet_tool_handle_focus_surface_destroy;
tool->cursor_surface_destroy_listener.notify = tablet_tool_handle_cursor_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 = tool->prepare_at_signal_id =
g_signal_connect (tool->default_sprite, "prepare-at", g_signal_connect (tool->default_sprite, "prepare-at",
G_CALLBACK (tool_cursor_prepare_at), tool); G_CALLBACK (tool_cursor_prepare_at), tool);

View File

@ -28,6 +28,7 @@
#include "meta-wayland-types.h" #include "meta-wayland-types.h"
#include "meta-cursor-renderer.h" #include "meta-cursor-renderer.h"
#include "backends/meta-cursor-sprite-xcursor.h"
struct _MetaWaylandTabletTool struct _MetaWaylandTabletTool
{ {
@ -43,7 +44,7 @@ struct _MetaWaylandTabletTool
MetaWaylandSurface *cursor_surface; MetaWaylandSurface *cursor_surface;
struct wl_listener cursor_surface_destroy_listener; struct wl_listener cursor_surface_destroy_listener;
MetaCursorRenderer *cursor_renderer; MetaCursorRenderer *cursor_renderer;
MetaCursorSprite *default_sprite; MetaCursorSpriteXcursor *default_sprite;
guint prepare_at_signal_id; guint prepare_at_signal_id;
MetaWaylandSurface *current; MetaWaylandSurface *current;