From 141760057b409cdf31067cf9e4ec2efdc5c79fe7 Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Mon, 13 Jul 2015 20:32:42 +0200 Subject: [PATCH] backend: Store XcursorImages for theme cursors There's a chance the icon will be animated, so store the XcursorImages instead of the individual XcursorImage, and handle that as a nimages=1 special case. API to "tick" a cursor animation, and retrieve current frame timing information has been added. https://bugzilla.gnome.org/show_bug.cgi?id=752342 --- src/backends/meta-cursor-private.h | 7 ++++ src/backends/meta-cursor.c | 62 ++++++++++++++++++++++++++---- 2 files changed, 61 insertions(+), 8 deletions(-) diff --git a/src/backends/meta-cursor-private.h b/src/backends/meta-cursor-private.h index c8440e87e..9f1845115 100644 --- a/src/backends/meta-cursor-private.h +++ b/src/backends/meta-cursor-private.h @@ -24,6 +24,7 @@ #include "meta-cursor.h" +#include #include #ifdef HAVE_NATIVE_BACKEND @@ -42,6 +43,8 @@ typedef struct { struct _MetaCursorReference { int ref_count; + int current_frame; + XcursorImages *xcursor_images; MetaCursor cursor; MetaCursorImage image; }; @@ -56,4 +59,8 @@ struct gbm_bo *meta_cursor_reference_get_gbm_bo (MetaCursorReference *cursor, int *hot_y); #endif +gboolean meta_cursor_reference_is_animated (MetaCursorReference *self); +void meta_cursor_reference_tick_frame (MetaCursorReference *self); +guint meta_cursor_reference_get_current_frame_time (MetaCursorReference *self); + #endif /* META_CURSOR_PRIVATE_H */ diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c index 7c51ef08e..d888c3ee3 100644 --- a/src/backends/meta-cursor.c +++ b/src/backends/meta-cursor.c @@ -67,6 +67,8 @@ meta_cursor_image_free (MetaCursorImage *image) static void meta_cursor_reference_free (MetaCursorReference *self) { + if (self->xcursor_images) + XcursorImagesDestroy (self->xcursor_images); meta_cursor_image_free (&self->image); g_slice_free (MetaCursorReference, self); } @@ -135,12 +137,12 @@ meta_cursor_create_x_cursor (Display *xdisplay, return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor)); } -static XcursorImage * +static XcursorImages * load_cursor_on_client (MetaCursor cursor) { - return XcursorLibraryLoadImage (translate_meta_cursor (cursor), - meta_prefs_get_cursor_theme (), - meta_prefs_get_cursor_size ()); + return XcursorLibraryLoadImages (translate_meta_cursor (cursor), + meta_prefs_get_cursor_theme (), + meta_prefs_get_cursor_size ()); } #ifdef HAVE_NATIVE_BACKEND @@ -256,6 +258,46 @@ meta_cursor_image_load_from_xcursor_image (MetaCursorImage *image, #endif } +static XcursorImage * +meta_cursor_reference_get_current_frame_image (MetaCursorReference *self) +{ + return self->xcursor_images->images[self->current_frame]; +} + +void +meta_cursor_reference_tick_frame (MetaCursorReference *self) +{ + XcursorImage *image; + + if (!meta_cursor_reference_is_animated (self)) + return; + + self->current_frame++; + + if (self->current_frame >= self->xcursor_images->nimage) + self->current_frame = 0; + + meta_cursor_image_free (&self->image); + image = meta_cursor_reference_get_current_frame_image (self); + meta_cursor_image_load_from_xcursor_image (&self->image, image); +} + +guint +meta_cursor_reference_get_current_frame_time (MetaCursorReference *self) +{ + if (!meta_cursor_reference_is_animated (self)) + return 0; + + return self->xcursor_images->images[self->current_frame]->delay; +} + +gboolean +meta_cursor_reference_is_animated (MetaCursorReference *self) +{ + return (self->xcursor_images && + self->xcursor_images->nimage > 1); +} + static void load_cursor_image (MetaCursorReference *cursor) { @@ -266,12 +308,16 @@ load_cursor_image (MetaCursorReference *cursor) * load this directly. */ g_assert (cursor->cursor != META_CURSOR_NONE); - image = load_cursor_on_client (cursor->cursor); - if (!image) - return; + if (!cursor->xcursor_images) + { + cursor->current_frame = 0; + cursor->xcursor_images = load_cursor_on_client (cursor->cursor); + if (!cursor->xcursor_images) + return; + } + image = meta_cursor_reference_get_current_frame_image (cursor); meta_cursor_image_load_from_xcursor_image (&cursor->image, image); - XcursorImageDestroy (image); } MetaCursorReference *