summaryrefslogtreecommitdiff
path: root/cursor
diff options
context:
space:
mode:
Diffstat (limited to 'cursor')
-rw-r--r--cursor/wayland-cursor.c87
-rw-r--r--cursor/xcursor.c107
-rw-r--r--cursor/xcursor.h4
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 <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);
+}
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