[PATCH wayland 2/2] wayland-cursor: load all cursors from a theme on wl_cursor_theme_load

Ander Conselvan de Oliveira ander.conselvan.de.oliveira at intel.com
Thu May 24 06:17:48 PDT 2012


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



More information about the wayland-devel mailing list