diff --git a/src/Makefile.am b/src/Makefile.am index 96dd01ebe..8094abc98 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -178,6 +178,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ backends/x11/meta-gpu-xrandr.h \ backends/x11/cm/meta-backend-x11-cm.c \ backends/x11/cm/meta-backend-x11-cm.h \ + backends/x11/cm/meta-cursor-sprite-xfixes.c \ + backends/x11/cm/meta-cursor-sprite-xfixes.h \ backends/x11/cm/meta-renderer-x11-cm.c \ backends/x11/cm/meta-renderer-x11-cm.h \ backends/x11/nested/meta-backend-x11-nested.c \ diff --git a/src/backends/meta-cursor-tracker-private.h b/src/backends/meta-cursor-tracker-private.h index 2ec946847..6f4f84b83 100644 --- a/src/backends/meta-cursor-tracker-private.h +++ b/src/backends/meta-cursor-tracker-private.h @@ -26,6 +26,7 @@ #include "meta-cursor.h" #include "meta-cursor-renderer.h" +#include "backends/x11/cm/meta-cursor-sprite-xfixes.h" struct _MetaCursorTracker { GObject parent_instance; @@ -46,7 +47,7 @@ struct _MetaCursorTracker { MetaCursorSprite *root_cursor; /* The cursor from the X11 server. */ - MetaCursorSprite *xfixes_cursor; + MetaCursorSpriteXfixes *xfixes_cursor; }; struct _MetaCursorTrackerClass { diff --git a/src/backends/meta-cursor-tracker.c b/src/backends/meta-cursor-tracker.c index 74fa4351d..6244f11ee 100644 --- a/src/backends/meta-cursor-tracker.c +++ b/src/backends/meta-cursor-tracker.c @@ -40,9 +40,9 @@ #include #include -#include #include "meta-backend-private.h" +#include "backends/x11/cm/meta-cursor-sprite-xfixes.h" G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT); @@ -218,75 +218,14 @@ static void ensure_xfixes_cursor (MetaCursorTracker *tracker) { MetaDisplay *display = meta_get_display (); - XFixesCursorImage *cursor_image; - CoglTexture2D *sprite; - guint8 *cursor_data; - gboolean free_cursor_data; - CoglContext *ctx; - CoglError *error = NULL; + g_autoptr (GError) error = NULL; if (tracker->xfixes_cursor) return; - cursor_image = XFixesGetCursorImage (display->xdisplay); - if (!cursor_image) - return; - - /* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit - * quantities as arrays of long; we need to convert on 64 bit */ - if (sizeof(long) == 4) - { - cursor_data = (guint8 *)cursor_image->pixels; - free_cursor_data = FALSE; - } - else - { - int i, j; - guint32 *cursor_words; - gulong *p; - guint32 *q; - - cursor_words = g_new (guint32, cursor_image->width * cursor_image->height); - cursor_data = (guint8 *)cursor_words; - - p = cursor_image->pixels; - q = cursor_words; - for (j = 0; j < cursor_image->height; j++) - for (i = 0; i < cursor_image->width; i++) - *(q++) = *(p++); - - free_cursor_data = TRUE; - } - - ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); - sprite = cogl_texture_2d_new_from_data (ctx, - cursor_image->width, - cursor_image->height, - CLUTTER_CAIRO_FORMAT_ARGB32, - cursor_image->width * 4, /* stride */ - cursor_data, - &error); - - if (free_cursor_data) - g_free (cursor_data); - - if (error != NULL) - { - meta_warning ("Failed to allocate cursor sprite texture: %s\n", error->message); - cogl_error_free (error); - } - - if (sprite != NULL) - { - MetaCursorSprite *cursor_sprite = meta_cursor_sprite_new (); - meta_cursor_sprite_set_texture (cursor_sprite, - COGL_TEXTURE (sprite), - cursor_image->xhot, - cursor_image->yhot); - cogl_object_unref (sprite); - tracker->xfixes_cursor = cursor_sprite; - } - XFree (cursor_image); + tracker->xfixes_cursor = meta_cursor_sprite_xfixes_new (display, &error); + if (!tracker->xfixes_cursor) + g_warning ("Failed to create XFIXES cursor: %s", error->message); } /** @@ -308,7 +247,7 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker) else { ensure_xfixes_cursor (tracker); - cursor_sprite = tracker->xfixes_cursor; + cursor_sprite = META_CURSOR_SPRITE (tracker->xfixes_cursor); } if (cursor_sprite) @@ -345,7 +284,7 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, else { ensure_xfixes_cursor (tracker); - cursor_sprite = tracker->xfixes_cursor; + cursor_sprite = META_CURSOR_SPRITE (tracker->xfixes_cursor); } if (cursor_sprite) diff --git a/src/backends/x11/cm/meta-cursor-sprite-xfixes.c b/src/backends/x11/cm/meta-cursor-sprite-xfixes.c new file mode 100644 index 000000000..143ebb791 --- /dev/null +++ b/src/backends/x11/cm/meta-cursor-sprite-xfixes.c @@ -0,0 +1,226 @@ +/* + * 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 . + * + */ + +#include "config.h" + +#include "backends/x11/cm/meta-cursor-sprite-xfixes.h" + +#include + +#include "core/display-private.h" + +enum +{ + PROP_0, + + PROP_DISPLAY, + + N_PROPS +}; + +static GParamSpec *obj_props[N_PROPS]; + +struct _MetaCursorSpriteXfixes +{ + MetaCursorSprite parent; + + MetaDisplay *display; +}; + +static void +meta_screen_cast_xfixes_init_initable_iface (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (MetaCursorSpriteXfixes, + meta_cursor_sprite_xfixes, + META_TYPE_CURSOR_SPRITE, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + meta_screen_cast_xfixes_init_initable_iface)) + +static void +meta_cursor_sprite_xfixes_realize_texture (MetaCursorSprite *sprite) +{ +} + +static gboolean +meta_cursor_sprite_xfixes_is_animated (MetaCursorSprite *sprite) +{ + return FALSE; +} + +static void +meta_cursor_sprite_xfixes_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + MetaCursorSpriteXfixes *sprite_xfixes = META_CURSOR_SPRITE_XFIXES (object); + + switch (prop_id) + { + case PROP_DISPLAY: + g_value_set_object (value, sprite_xfixes->display); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +meta_cursor_sprite_xfixes_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + MetaCursorSpriteXfixes *sprite_xfixes = META_CURSOR_SPRITE_XFIXES (object); + + switch (prop_id) + { + case PROP_DISPLAY: + sprite_xfixes->display = g_value_get_object (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +MetaCursorSpriteXfixes * +meta_cursor_sprite_xfixes_new (MetaDisplay *display, + GError **error) +{ + return g_initable_new (META_TYPE_CURSOR_SPRITE_XFIXES, + NULL, error, + "display", display, + NULL); +} + +static gboolean +meta_cursor_sprite_xfixes_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + MetaCursorSpriteXfixes *sprite_xfixes = + META_CURSOR_SPRITE_XFIXES (initable); + MetaCursorSprite *sprite = META_CURSOR_SPRITE (sprite_xfixes); + XFixesCursorImage *cursor_image; + CoglTexture2D *texture; + uint8_t *cursor_data; + gboolean free_cursor_data; + ClutterBackend *clutter_backend; + CoglContext *cogl_context; + + cursor_image = XFixesGetCursorImage (sprite_xfixes->display->xdisplay); + if (!cursor_image) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to get cursor image"); + return FALSE; + } + + /* + * Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit + * quantities as arrays of long; we need to convert on 64 bit + */ + if (sizeof (long) == 4) + { + cursor_data = (uint8_t *) cursor_image->pixels; + free_cursor_data = FALSE; + } + else + { + int i, j; + uint32_t *cursor_words; + unsigned long *p; + uint32_t *q; + + cursor_words = g_new (uint32_t, + cursor_image->width * cursor_image->height); + cursor_data = (uint8_t *) cursor_words; + + p = cursor_image->pixels; + q = cursor_words; + for (j = 0; j < cursor_image->height; j++) + { + for (i = 0; i < cursor_image->width; i++) + *(q++) = *(p++); + } + + free_cursor_data = TRUE; + } + + clutter_backend = clutter_get_default_backend (); + cogl_context = clutter_backend_get_cogl_context (clutter_backend); + texture = cogl_texture_2d_new_from_data (cogl_context, + cursor_image->width, + cursor_image->height, + CLUTTER_CAIRO_FORMAT_ARGB32, + cursor_image->width * 4, /* stride */ + cursor_data, + error); + + if (free_cursor_data) + g_free (cursor_data); + + if (!sprite) + return FALSE; + + meta_cursor_sprite_set_texture (sprite, + COGL_TEXTURE (texture), + cursor_image->xhot, + cursor_image->yhot); + cogl_object_unref (texture); + XFree (cursor_image); + + return TRUE; +} + +static void +meta_screen_cast_xfixes_init_initable_iface (GInitableIface *iface) +{ + iface->init = meta_cursor_sprite_xfixes_initable_init; +} + +static void +meta_cursor_sprite_xfixes_init (MetaCursorSpriteXfixes *sprite_xfixes) +{ +} + +static void +meta_cursor_sprite_xfixes_class_init (MetaCursorSpriteXfixesClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MetaCursorSpriteClass *cursor_sprite_class = META_CURSOR_SPRITE_CLASS (klass); + + object_class->get_property = meta_cursor_sprite_xfixes_get_property; + object_class->set_property = meta_cursor_sprite_xfixes_set_property; + + cursor_sprite_class->realize_texture = + meta_cursor_sprite_xfixes_realize_texture; + cursor_sprite_class->is_animated = meta_cursor_sprite_xfixes_is_animated; + + obj_props[PROP_DISPLAY] = + g_param_spec_object ("display", + "display", + "MetaDisplay", + META_TYPE_DISPLAY, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + g_object_class_install_properties (object_class, N_PROPS, obj_props); +} diff --git a/src/backends/x11/cm/meta-cursor-sprite-xfixes.h b/src/backends/x11/cm/meta-cursor-sprite-xfixes.h new file mode 100644 index 000000000..c7073fc2c --- /dev/null +++ b/src/backends/x11/cm/meta-cursor-sprite-xfixes.h @@ -0,0 +1,36 @@ +/* + * 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 . + * + */ + +#ifndef META_CURSOR_SPRITE_XFIXES_H +#define META_CURSOR_SPRITE_XFIXES_H + +#include + +#include "backends/meta-cursor.h" +#include "meta/types.h" + +#define META_TYPE_CURSOR_SPRITE_XFIXES (meta_cursor_sprite_xfixes_get_type ()) +G_DECLARE_FINAL_TYPE (MetaCursorSpriteXfixes, + meta_cursor_sprite_xfixes, + META, CURSOR_SPRITE_XFIXES, + MetaCursorSprite) + +MetaCursorSpriteXfixes * meta_cursor_sprite_xfixes_new (MetaDisplay *display, + GError **error); + +#endif /* META_CURSOR_SPRITE_XFIXES_H */