From c66f26024b8ddc7b4b00b81e37945ad86b1a1fd8 Mon Sep 17 00:00:00 2001 From: Ander Conselvan de Oliveira Date: Thu, 24 May 2012 16:17:48 +0300 Subject: [PATCH] wayland-cursor: load all cursors from a theme on wl_cursor_theme_load --- cursor/wayland-cursor.c | 87 +++++++++++++++------------------------ cursor/xcursor.c | 107 ++++++++++++++++++++++++++++++++++++++++++++++++ cursor/xcursor.h | 4 ++ 3 files changed, 145 insertions(+), 53 deletions(-) diff --git a/cursor/wayland-cursor.c b/cursor/wayland-cursor.c index bfacc71..05d79e8 100644 --- a/cursor/wayland-cursor.c +++ b/cursor/wayland-cursor.c @@ -113,21 +113,6 @@ shm_pool_destroy(struct shm_pool *pool) } -static const char *cursor_names[] = { - "bottom_left_corner", - "bottom_right_corner", - "bottom_side", - "grabbing", - "left_ptr", - "left_side", - "right_side", - "top_left_corner", - "top_right_corner", - "top_side", - "xterm", - "hand1", -}; - struct wl_cursor_theme { unsigned int cursor_count; struct wl_cursor **cursors; @@ -192,32 +177,25 @@ wl_cursor_destroy(struct wl_cursor *cursor) } static struct wl_cursor * -load_cursor(struct wl_cursor_theme *theme, const char *name) +wl_cursor_create_from_xcursor_images(XcursorImages *images, + struct wl_cursor_theme *theme) { - XcursorImages *images; struct wl_cursor *cursor; struct cursor_image *image; int i, size; - images = XcursorLibraryLoadImages(name, theme->name, theme->size); - if (!images) - return NULL; - cursor = malloc(sizeof *cursor); - if (!cursor) { - XcursorImagesDestroy(images); + if (!cursor) return NULL; - } cursor->image_count = images->nimage; cursor->images = malloc(images->nimage * sizeof cursor->images[0]); if (!cursor->images) { - XcursorImagesDestroy(images); free(cursor); return NULL; } - cursor->name = strdup(name); + cursor->name = strdup(images->name); for (i = 0; i < images->nimage; i++) { image = malloc(sizeof *image); @@ -239,11 +217,34 @@ load_cursor(struct wl_cursor_theme *theme, const char *name) images->images[i]->pixels, size); } - XcursorImagesDestroy(images); - return cursor; } +static void +load_callback(XcursorImages *images, void *data) +{ + struct wl_cursor_theme *theme = data; + struct wl_cursor *cursor; + + if (wl_cursor_theme_get_cursor(theme, images->name)) { + XcursorImagesDestroy(images); + return; + } + + cursor = wl_cursor_create_from_xcursor_images(images, theme); + + if (cursor) { + theme->cursor_count++; + theme->cursors = + realloc(theme->cursors, + theme->cursor_count * sizeof theme->cursors[0]); + + theme->cursors[theme->cursor_count - 1] = cursor; + } + + XcursorImagesDestroy(images); +} + /** Load a cursor theme to memory shared with the compositor * * \param name The name of the cursor theme to load. If %NULL, the default @@ -258,7 +259,6 @@ WL_EXPORT struct wl_cursor_theme * wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm) { struct wl_cursor_theme *theme; - unsigned int i; theme = malloc(sizeof *theme); if (!theme) @@ -269,20 +269,13 @@ wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm) theme->name = strdup(name); theme->size = size; - theme->cursor_count = ARRAY_LENGTH(cursor_names); - - theme->cursors = - malloc(theme->cursor_count * sizeof theme->cursors[0]); - if (!theme->cursors) { - free(theme); - return NULL; - } + theme->cursor_count = 0; + theme->cursors = NULL; theme->pool = - shm_pool_create(shm, theme->cursor_count * size * size * 4); + shm_pool_create(shm, size * size * 4); - for (i = 0; i < theme->cursor_count; i++) - theme->cursors[i] = load_cursor(theme, cursor_names[i]); + xcursor_load_theme(name, size, load_callback, theme); return theme; } @@ -317,23 +310,11 @@ wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme, const char *name) { unsigned int i; - struct wl_cursor *cursor; for (i = 0; i < theme->cursor_count; i++) { if (strcmp(name, theme->cursors[i]->name) == 0) return theme->cursors[i]; } - cursor = load_cursor(theme, name); - if (!cursor) - return NULL; - - theme->cursor_count++; - theme->cursors = - realloc(theme->cursors, - theme->cursor_count * sizeof theme->cursors[0]); - - theme->cursors[theme->cursor_count - 1] = cursor; - - return cursor; + return NULL; } diff --git a/cursor/xcursor.c b/cursor/xcursor.c index 8b1199f..b3fa271 100644 --- a/cursor/xcursor.c +++ b/cursor/xcursor.c @@ -24,6 +24,7 @@ #include #include #include +#include /* * From libXcursor/include/X11/extensions/Xcursor.h @@ -854,3 +855,109 @@ XcursorLibraryLoadImages (const char *file, const char *theme, int size) } return images; } + +static void +load_all_cursors_from_dir(const char *path, int size, + void (*load_callback)(XcursorImages *, void *), + void *user_data) +{ + FILE *f; + DIR *dir = opendir(path); + struct dirent *ent; + char *full; + XcursorImages *images; + + if (!dir) + return; + + ent = readdir(dir); + for(ent = readdir(dir); ent; ent = readdir(dir)) { +#ifdef _DIRENT_HAVE_D_TYPE + if (ent->d_type != DT_REG && ent->d_type != DT_LNK) + continue; +#endif + + full = _XcursorBuildFullname(path, "", ent->d_name); + if (!full) + continue; + + f = fopen(full, "r"); + if (!f) + continue; + + images = XcursorFileLoadImages(f, size); + + if (images) { + XcursorImagesSetName(images, ent->d_name); + load_callback(images, user_data); + } + + fclose (f); + } + + closedir(dir); +} + +/** Load all the cursor of a theme + * + * This function loads all the cursor images of a given theme and its + * inherited themes. Each cursor is loaded into an XcursorImages object + * which is passed to the caller's load callback. If a cursor appears + * more than once across all the inherited themes, the load callback + * will be called multiple times, with possibly different XcursorImages + * object which have the same name. The user is expected to destroy the + * XcursorImages objects passed to the callback with + * XcursorImagesDestroy(). + * + * \param theme The name of theme that should be loaded + * \param size The desired size of the cursor images + * \param load_callback A callback function that will be called + * for each cursor loaded. The first parameter is the XcursorImages + * object representing the loaded cursor and the second is a pointer + * to data provided by the user. + * \param user_data The data that should be passed to the load callback + */ +void +xcursor_load_theme(const char *theme, int size, + void (*load_callback)(XcursorImages *, void *), + void *user_data) +{ + char *full, *dir; + char *inherits = NULL; + const char *path, *i; + + if (!theme) + theme = "default"; + + for (path = XcursorLibraryPath(); + path; + path = _XcursorNextPath(path)) { + dir = _XcursorBuildThemeDir(path, theme); + if (!dir) + continue; + + full = _XcursorBuildFullname(dir, "cursors", ""); + + if (full) { + load_all_cursors_from_dir(full, size, load_callback, + user_data); + free(full); + } + + if (!inherits) { + full = _XcursorBuildFullname(dir, "", "index.theme"); + if (full) { + inherits = _XcursorThemeInherits(full); + free(full); + } + } + + free(dir); + } + + for (i = inherits; i; i = _XcursorNextPath(i)) + xcursor_load_theme(i, size, load_callback, user_data); + + if (inherits) + free(inherits); +} diff --git a/cursor/xcursor.h b/cursor/xcursor.h index a39c58e..91747d9 100644 --- a/cursor/xcursor.h +++ b/cursor/xcursor.h @@ -55,4 +55,8 @@ XcursorLibraryLoadImages (const char *file, const char *theme, int size); void XcursorImagesDestroy (XcursorImages *images); +void +xcursor_load_theme(const char *theme, int size, + void (*load_callback)(XcursorImages *, void *), + void *user_data); #endif -- 2.7.4