wayland-cursor: load all cursors from a theme on wl_cursor_theme_load

This commit is contained in:
Ander Conselvan de Oliveira 2012-05-24 16:17:48 +03:00 committed by Kristian Høgsberg
parent f779c57be2
commit c66f26024b
3 changed files with 145 additions and 53 deletions

View file

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

View file

@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
/*
* 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);
}

View file

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