Commit 775002c6 authored by Ander Conselvan de Oliveira's avatar Ander Conselvan de Oliveira Committed by Kristian H. Kristensen

Introduce libwayland-cursor, a cursor helper library

The purpose of this library is to be the equivalent of libXcursor in
the X world. This library is compatible with X cursor themes and loads
them directly into an shm pool making it easy for the clients to get
buffer for each cursor image.

The code for handling the X cursor theme was taken from libXcursor. The
files cursor/xcursor.[ch] are a stripped down version of that library
containing only the interfaces necessary for implementing the wayland
counterpart.
parent ff0d7456
SUBDIRS = src protocol doc tests
SUBDIRS = src protocol doc tests cursor
ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
......
......@@ -78,6 +78,8 @@ AM_CONDITIONAL([HAVE_PUBLICAN], [test "x$PUBLICAN" != "x"])
AC_CONFIG_FILES([Makefile
wayland-scanner.m4
cursor/Makefile
cursor/wayland-cursor.pc
doc/Makefile
doc/Wayland/Makefile
src/Makefile
......
lib_LTLIBRARIES = libwayland-cursor.la
include_HEADERS = wayland-cursor.h
libwayland_cursor_la_SOURCES = \
wayland-cursor.c \
xcursor.c \
xcursor.h
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = wayland-cursor.pc
AM_CFLAGS = $(GCC_CFLAGS) -I../src
LDADD = $(top_builddir)/src/libwayland-client.la
/*
* Copyright © 2012 Intel Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#include "xcursor.h"
#include "wayland-cursor.h"
#include "wayland-client.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
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;
char filename[] = "/tmp/wayland-shm-XXXXXX";
pool = malloc(sizeof *pool);
if (!pool)
return NULL;
pool->fd = mkstemp(filename);
if (pool->fd < 0)
return NULL;
if (ftruncate(pool->fd, size) < 0) {
close(pool->fd);
return NULL;
}
pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
pool->fd, 0);
unlink(filename);
if (pool->data == MAP_FAILED) {
close(pool->fd);
return NULL;
}
pool->pool = wl_shm_create_pool(shm, pool->fd, size);
pool->size = size;
pool->used = 0;
return pool;
}
static int
shm_pool_resize(struct shm_pool *pool, int size)
{
if (ftruncate(pool->fd, size) < 0)
return 0;
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);
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);
free(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;
struct wl_shm *shm;
struct shm_pool *pool;
char *name;
int size;
};
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 */
};
/** 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.
*/
WL_EXPORT 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->name);
free(cursor);
}
static struct wl_cursor *
load_cursor(struct wl_cursor_theme *theme, const char *name)
{
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);
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);
for (i = 0; i < images->nimage; i++) {
image = malloc(sizeof *image);
cursor->images[i] = (struct wl_cursor_image *) image;
image->theme = theme;
image->buffer = NULL;
image->image.width = images->images[i]->width;
image->image.height = images->images[i]->height;
image->image.hotspot_x = images->images[i]->xhot;
image->image.hotspot_y = images->images[i]->yhot;
image->image.delay = images->images[i]->delay;
/* copy pixels to shm pool */
size = image->image.width * image->image.height * 4;
image->offset = shm_pool_allocate(theme->pool, size);
memcpy(theme->pool->data + image->offset,
images->images[i]->pixels, size);
}
XcursorImagesDestroy(images);
return 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.
*/
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)
return NULL;
if (!name)
name = "default";
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->pool =
shm_pool_create(shm, theme->cursor_count * size * size * 4);
for (i = 0; i < theme->cursor_count; i++)
theme->cursors[i] = load_cursor(theme, cursor_names[i]);
return theme;
}
/** Destroys a cursor theme object
*
* \param theme The cursor theme to be destroyed
*/
WL_EXPORT 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);
}
/** Get the cursor for a given type from a cursor theme
*
* \param theme The cursor theme
* \patam type The desired cursor type
* \return The theme's cursor of the given type or %NULL if there is no
* such cursor
*/
WL_EXPORT struct wl_cursor *
wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
enum wl_cursor_type type)
{
if (type < theme->cursor_count)
return theme->cursors[type];
return NULL;
}
/** 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
*/
WL_EXPORT struct wl_cursor *
wl_cursor_theme_get_cursor_by_name(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;
}
/*
* Copyright © 2012 Intel Corporation
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that copyright
* notice and this permission notice appear in supporting documentation, and
* that the name of the copyright holders not be used in advertising or
* publicity pertaining to distribution of the software without specific,
* written prior permission. The copyright holders make no representations
* about the suitability of this software for any purpose. It is provided "as
* is" without express or implied warranty.
*
* THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
* OF THIS SOFTWARE.
*/
#ifndef WAYLAND_CURSOR_H
#define WAYLAND_CURSOR_H
#include <stdint.h>
enum wl_cursor_type {
WL_CURSOR_BOTTOM_LEFT,
WL_CURSOR_BOTTOM_RIGHT,
WL_CURSOR_BOTTOM,
WL_CURSOR_DRAGGING,
WL_CURSOR_LEFT_PTR,
WL_CURSOR_LEFT,
WL_CURSOR_RIGHT,
WL_CURSOR_TOP_LEFT,
WL_CURSOR_TOP_RIGHT,
WL_CURSOR_TOP,
WL_CURSOR_IBEAM,
WL_CURSOR_HAND1,
};
struct wl_cursor_theme;
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;
};
struct wl_shm;
struct wl_cursor_theme *
wl_cursor_theme_load(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,
enum wl_cursor_type type);
struct wl_cursor *
wl_cursor_theme_get_cursor_by_name(struct wl_cursor_theme *theme,
const char *name);
struct wl_buffer *
wl_cursor_image_get_buffer(struct wl_cursor_image *image);
#endif
prefix=@prefix@
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: Wayland Cursor
Description: Wayland cursor helper library
Version: @WAYLAND_VERSION@
Cflags: -I${includedir}
Libs: -L${libdir} -lwayland-cursor
This diff is collapsed.
/*
* Copyright © 2002 Keith Packard
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation, and that the name of Keith Packard not be used in
* advertising or publicity pertaining to distribution of the software without
* specific, written prior permission. Keith Packard makes no
* representations about the suitability of this software for any purpose. It
* is provided "as is" without express or implied warranty.
*
* KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
* EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
* DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS 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;
XcursorImages *
XcursorLibraryLoadImages (const char *file, const char *theme, int size);
void
XcursorImagesDestroy (XcursorImages *images);
#endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment