diff --git a/gdk/wayland/cursor/meson.build b/gdk/wayland/cursor/meson.build deleted file mode 100644 index 02d5f2bed8..0000000000 --- a/gdk/wayland/cursor/meson.build +++ /dev/null @@ -1,12 +0,0 @@ -wayland_cursor_sources = files([ - 'wayland-cursor.c', - 'xcursor.c', - 'os-compatibility.c' -]) - -libwayland_cursor = static_library('wayland+cursor', - sources: wayland_cursor_sources, - include_directories: [ confinc, ], - dependencies: [ glib_dep, wlclientdep, ], - c_args: common_cflags, -) diff --git a/gdk/wayland/cursor/os-compatibility.c b/gdk/wayland/cursor/os-compatibility.c deleted file mode 100644 index 3818a6170e..0000000000 --- a/gdk/wayland/cursor/os-compatibility.c +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright © 2012 Collabora, Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "config.h" - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_MEMFD_CREATE -#include -#endif - -#include "os-compatibility.h" - -#ifndef HAVE_MKOSTEMP -static int -set_cloexec_or_close(int fd) -{ - long flags; - - if (fd == -1) - return -1; - - flags = fcntl(fd, F_GETFD); - if (flags == -1) - goto err; - - if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1) - goto err; - - return fd; - -err: - close(fd); - return -1; -} -#endif - -static int -create_tmpfile_cloexec(char *tmpname) -{ - int fd; - -#ifdef HAVE_MKOSTEMP - fd = mkostemp(tmpname, O_CLOEXEC); - if (fd >= 0) - unlink(tmpname); -#else - fd = mkstemp(tmpname); - if (fd >= 0) { - fd = set_cloexec_or_close(fd); - unlink(tmpname); - } -#endif - - return fd; -} - -/* - * Create a new, unique, anonymous file of the given size, and - * return the file descriptor for it. The file descriptor is set - * CLOEXEC. The file is immediately suitable for mmap()'ing - * the given size at offset zero. - * - * The file should not have a permanent backing store like a disk, - * but may have if XDG_RUNTIME_DIR is not properly implemented in OS. - * - * The file name is deleted from the file system. - * - * The file is suitable for buffer sharing between processes by - * transmitting the file descriptor over Unix sockets using the - * SCM_RIGHTS methods. - * - * If the C library implements posix_fallocate(), it is used to - * guarantee that disk space is available for the file at the - * given size. If disk space is insufficient, errno is set to ENOSPC. - * If posix_fallocate() is not supported, program may receive - * SIGBUS on accessing mmap()'ed file contents instead. - * - * If the C library implements memfd_create(), it is used to create the - * file purely in memory, without any backing file name on the file - * system, and then sealing off the possibility of shrinking it. This - * can then be checked before accessing mmap()'ed file contents, to - * make sure SIGBUS can't happen. It also avoids requiring - * XDG_RUNTIME_DIR. - */ -int -os_create_anonymous_file(off_t size) -{ - static const char template[] = "/wayland-cursor-shared-XXXXXX"; - const char *path; - char *name; - int fd; - int ret; - -#ifdef HAVE_MEMFD_CREATE - fd = memfd_create("wayland-cursor", MFD_CLOEXEC | MFD_ALLOW_SEALING); - if (fd >= 0) { - /* We can add this seal before calling posix_fallocate(), as - * the file is currently zero-sized anyway. - * - * There is also no need to check for the return value, we - * couldn't do anything with it anyway. - */ - fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL); - } else -#endif - { - path = getenv("XDG_RUNTIME_DIR"); - if (!path) { - errno = ENOENT; - return -1; - } - - name = malloc(strlen(path) + sizeof(template)); - if (!name) - return -1; - - strcpy(name, path); - strcat(name, template); - - fd = create_tmpfile_cloexec(name); - - free(name); - - if (fd < 0) - return -1; - } - -#ifdef HAVE_POSIX_FALLOCATE - ret = posix_fallocate(fd, 0, size); - if (ret != 0) { - close(fd); - errno = ret; - return -1; - } -#else - ret = ftruncate(fd, size); - if (ret < 0) { - close(fd); - return -1; - } -#endif - - return fd; -} diff --git a/gdk/wayland/cursor/os-compatibility.h b/gdk/wayland/cursor/os-compatibility.h deleted file mode 100644 index d0e69acd93..0000000000 --- a/gdk/wayland/cursor/os-compatibility.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright © 2012 Collabora, Ltd. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef OS_COMPATIBILITY_H -#define OS_COMPATIBILITY_H - -#include - -int -os_create_anonymous_file(off_t size); - -#endif /* OS_COMPATIBILITY_H */ diff --git a/gdk/wayland/cursor/wayland-cursor.c b/gdk/wayland/cursor/wayland-cursor.c deleted file mode 100644 index 4be8f9a4d4..0000000000 --- a/gdk/wayland/cursor/wayland-cursor.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "config.h" -#include "xcursor.h" -#include "wayland-cursor.h" -#include "wayland-client.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) - -struct shm_pool { - struct wl_shm_pool *pool; - int fd; - unsigned int size; - unsigned int used; - char *data; -}; - -static struct shm_pool * -shm_pool_create(struct wl_shm *shm, int size) -{ - struct shm_pool *pool; - - pool = malloc(sizeof *pool); - if (!pool) - return NULL; - - pool->fd = os_create_anonymous_file (size); - if (pool->fd < 0) - goto err_free; - - pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, - pool->fd, 0); - - if (pool->data == MAP_FAILED) - goto err_close; - - pool->pool = wl_shm_create_pool(shm, pool->fd, size); - pool->size = size; - pool->used = 0; - - return pool; - -err_close: - close(pool->fd); -err_free: - free(pool); - return NULL; -} - -static int -shm_pool_resize(struct shm_pool *pool, int size) -{ - if (ftruncate(pool->fd, size) < 0) - return 0; - -#ifdef HAVE_POSIX_FALLOCATE - errno = posix_fallocate(pool->fd, 0, size); - if (errno != 0) - return 0; -#endif - - wl_shm_pool_resize(pool->pool, size); - - munmap(pool->data, pool->size); - - pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, - pool->fd, 0); - if (pool->data == (void *)-1) - return 0; - pool->size = size; - - return 1; -} - -static int -shm_pool_allocate(struct shm_pool *pool, int size) -{ - int offset; - - if (pool->used + size > pool->size) - if (!shm_pool_resize(pool, 2 * pool->size + size)) - return -1; - - offset = pool->used; - pool->used += size; - - return offset; -} - -static void -shm_pool_destroy(struct shm_pool *pool) -{ - munmap(pool->data, pool->size); - wl_shm_pool_destroy(pool->pool); - close(pool->fd); - free(pool); -} - - -struct wl_cursor_theme { - unsigned int cursor_count; - struct wl_cursor **cursors; - struct wl_shm *shm; - struct shm_pool *pool; - int size; - char *path; -}; - -struct cursor_image { - struct wl_cursor_image image; - struct wl_cursor_theme *theme; - struct wl_buffer *buffer; - int offset; /* data offset of this image in the shm pool */ -}; - -struct cursor { - struct wl_cursor cursor; - uint32_t total_delay; /* length of the animation in ms */ -}; - -/** Get an shm buffer for a cursor image - * - * \param image The cursor image - * \return An shm buffer for the cursor image. The user should not destroy - * the returned buffer. - */ -struct wl_buffer * -wl_cursor_image_get_buffer(struct wl_cursor_image *_img) -{ - struct cursor_image *image = (struct cursor_image *) _img; - struct wl_cursor_theme *theme = image->theme; - - if (!image->buffer) { - image->buffer = - wl_shm_pool_create_buffer(theme->pool->pool, - image->offset, - _img->width, _img->height, - _img->width * 4, - WL_SHM_FORMAT_ARGB8888); - }; - - return image->buffer; -} - -static void -wl_cursor_image_destroy(struct wl_cursor_image *_img) -{ - struct cursor_image *image = (struct cursor_image *) _img; - - if (image->buffer) - wl_buffer_destroy(image->buffer); - - free(image); -} - -static void -wl_cursor_destroy(struct wl_cursor *cursor) -{ - unsigned int i; - - for (i = 0; i < cursor->image_count; i++) - wl_cursor_image_destroy(cursor->images[i]); - - free(cursor->images); - free(cursor->name); - free(cursor); -} - -static struct wl_cursor * -wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme, - const char *name, - unsigned int size, - unsigned int scale) -{ - char *path; - XcursorImages *images; - struct cursor *cursor; - struct cursor_image *image; - int i, nbytes; - unsigned int load_size; - int load_scale = 1; - - load_size = size * scale; - - path = g_strconcat (theme->path, "/", name, NULL); - images = xcursor_load_images (path, load_size); - - if (!images) - { - g_free (path); - return NULL; - } - - if (images->images[0]->width != load_size || - images->images[0]->height != load_size) - { - xcursor_images_destroy (images); - images = xcursor_load_images (path, size); - load_scale = scale; - } - - g_free (path); - - cursor = malloc(sizeof *cursor); - if (!cursor) { - xcursor_images_destroy (images); - return NULL; - } - - cursor->cursor.images = - malloc(images->nimage * sizeof cursor->cursor.images[0]); - if (!cursor->cursor.images) { - free(cursor); - xcursor_images_destroy (images); - return NULL; - } - - cursor->cursor.name = strdup(name); - cursor->cursor.size = load_size; - cursor->total_delay = 0; - - for (i = 0; i < images->nimage; i++) { - image = malloc(sizeof *image); - if (image == NULL) - break; - - image->theme = theme; - image->buffer = NULL; - - image->image.width = images->images[i]->width * load_scale; - image->image.height = images->images[i]->height * load_scale; - image->image.hotspot_x = images->images[i]->xhot * load_scale; - image->image.hotspot_y = images->images[i]->yhot * load_scale; - image->image.delay = images->images[i]->delay; - - nbytes = image->image.width * image->image.height * 4; - image->offset = shm_pool_allocate(theme->pool, nbytes); - if (image->offset < 0) { - free(image); - break; - } - - if (load_scale == 1) { - /* copy pixels to shm pool */ - memcpy(theme->pool->data + image->offset, - images->images[i]->pixels, nbytes); - } - else { - /* scale image up while copying it */ - for (int y = 0; y < image->image.height; y++) { - char *p = theme->pool->data + image->offset + y * image->image.width * 4; - char *q = ((char *)images->images[i]->pixels) + (y / load_scale) * images->images[i]->width * 4; - for (int x = 0; x < image->image.width; x++) { - p[4 * x] = q[4 * (x/load_scale)]; - p[4 * x + 1] = q[4 * (x/load_scale) + 1]; - p[4 * x + 2] = q[4 * (x/load_scale) + 2]; - p[4 * x + 3] = q[4 * (x/load_scale) + 3]; - } - } - } - cursor->total_delay += image->image.delay; - cursor->cursor.images[i] = (struct wl_cursor_image *) image; - } - cursor->cursor.image_count = i; - - if (cursor->cursor.image_count == 0) { - free(cursor->cursor.name); - free(cursor->cursor.images); - free(cursor); - xcursor_images_destroy (images); - return NULL; - } - - xcursor_images_destroy (images); - - return &cursor->cursor; -} - -static void -load_cursor(struct wl_cursor_theme *theme, - const char *name, - unsigned int size, - unsigned int scale) -{ - struct wl_cursor *cursor; - - cursor = wl_cursor_create_from_xcursor_images(theme, name, size, scale); - - if (cursor) { - theme->cursor_count++; - theme->cursors = - realloc(theme->cursors, - theme->cursor_count * sizeof theme->cursors[0]); - - if (theme->cursors == NULL) { - theme->cursor_count--; - free(cursor); - } else { - theme->cursors[theme->cursor_count - 1] = cursor; - } - } -} - -/** Load a cursor theme to memory shared with the compositor - * - * \param name The name of the cursor theme to load. If %NULL, the default - * theme will be loaded. - * \param size Desired size of the cursor images. - * \param shm The compositor's shm interface. - * - * \return An object representing the theme that should be destroyed with - * wl_cursor_theme_destroy() or %NULL on error. If no theme with the given - * name exists, a default theme will be loaded. - */ -struct wl_cursor_theme * -wl_cursor_theme_create(const char *path, int size, struct wl_shm *shm) -{ - struct wl_cursor_theme *theme; - - theme = malloc(sizeof *theme); - if (!theme) - return NULL; - - theme->path = strdup (path); - theme->size = size; - theme->cursor_count = 0; - theme->cursors = NULL; - - theme->pool = shm_pool_create(shm, size * size * 4); - if (!theme->pool) { - free (theme->path); - free (theme); - return NULL; - } - - return theme; -} - -/** Destroys a cursor theme object - * - * \param theme The cursor theme to be destroyed - */ -void -wl_cursor_theme_destroy(struct wl_cursor_theme *theme) -{ - unsigned int i; - - for (i = 0; i < theme->cursor_count; i++) - wl_cursor_destroy(theme->cursors[i]); - - shm_pool_destroy(theme->pool); - - free(theme->cursors); - free(theme->path); - free(theme); -} - -/** Get the cursor for a given name from a cursor theme - * - * \param theme The cursor theme - * \param name Name of the desired cursor - * \return The theme's cursor of the given name or %NULL if there is no - * such cursor - */ -struct wl_cursor * -wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme, - const char *name, - unsigned int scale) -{ - unsigned int i; - unsigned int size; - - size = theme->size * scale; - - for (i = 0; i < theme->cursor_count; i++) { - if (size == theme->cursors[i]->size && - strcmp(name, theme->cursors[i]->name) == 0) - return theme->cursors[i]; - } - - load_cursor (theme, name, theme->size, scale); - - if (i < theme->cursor_count) { - if (size == theme->cursors[i]->size && - strcmp (name, theme->cursors[theme->cursor_count - 1]->name) == 0) - return theme->cursors[theme->cursor_count - 1]; - } - - return NULL; -} diff --git a/gdk/wayland/cursor/wayland-cursor.h b/gdk/wayland/cursor/wayland-cursor.h deleted file mode 100644 index 6a26fa785e..0000000000 --- a/gdk/wayland/cursor/wayland-cursor.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright © 2012 Intel Corporation - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef WAYLAND_CURSOR_H -#define WAYLAND_CURSOR_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -struct wl_cursor_theme; -struct wl_buffer; -struct wl_shm; - -struct wl_cursor_image { - uint32_t width; /* actual width */ - uint32_t height; /* actual height */ - uint32_t hotspot_x; /* hot spot x (must be inside image) */ - uint32_t hotspot_y; /* hot spot y (must be inside image) */ - uint32_t delay; /* animation delay to next frame (ms) */ -}; - -struct wl_cursor { - unsigned int image_count; - struct wl_cursor_image **images; - char *name; - unsigned int size; -}; - -struct wl_cursor_theme * -wl_cursor_theme_create(const char *name, int size, struct wl_shm *shm); - -void -wl_cursor_theme_destroy(struct wl_cursor_theme *theme); - -struct wl_cursor * -wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme, - const char *name, - unsigned int scale); - -struct wl_buffer * -wl_cursor_image_get_buffer(struct wl_cursor_image *image); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/gdk/wayland/cursor/xcursor.c b/gdk/wayland/cursor/xcursor.c deleted file mode 100644 index eef013390c..0000000000 --- a/gdk/wayland/cursor/xcursor.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * Copyright © 2002 Keith Packard - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "xcursor.h" -#include -#include -#include -#include - -/* - * From libXcursor/include/X11/extensions/Xcursor.h - */ - -#define XcursorTrue 1 -#define XcursorFalse 0 - -/* - * Cursor files start with a header. The header - * contains a magic number, a version number and a - * table of contents which has type and offset information - * for the remaining tables in the file. - * - * File minor versions increment for compatible changes - * File major versions increment for incompatible changes (never, we hope) - * - * Chunks of the same type are always upward compatible. Incompatible - * changes are made with new chunk types; the old data can remain under - * the old type. Upward compatible changes can add header data as the - * header lengths are specified in the file. - * - * File: - * FileHeader - * LISTofChunk - * - * FileHeader: - * CARD32 magic magic number - * CARD32 header bytes in file header - * CARD32 version file version - * CARD32 ntoc number of toc entries - * LISTofFileToc toc table of contents - * - * FileToc: - * CARD32 type entry type - * CARD32 subtype entry subtype (size for images) - * CARD32 position absolute file position - */ - -#define XCURSOR_MAGIC 0x72756358 /* "Xcur" LSBFirst */ - -/* - * Current Xcursor version number. Will be substituted by configure - * from the version in the libXcursor configure.ac file. - */ - -#define XCURSOR_LIB_MAJOR 1 -#define XCURSOR_LIB_MINOR 1 -#define XCURSOR_LIB_REVISION 13 -#define XCURSOR_LIB_VERSION ((XCURSOR_LIB_MAJOR * 10000) + \ - (XCURSOR_LIB_MINOR * 100) + \ - (XCURSOR_LIB_REVISION)) - -/* - * This version number is stored in cursor files; changes to the - * file format require updating this version number - */ -#define XCURSOR_FILE_MAJOR 1 -#define XCURSOR_FILE_MINOR 0 -#define XCURSOR_FILE_VERSION ((XCURSOR_FILE_MAJOR << 16) | (XCURSOR_FILE_MINOR)) -#define XCURSOR_FILE_HEADER_LEN (4 * 4) -#define XCURSOR_FILE_TOC_LEN (3 * 4) - -typedef struct _XcursorFileToc { - XcursorUInt type; /* chunk type */ - XcursorUInt subtype; /* subtype (size for images) */ - XcursorUInt position; /* absolute position in file */ -} XcursorFileToc; - -typedef struct _XcursorFileHeader { - XcursorUInt magic; /* magic number */ - XcursorUInt header; /* byte length of header */ - XcursorUInt version; /* file version number */ - XcursorUInt ntoc; /* number of toc entries */ - XcursorFileToc *tocs; /* table of contents */ -} XcursorFileHeader; - -/* - * The rest of the file is a list of chunks, each tagged by type - * and version. - * - * Chunk: - * ChunkHeader - * - * - * - * ChunkHeader: - * CARD32 header bytes in chunk header + type header - * CARD32 type chunk type - * CARD32 subtype chunk subtype - * CARD32 version chunk type version - */ - -#define XCURSOR_CHUNK_HEADER_LEN (4 * 4) - -typedef struct _XcursorChunkHeader { - XcursorUInt header; /* bytes in chunk header */ - XcursorUInt type; /* chunk type */ - XcursorUInt subtype; /* chunk subtype (size for images) */ - XcursorUInt version; /* version of this type */ -} XcursorChunkHeader; - -/* - * Here's a list of the known chunk types - */ - -/* - * Comments consist of a 4-byte length field followed by - * UTF-8 encoded text - * - * Comment: - * ChunkHeader header chunk header - * CARD32 length bytes in text - * LISTofCARD8 text UTF-8 encoded text - */ - -#define XCURSOR_COMMENT_TYPE 0xfffe0001 -#define XCURSOR_COMMENT_VERSION 1 -#define XCURSOR_COMMENT_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (1 *4)) -#define XCURSOR_COMMENT_COPYRIGHT 1 -#define XCURSOR_COMMENT_LICENSE 2 -#define XCURSOR_COMMENT_OTHER 3 -#define XCURSOR_COMMENT_MAX_LEN 0x100000 - -typedef struct _XcursorComment { - XcursorUInt version; - XcursorUInt comment_type; - char *comment; -} XcursorComment; - -/* - * Each cursor image occupies a separate image chunk. - * The length of the image header follows the chunk header - * so that future versions can extend the header without - * breaking older applications - * - * Image: - * ChunkHeader header chunk header - * CARD32 width actual width - * CARD32 height actual height - * CARD32 xhot hot spot x - * CARD32 yhot hot spot y - * CARD32 delay animation delay - * LISTofCARD32 pixels ARGB pixels - */ - -#define XCURSOR_IMAGE_TYPE 0xfffd0002 -#define XCURSOR_IMAGE_VERSION 1 -#define XCURSOR_IMAGE_HEADER_LEN (XCURSOR_CHUNK_HEADER_LEN + (5*4)) -#define XCURSOR_IMAGE_MAX_SIZE 0x7fff /* 32767x32767 max cursor size */ - -typedef struct _XcursorFile XcursorFile; - -struct _XcursorFile { - void *closure; - int (*read) (XcursorFile *file, unsigned char *buf, int len); - int (*write) (XcursorFile *file, unsigned char *buf, int len); - int (*seek) (XcursorFile *file, long offset, int whence); -}; - -typedef struct _XcursorComments { - int ncomment; /* number of comments */ - XcursorComment **comments; /* array of XcursorComment pointers */ -} XcursorComments; - -/* - * From libXcursor/src/file.c - */ - -static XcursorImage * -XcursorImageCreate (int width, int height) -{ - XcursorImage *image; - - if (width < 0 || height < 0) - return NULL; - if (width > XCURSOR_IMAGE_MAX_SIZE || height > XCURSOR_IMAGE_MAX_SIZE) - return NULL; - - image = malloc (sizeof (XcursorImage) + - width * height * sizeof (XcursorPixel)); - if (!image) - return NULL; - image->version = XCURSOR_IMAGE_VERSION; - image->pixels = (XcursorPixel *) (image + 1); - image->size = width > height ? width : height; - image->width = width; - image->height = height; - image->delay = 0; - return image; -} - -static void -XcursorImageDestroy (XcursorImage *image) -{ - free (image); -} - -static XcursorImages * -XcursorImagesCreate (int size) -{ - XcursorImages *images; - - images = malloc (sizeof (XcursorImages) + - size * sizeof (XcursorImage *)); - if (!images) - return NULL; - images->nimage = 0; - images->images = (XcursorImage **) (images + 1); - images->name = NULL; - return images; -} - -static void -XcursorImagesDestroy (XcursorImages *images) -{ - int n; - - if (!images) - return; - - for (n = 0; n < images->nimage; n++) - XcursorImageDestroy (images->images[n]); - if (images->name) - free (images->name); - free (images); -} - -static XcursorBool -_XcursorReadUInt (XcursorFile *file, XcursorUInt *u) -{ - unsigned char bytes[4]; - - if (!file || !u) - return XcursorFalse; - - if ((*file->read) (file, bytes, 4) != 4) - return XcursorFalse; - *u = ((bytes[0] << 0) | - (bytes[1] << 8) | - (bytes[2] << 16) | - (bytes[3] << 24)); - return XcursorTrue; -} - -static void -_XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader) -{ - free (fileHeader); -} - -static XcursorFileHeader * -_XcursorFileHeaderCreate (int ntoc) -{ - XcursorFileHeader *fileHeader; - - if (ntoc > 0x10000) - return NULL; - fileHeader = malloc (sizeof (XcursorFileHeader) + - ntoc * sizeof (XcursorFileToc)); - if (!fileHeader) - return NULL; - fileHeader->magic = XCURSOR_MAGIC; - fileHeader->header = XCURSOR_FILE_HEADER_LEN; - fileHeader->version = XCURSOR_FILE_VERSION; - fileHeader->ntoc = ntoc; - fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1); - return fileHeader; -} - -static XcursorFileHeader * -_XcursorReadFileHeader (XcursorFile *file) -{ - XcursorFileHeader head, *fileHeader; - XcursorUInt skip; - unsigned int n; - - if (!file) - return NULL; - - if (!_XcursorReadUInt (file, &head.magic)) - return NULL; - if (head.magic != XCURSOR_MAGIC) - return NULL; - if (!_XcursorReadUInt (file, &head.header)) - return NULL; - if (!_XcursorReadUInt (file, &head.version)) - return NULL; - if (!_XcursorReadUInt (file, &head.ntoc)) - return NULL; - skip = head.header - XCURSOR_FILE_HEADER_LEN; - if (skip) - if ((*file->seek) (file, skip, SEEK_CUR) == EOF) - return NULL; - fileHeader = _XcursorFileHeaderCreate (head.ntoc); - if (!fileHeader) - return NULL; - fileHeader->magic = head.magic; - fileHeader->header = head.header; - fileHeader->version = head.version; - fileHeader->ntoc = head.ntoc; - for (n = 0; n < fileHeader->ntoc; n++) - { - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type)) - break; - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype)) - break; - if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position)) - break; - } - if (n != fileHeader->ntoc) - { - _XcursorFileHeaderDestroy (fileHeader); - return NULL; - } - return fileHeader; -} - -static XcursorBool -_XcursorSeekToToc (XcursorFile *file, - XcursorFileHeader *fileHeader, - int toc) -{ - if (!file || !fileHeader || \ - (*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET) == EOF) - return XcursorFalse; - return XcursorTrue; -} - -static XcursorBool -_XcursorFileReadChunkHeader (XcursorFile *file, - XcursorFileHeader *fileHeader, - int toc, - XcursorChunkHeader *chunkHeader) -{ - if (!file || !fileHeader || !chunkHeader) - return XcursorFalse; - if (!_XcursorSeekToToc (file, fileHeader, toc)) - return XcursorFalse; - if (!_XcursorReadUInt (file, &chunkHeader->header)) - return XcursorFalse; - if (!_XcursorReadUInt (file, &chunkHeader->type)) - return XcursorFalse; - if (!_XcursorReadUInt (file, &chunkHeader->subtype)) - return XcursorFalse; - if (!_XcursorReadUInt (file, &chunkHeader->version)) - return XcursorFalse; - /* sanity check */ - if (chunkHeader->type != fileHeader->tocs[toc].type || - chunkHeader->subtype != fileHeader->tocs[toc].subtype) - return XcursorFalse; - return XcursorTrue; -} - -#define dist(a,b) ((a) > (b) ? (a) - (b) : (b) - (a)) - -static XcursorDim -_XcursorFindBestSize (XcursorFileHeader *fileHeader, - XcursorDim size, - int *nsizesp) -{ - unsigned int n; - int nsizes = 0; - XcursorDim bestSize = 0; - XcursorDim thisSize; - - if (!fileHeader || !nsizesp) - return 0; - - for (n = 0; n < fileHeader->ntoc; n++) - { - if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE) - continue; - thisSize = fileHeader->tocs[n].subtype; - if (!bestSize || dist (thisSize, size) < dist (bestSize, size)) - { - bestSize = thisSize; - nsizes = 1; - } - else if (thisSize == bestSize) - nsizes++; - } - *nsizesp = nsizes; - return bestSize; -} - -static int -_XcursorFindImageToc (XcursorFileHeader *fileHeader, - XcursorDim size, - int count) -{ - unsigned int toc; - XcursorDim thisSize; - - if (!fileHeader) - return 0; - - for (toc = 0; toc < fileHeader->ntoc; toc++) - { - if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE) - continue; - thisSize = fileHeader->tocs[toc].subtype; - if (thisSize != size) - continue; - if (!count) - break; - count--; - } - if (toc == fileHeader->ntoc) - return -1; - return toc; -} - -static XcursorImage * -_XcursorReadImage (XcursorFile *file, - XcursorFileHeader *fileHeader, - int toc) -{ - XcursorChunkHeader chunkHeader; - XcursorImage head; - XcursorImage *image; - int n; - XcursorPixel *p; - - if (!file || !fileHeader) - return NULL; - - if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader)) - return NULL; - if (!_XcursorReadUInt (file, &head.width)) - return NULL; - if (!_XcursorReadUInt (file, &head.height)) - return NULL; - if (!_XcursorReadUInt (file, &head.xhot)) - return NULL; - if (!_XcursorReadUInt (file, &head.yhot)) - return NULL; - if (!_XcursorReadUInt (file, &head.delay)) - return NULL; - /* sanity check data */ - if (head.width > XCURSOR_IMAGE_MAX_SIZE || - head.height > XCURSOR_IMAGE_MAX_SIZE) - return NULL; - if (head.width == 0 || head.height == 0) - return NULL; - if (head.xhot > head.width || head.yhot > head.height) - return NULL; - - /* Create the image and initialize it */ - image = XcursorImageCreate (head.width, head.height); - if (image == NULL) - return NULL; - if (chunkHeader.version < image->version) - image->version = chunkHeader.version; - image->size = chunkHeader.subtype; - image->xhot = head.xhot; - image->yhot = head.yhot; - image->delay = head.delay; - n = image->width * image->height; - p = image->pixels; - while (n--) - { - if (!_XcursorReadUInt (file, p)) - { - XcursorImageDestroy (image); - return NULL; - } - p++; - } - return image; -} - -static XcursorImages * -XcursorXcFileLoadImages (XcursorFile *file, int size) -{ - XcursorFileHeader *fileHeader; - XcursorDim bestSize; - int nsize; - XcursorImages *images; - int n; - int toc; - - if (!file || size < 0) - return NULL; - fileHeader = _XcursorReadFileHeader (file); - if (!fileHeader) - return NULL; - bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize); - if (!bestSize) - { - _XcursorFileHeaderDestroy (fileHeader); - return NULL; - } - images = XcursorImagesCreate (nsize); - if (!images) - { - _XcursorFileHeaderDestroy (fileHeader); - return NULL; - } - for (n = 0; n < nsize; n++) - { - toc = _XcursorFindImageToc (fileHeader, bestSize, n); - if (toc < 0) - break; - images->images[images->nimage] = _XcursorReadImage (file, fileHeader, - toc); - if (!images->images[images->nimage]) - break; - images->nimage++; - } - _XcursorFileHeaderDestroy (fileHeader); - if (images->nimage != nsize) - { - XcursorImagesDestroy (images); - images = NULL; - } - return images; -} - -static int -_XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len) -{ - FILE *f = file->closure; - return fread (buf, 1, len, f); -} - -static int -_XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len) -{ - FILE *f = file->closure; - return fwrite (buf, 1, len, f); -} - -static int -_XcursorStdioFileSeek (XcursorFile *file, long offset, int whence) -{ - FILE *f = file->closure; - return fseek (f, offset, whence); -} - -static void -_XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file) -{ - file->closure = stdfile; - file->read = _XcursorStdioFileRead; - file->write = _XcursorStdioFileWrite; - file->seek = _XcursorStdioFileSeek; -} - -static XcursorImages * -XcursorFileLoadImages (FILE *file, int size) -{ - XcursorFile f; - - if (!file) - return NULL; - - _XcursorStdioFileInitialize (file, &f); - return XcursorXcFileLoadImages (&f, size); -} - -XcursorImages * -xcursor_load_images (const char *path, int size) -{ - FILE *f; - XcursorImages *images; - - f = fopen (path, "r"); - if (!f) - return NULL; - - images = XcursorFileLoadImages (f, size); - fclose (f); - - return images; -} - -void -xcursor_images_destroy (XcursorImages *images) -{ - XcursorImagesDestroy (images); -} diff --git a/gdk/wayland/cursor/xcursor.h b/gdk/wayland/cursor/xcursor.h deleted file mode 100644 index 34feb0cf36..0000000000 --- a/gdk/wayland/cursor/xcursor.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright © 2002 Keith Packard - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef XCURSOR_H -#define XCURSOR_H - -typedef int XcursorBool; -typedef unsigned int XcursorUInt; - -typedef XcursorUInt XcursorDim; -typedef XcursorUInt XcursorPixel; - -typedef struct _XcursorImage { - XcursorUInt version; /* version of the image data */ - XcursorDim size; /* nominal size for matching */ - XcursorDim width; /* actual width */ - XcursorDim height; /* actual height */ - XcursorDim xhot; /* hot spot x (must be inside image) */ - XcursorDim yhot; /* hot spot y (must be inside image) */ - XcursorUInt delay; /* animation delay to next frame (ms) */ - XcursorPixel *pixels; /* pointer to pixels */ -} XcursorImage; - -/* - * Other data structures exposed by the library API - */ -typedef struct _XcursorImages { - int nimage; /* number of images */ - XcursorImage **images; /* array of XcursorImage pointers */ - char *name; /* name used to load images */ -} XcursorImages; - -void -xcursor_images_destroy (XcursorImages *images); - -XcursorImages * -xcursor_load_images (const char *path, int size); - -#endif diff --git a/gdk/wayland/gdkcursor-wayland.c b/gdk/wayland/gdkcursor-wayland.c index 908f7621fa..c3e97286e1 100644 --- a/gdk/wayland/gdkcursor-wayland.c +++ b/gdk/wayland/gdkcursor-wayland.c @@ -34,7 +34,7 @@ #include "gdkwayland.h" #include -#include +#include #define GDK_TYPE_WAYLAND_CURSOR (_gdk_wayland_cursor_get_type ()) #define GDK_WAYLAND_CURSOR(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_WAYLAND_CURSOR, GdkWaylandCursor)) @@ -149,8 +149,9 @@ _gdk_wayland_cursor_update (GdkWaylandDisplay *display_wayland, if (cursor->name == NULL) return FALSE; - theme = _gdk_wayland_display_get_cursor_theme (display_wayland); - c = wl_cursor_theme_get_cursor (theme, cursor->name, cursor->scale); + theme = _gdk_wayland_display_get_scaled_cursor_theme (display_wayland, + cursor->scale); + c = wl_cursor_theme_get_cursor (theme, cursor->name); if (!c) { const char *fallback; @@ -158,9 +159,9 @@ _gdk_wayland_cursor_update (GdkWaylandDisplay *display_wayland, fallback = name_fallback (cursor->name); if (fallback) { - c = wl_cursor_theme_get_cursor (theme, fallback, cursor->scale); + c = wl_cursor_theme_get_cursor (theme, name_fallback (cursor->name)); if (!c) - c = wl_cursor_theme_get_cursor (theme, "left_ptr", cursor->scale); + c = wl_cursor_theme_get_cursor (theme, "left_ptr"); } } @@ -222,6 +223,7 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor, if (wayland_cursor->wl_cursor) { struct wl_cursor_image *image; + int cursor_scale; if (image_index >= wayland_cursor->wl_cursor->image_count) { @@ -233,12 +235,22 @@ _gdk_wayland_cursor_get_buffer (GdkCursor *cursor, image = wayland_cursor->wl_cursor->images[image_index]; - *hotspot_x = image->hotspot_x / wayland_cursor->scale; - *hotspot_y = image->hotspot_y / wayland_cursor->scale; + cursor_scale = wayland_cursor->scale; + if ((image->width % cursor_scale != 0) || + (image->height % cursor_scale != 0)) + { + g_warning (G_STRLOC " cursor image size (%dx%d) not an integer" + "multiple of scale (%d)", image->width, image->height, + cursor_scale); + cursor_scale = 1; + } - *w = image->width / wayland_cursor->scale; - *h = image->height / wayland_cursor->scale; - *scale = wayland_cursor->scale; + *hotspot_x = image->hotspot_x / cursor_scale; + *hotspot_y = image->hotspot_y / cursor_scale; + + *w = image->width / cursor_scale; + *h = image->height / cursor_scale; + *scale = cursor_scale; return wl_cursor_image_get_buffer (image); } @@ -304,6 +316,12 @@ _gdk_wayland_cursor_set_scale (GdkCursor *cursor, GDK_WAYLAND_DISPLAY (gdk_cursor_get_display (cursor)); GdkWaylandCursor *wayland_cursor = GDK_WAYLAND_CURSOR (cursor); + if (scale > GDK_WAYLAND_MAX_THEME_SCALE) + { + g_warning (G_STRLOC ": cursor theme size %u too large", scale); + scale = GDK_WAYLAND_MAX_THEME_SCALE; + } + if (wayland_cursor->scale == scale) return; diff --git a/gdk/wayland/gdkdisplay-wayland.c b/gdk/wayland/gdkdisplay-wayland.c index ddf2bf312c..55c0388ec6 100644 --- a/gdk/wayland/gdkdisplay-wayland.c +++ b/gdk/wayland/gdkdisplay-wayland.c @@ -720,6 +720,7 @@ static void gdk_wayland_display_finalize (GObject *object) { GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY (object); + guint i; _gdk_wayland_display_finalize_cursors (display_wayland); @@ -729,10 +730,13 @@ gdk_wayland_display_finalize (GObject *object) g_free (display_wayland->cursor_theme_name); xkb_context_unref (display_wayland->xkb_context); - if (display_wayland->cursor_theme) + for (i = 0; i < GDK_WAYLAND_THEME_SCALES_COUNT; i++) { - wl_cursor_theme_destroy (display_wayland->cursor_theme); - display_wayland->cursor_theme = NULL; + if (display_wayland->scaled_cursor_themes[i]) + { + wl_cursor_theme_destroy (display_wayland->scaled_cursor_themes[i]); + display_wayland->scaled_cursor_themes[i] = NULL; + } } g_ptr_array_free (display_wayland->monitors, TRUE); @@ -1112,55 +1116,6 @@ gdk_wayland_display_init (GdkWaylandDisplay *display) display->monitors = g_ptr_array_new_with_free_func (g_object_unref); } -static struct wl_cursor_theme * -try_load_theme (GdkWaylandDisplay *display_wayland, - const char *dir, - gboolean dotdir, - const char *name, - int size) -{ - struct wl_cursor_theme *theme = NULL; - char *path; - - path = g_build_filename (dir, dotdir ? ".icons" : "icons", name, "cursors", NULL); - - if (g_file_test (path, G_FILE_TEST_IS_DIR)) - theme = wl_cursor_theme_create (path, size, display_wayland->shm); - - g_free (path); - - return theme; -} - -static struct wl_cursor_theme * -get_cursor_theme (GdkWaylandDisplay *display_wayland, - const char *name, - int size) -{ - const char * const *xdg_data_dirs; - struct wl_cursor_theme *theme = NULL; - int i; - - theme = try_load_theme (display_wayland, g_get_user_data_dir (), FALSE, name, size); - if (theme) - return theme; - - theme = try_load_theme (display_wayland, g_get_home_dir (), TRUE, name, size); - if (theme) - return theme; - - xdg_data_dirs = g_get_system_data_dirs (); - for (i = 0; xdg_data_dirs[i]; i++) - { - theme = try_load_theme (display_wayland, xdg_data_dirs[i], FALSE, name, size); - if (theme) - return theme; - } - - /* This may fall back to builtin cursors */ - return wl_cursor_theme_create ("/usr/share/icons/default/cursors", size, display_wayland->shm); -} - void gdk_wayland_display_set_cursor_theme (GdkDisplay *display, const gchar *name, @@ -1168,6 +1123,7 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display, { GdkWaylandDisplay *display_wayland = GDK_WAYLAND_DISPLAY(display); struct wl_cursor_theme *theme; + int i; g_assert (display_wayland); g_assert (display_wayland->shm); @@ -1176,21 +1132,22 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display, display_wayland->cursor_theme_size == size) return; - theme = get_cursor_theme (display_wayland, name, size); + theme = wl_cursor_theme_load (name, size, display_wayland->shm); if (theme == NULL) { g_warning ("Failed to load cursor theme %s", name); return; } - if (display_wayland->cursor_theme) + for (i = 0; i < GDK_WAYLAND_THEME_SCALES_COUNT; i++) { - wl_cursor_theme_destroy (display_wayland->cursor_theme); - display_wayland->cursor_theme = NULL; + if (display_wayland->scaled_cursor_themes[i]) + { + wl_cursor_theme_destroy (display_wayland->scaled_cursor_themes[i]); + display_wayland->scaled_cursor_themes[i] = NULL; + } } - - display_wayland->cursor_theme = theme; - + display_wayland->scaled_cursor_themes[0] = theme; if (display_wayland->cursor_theme_name != NULL) g_free (display_wayland->cursor_theme_name); display_wayland->cursor_theme_name = g_strdup (name); @@ -1200,11 +1157,31 @@ gdk_wayland_display_set_cursor_theme (GdkDisplay *display, } struct wl_cursor_theme * -_gdk_wayland_display_get_cursor_theme (GdkWaylandDisplay *display_wayland) +_gdk_wayland_display_get_scaled_cursor_theme (GdkWaylandDisplay *display_wayland, + guint scale) { - g_assert (display_wayland->cursor_theme_name); + struct wl_cursor_theme *theme; - return display_wayland->cursor_theme; + g_assert (display_wayland->cursor_theme_name); + g_assert (scale <= GDK_WAYLAND_MAX_THEME_SCALE); + g_assert (scale >= 1); + + theme = display_wayland->scaled_cursor_themes[scale - 1]; + if (!theme) + { + theme = wl_cursor_theme_load (display_wayland->cursor_theme_name, + display_wayland->cursor_theme_size * scale, + display_wayland->shm); + if (theme == NULL) + { + g_warning ("Failed to load cursor theme %s with scale %u", + display_wayland->cursor_theme_name, scale); + return NULL; + } + display_wayland->scaled_cursor_themes[scale - 1] = theme; + } + + return theme; } static void diff --git a/gdk/wayland/gdkdisplay-wayland.h b/gdk/wayland/gdkdisplay-wayland.h index 5ac80ee2e6..925476a781 100644 --- a/gdk/wayland/gdkdisplay-wayland.h +++ b/gdk/wayland/gdkdisplay-wayland.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #ifdef HAVE_XDG_ACTIVATION #include #endif -#include #include #include @@ -52,6 +52,9 @@ G_BEGIN_DECLS +#define GDK_WAYLAND_MAX_THEME_SCALE 4 +#define GDK_WAYLAND_THEME_SCALES_COUNT GDK_WAYLAND_MAX_THEME_SCALE + #define GDK_ZWP_POINTER_GESTURES_V1_VERSION 1 typedef struct _GdkWaylandSelection GdkWaylandSelection; @@ -116,7 +119,7 @@ struct _GdkWaylandDisplay GList *current_popups; - struct wl_cursor_theme *cursor_theme; + struct wl_cursor_theme *scaled_cursor_themes[GDK_WAYLAND_THEME_SCALES_COUNT]; gchar *cursor_theme_name; int cursor_theme_size; GHashTable *cursor_cache; diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 102c945e26..5173873381 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -60,7 +60,8 @@ void _gdk_wayland_display_init_cursors (GdkWaylandDisplay *display); void _gdk_wayland_display_finalize_cursors (GdkWaylandDisplay *display); void _gdk_wayland_display_update_cursors (GdkWaylandDisplay *display); -struct wl_cursor_theme * _gdk_wayland_display_get_cursor_theme (GdkWaylandDisplay *display_wayland); +struct wl_cursor_theme * _gdk_wayland_display_get_scaled_cursor_theme (GdkWaylandDisplay *display_wayland, + guint scale); GdkCursor *_gdk_wayland_display_get_cursor_for_type (GdkDisplay *display, GdkCursorType cursor_type); diff --git a/gdk/wayland/meson.build b/gdk/wayland/meson.build index d9ed7da3fc..ad5dfe5591 100644 --- a/gdk/wayland/meson.build +++ b/gdk/wayland/meson.build @@ -1,5 +1,3 @@ -subdir('cursor') - gdk_wayland_sources = files( 'gdkapplaunchcontext-wayland.c', 'gdkcursor-wayland.c', @@ -33,6 +31,7 @@ gdk_wayland_deps = [ xkbdep, wlclientdep, wlprotocolsdep, + wlcursordep, wlegldep, ] @@ -113,5 +112,4 @@ libgdk_wayland = static_library('gdk-wayland', '-DG_LOG_DOMAIN="Gdk"', ] + common_cflags, link_args: common_ldflags, - link_with: [libwayland_cursor, ], dependencies: [ gdk_deps, gdk_wayland_deps, ]) diff --git a/meson.build b/meson.build index 8726822897..373c5f689f 100644 --- a/meson.build +++ b/meson.build @@ -537,6 +537,7 @@ wayland_pkgs = [] if wayland_enabled wlclientdep = dependency('wayland-client', version: wayland_req) wlprotocolsdep = dependency('wayland-protocols', version: wayland_proto_req) + wlcursordep = dependency('wayland-cursor', version: wayland_req) wlegldep = dependency('wayland-egl') backend_immodules += ['wayland'] @@ -545,6 +546,7 @@ if wayland_enabled wayland_pkgs = [ 'wayland-client', wayland_req, 'xkbcommon', xkbcommon_req, + 'wayland-cursor', wayland_req, 'wayland-egl', ] endif