mirror of
https://gitlab.freedesktop.org/wayland/wayland.git
synced 2026-02-18 22:05:55 -05:00
wayland-cursor: load all cursors from a theme on wl_cursor_theme_load
This commit is contained in:
parent
f779c57be2
commit
c66f26024b
3 changed files with 145 additions and 53 deletions
|
|
@ -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 {
|
struct wl_cursor_theme {
|
||||||
unsigned int cursor_count;
|
unsigned int cursor_count;
|
||||||
struct wl_cursor **cursors;
|
struct wl_cursor **cursors;
|
||||||
|
|
@ -192,32 +177,25 @@ wl_cursor_destroy(struct wl_cursor *cursor)
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct wl_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 wl_cursor *cursor;
|
||||||
struct cursor_image *image;
|
struct cursor_image *image;
|
||||||
int i, size;
|
int i, size;
|
||||||
|
|
||||||
images = XcursorLibraryLoadImages(name, theme->name, theme->size);
|
|
||||||
if (!images)
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
cursor = malloc(sizeof *cursor);
|
cursor = malloc(sizeof *cursor);
|
||||||
if (!cursor) {
|
if (!cursor)
|
||||||
XcursorImagesDestroy(images);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
|
||||||
|
|
||||||
cursor->image_count = images->nimage;
|
cursor->image_count = images->nimage;
|
||||||
cursor->images = malloc(images->nimage * sizeof cursor->images[0]);
|
cursor->images = malloc(images->nimage * sizeof cursor->images[0]);
|
||||||
if (!cursor->images) {
|
if (!cursor->images) {
|
||||||
XcursorImagesDestroy(images);
|
|
||||||
free(cursor);
|
free(cursor);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor->name = strdup(name);
|
cursor->name = strdup(images->name);
|
||||||
|
|
||||||
for (i = 0; i < images->nimage; i++) {
|
for (i = 0; i < images->nimage; i++) {
|
||||||
image = malloc(sizeof *image);
|
image = malloc(sizeof *image);
|
||||||
|
|
@ -239,11 +217,34 @@ load_cursor(struct wl_cursor_theme *theme, const char *name)
|
||||||
images->images[i]->pixels, size);
|
images->images[i]->pixels, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
XcursorImagesDestroy(images);
|
|
||||||
|
|
||||||
return cursor;
|
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
|
/** Load a cursor theme to memory shared with the compositor
|
||||||
*
|
*
|
||||||
* \param name The name of the cursor theme to load. If %NULL, the default
|
* \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)
|
wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
|
||||||
{
|
{
|
||||||
struct wl_cursor_theme *theme;
|
struct wl_cursor_theme *theme;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
theme = malloc(sizeof *theme);
|
theme = malloc(sizeof *theme);
|
||||||
if (!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->name = strdup(name);
|
||||||
theme->size = size;
|
theme->size = size;
|
||||||
theme->cursor_count = ARRAY_LENGTH(cursor_names);
|
theme->cursor_count = 0;
|
||||||
|
theme->cursors = NULL;
|
||||||
theme->cursors =
|
|
||||||
malloc(theme->cursor_count * sizeof theme->cursors[0]);
|
|
||||||
if (!theme->cursors) {
|
|
||||||
free(theme);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
theme->pool =
|
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++)
|
xcursor_load_theme(name, size, load_callback, theme);
|
||||||
theme->cursors[i] = load_cursor(theme, cursor_names[i]);
|
|
||||||
|
|
||||||
return theme;
|
return theme;
|
||||||
}
|
}
|
||||||
|
|
@ -317,23 +310,11 @@ wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
struct wl_cursor *cursor;
|
|
||||||
|
|
||||||
for (i = 0; i < theme->cursor_count; i++) {
|
for (i = 0; i < theme->cursor_count; i++) {
|
||||||
if (strcmp(name, theme->cursors[i]->name) == 0)
|
if (strcmp(name, theme->cursors[i]->name) == 0)
|
||||||
return theme->cursors[i];
|
return theme->cursors[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
cursor = load_cursor(theme, name);
|
return NULL;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
107
cursor/xcursor.c
107
cursor/xcursor.c
|
|
@ -24,6 +24,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* From libXcursor/include/X11/extensions/Xcursor.h
|
* From libXcursor/include/X11/extensions/Xcursor.h
|
||||||
|
|
@ -854,3 +855,109 @@ XcursorLibraryLoadImages (const char *file, const char *theme, int size)
|
||||||
}
|
}
|
||||||
return images;
|
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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,4 +55,8 @@ XcursorLibraryLoadImages (const char *file, const char *theme, int size);
|
||||||
void
|
void
|
||||||
XcursorImagesDestroy (XcursorImages *images);
|
XcursorImagesDestroy (XcursorImages *images);
|
||||||
|
|
||||||
|
void
|
||||||
|
xcursor_load_theme(const char *theme, int size,
|
||||||
|
void (*load_callback)(XcursorImages *, void *),
|
||||||
|
void *user_data);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue