Home | History | Annotate | Download | only in cursor
      1 /*
      2  * Copyright  2012 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining
      5  * a copy of this software and associated documentation files (the
      6  * "Software"), to deal in the Software without restriction, including
      7  * without limitation the rights to use, copy, modify, merge, publish,
      8  * distribute, sublicense, and/or sell copies of the Software, and to
      9  * permit persons to whom the Software is furnished to do so, subject to
     10  * the following conditions:
     11  *
     12  * The above copyright notice and this permission notice (including the
     13  * next paragraph) shall be included in all copies or substantial
     14  * portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     17  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     18  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
     19  * NONINFRINGEMENT.  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
     20  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
     21  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     23  * SOFTWARE.
     24  */
     25 
     26 #include "config.h"
     27 #include "xcursor.h"
     28 #include "wayland-cursor.h"
     29 #include "wayland-client.h"
     30 #include <stdio.h>
     31 #include <stdlib.h>
     32 #include <stdint.h>
     33 #include <string.h>
     34 #include <unistd.h>
     35 #include <sys/mman.h>
     36 #include <fcntl.h>
     37 #include <errno.h>
     38 
     39 #include "os-compatibility.h"
     40 
     41 #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
     42 
     43 struct shm_pool {
     44 	struct wl_shm_pool *pool;
     45 	int fd;
     46 	unsigned int size;
     47 	unsigned int used;
     48 	char *data;
     49 };
     50 
     51 static struct shm_pool *
     52 shm_pool_create(struct wl_shm *shm, int size)
     53 {
     54 	struct shm_pool *pool;
     55 
     56 	pool = malloc(sizeof *pool);
     57 	if (!pool)
     58 		return NULL;
     59 
     60 	pool->fd = os_create_anonymous_file(size);
     61 	if (pool->fd < 0)
     62 		goto err_free;
     63 
     64 	pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
     65 			  pool->fd, 0);
     66 
     67 	if (pool->data == MAP_FAILED)
     68 		goto err_close;
     69 
     70 	pool->pool = wl_shm_create_pool(shm, pool->fd, size);
     71 	pool->size = size;
     72 	pool->used = 0;
     73 
     74 	return pool;
     75 
     76 err_close:
     77 	close(pool->fd);
     78 err_free:
     79 	free(pool);
     80 	return NULL;
     81 }
     82 
     83 static int
     84 shm_pool_resize(struct shm_pool *pool, int size)
     85 {
     86 	if (ftruncate(pool->fd, size) < 0)
     87 		return 0;
     88 
     89 #ifdef HAVE_POSIX_FALLOCATE
     90 	errno = posix_fallocate(pool->fd, 0, size);
     91 	if (errno != 0)
     92 		return 0;
     93 #endif
     94 
     95 	wl_shm_pool_resize(pool->pool, size);
     96 
     97 	munmap(pool->data, pool->size);
     98 
     99 	pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
    100 			  pool->fd, 0);
    101 	if (pool->data == (void *)-1)
    102 		return 0;
    103 	pool->size = size;
    104 
    105 	return 1;
    106 }
    107 
    108 static int
    109 shm_pool_allocate(struct shm_pool *pool, int size)
    110 {
    111 	int offset;
    112 
    113 	if (pool->used + size > pool->size)
    114 		if (!shm_pool_resize(pool, 2 * pool->size + size))
    115 			return -1;
    116 
    117 	offset = pool->used;
    118 	pool->used += size;
    119 
    120 	return offset;
    121 }
    122 
    123 static void
    124 shm_pool_destroy(struct shm_pool *pool)
    125 {
    126 	munmap(pool->data, pool->size);
    127 	wl_shm_pool_destroy(pool->pool);
    128 	close(pool->fd);
    129 	free(pool);
    130 }
    131 
    132 
    133 struct wl_cursor_theme {
    134 	unsigned int cursor_count;
    135 	struct wl_cursor **cursors;
    136 	struct wl_shm *shm;
    137 	struct shm_pool *pool;
    138 	char *name;
    139 	int size;
    140 };
    141 
    142 struct cursor_image {
    143 	struct wl_cursor_image image;
    144 	struct wl_cursor_theme *theme;
    145 	struct wl_buffer *buffer;
    146 	int offset; /* data offset of this image in the shm pool */
    147 };
    148 
    149 struct cursor {
    150 	struct wl_cursor cursor;
    151 	uint32_t total_delay; /* length of the animation in ms */
    152 };
    153 
    154 /** Get an shm buffer for a cursor image
    155  *
    156  * \param image The cursor image
    157  * \return An shm buffer for the cursor image. The user should not destroy
    158  * the returned buffer.
    159  */
    160 WL_EXPORT struct wl_buffer *
    161 wl_cursor_image_get_buffer(struct wl_cursor_image *_img)
    162 {
    163 	struct cursor_image *image = (struct cursor_image *) _img;
    164 	struct wl_cursor_theme *theme = image->theme;
    165 
    166 	if (!image->buffer) {
    167 		image->buffer =
    168 			wl_shm_pool_create_buffer(theme->pool->pool,
    169 						  image->offset,
    170 						  _img->width, _img->height,
    171 						  _img->width * 4,
    172 						  WL_SHM_FORMAT_ARGB8888);
    173 	};
    174 
    175 	return image->buffer;
    176 }
    177 
    178 static void
    179 wl_cursor_image_destroy(struct wl_cursor_image *_img)
    180 {
    181 	struct cursor_image *image = (struct cursor_image *) _img;
    182 
    183 	if (image->buffer)
    184 		wl_buffer_destroy(image->buffer);
    185 
    186 	free(image);
    187 }
    188 
    189 static void
    190 wl_cursor_destroy(struct wl_cursor *cursor)
    191 {
    192 	unsigned int i;
    193 
    194 	for (i = 0; i < cursor->image_count; i++)
    195 		wl_cursor_image_destroy(cursor->images[i]);
    196 
    197 	free(cursor->images);
    198 	free(cursor->name);
    199 	free(cursor);
    200 }
    201 
    202 #include "cursor-data.h"
    203 
    204 static struct wl_cursor *
    205 wl_cursor_create_from_data(struct cursor_metadata *metadata,
    206 			   struct wl_cursor_theme *theme)
    207 {
    208 	struct cursor *cursor;
    209 	struct cursor_image *image;
    210 	int size;
    211 
    212 	cursor = malloc(sizeof *cursor);
    213 	if (!cursor)
    214 		return NULL;
    215 
    216 	cursor->cursor.image_count = 1;
    217 	cursor->cursor.images = malloc(sizeof *cursor->cursor.images);
    218 	if (!cursor->cursor.images)
    219 		goto err_free_cursor;
    220 
    221 	cursor->cursor.name = strdup(metadata->name);
    222 	cursor->total_delay = 0;
    223 
    224 	image = malloc(sizeof *image);
    225 	if (!image)
    226 		goto err_free_images;
    227 
    228 	cursor->cursor.images[0] = (struct wl_cursor_image *) image;
    229 	image->theme = theme;
    230 	image->buffer = NULL;
    231 	image->image.width = metadata->width;
    232 	image->image.height = metadata->height;
    233 	image->image.hotspot_x = metadata->hotspot_x;
    234 	image->image.hotspot_y = metadata->hotspot_y;
    235 	image->image.delay = 0;
    236 
    237 	size = metadata->width * metadata->height * sizeof(uint32_t);
    238 	image->offset = shm_pool_allocate(theme->pool, size);
    239 
    240 	if (image->offset < 0)
    241 		goto err_free_image;
    242 
    243 	memcpy(theme->pool->data + image->offset,
    244 	       cursor_data + metadata->offset, size);
    245 
    246 	return &cursor->cursor;
    247 
    248 err_free_image:
    249 	free(image);
    250 
    251 err_free_images:
    252 	free(cursor->cursor.name);
    253 	free(cursor->cursor.images);
    254 
    255 err_free_cursor:
    256 	free(cursor);
    257 	return NULL;
    258 }
    259 
    260 static void
    261 load_default_theme(struct wl_cursor_theme *theme)
    262 {
    263 	uint32_t i;
    264 
    265 	free(theme->name);
    266 	theme->name = strdup("default");
    267 
    268 	theme->cursor_count = ARRAY_LENGTH(cursor_metadata);
    269 	theme->cursors = malloc(theme->cursor_count * sizeof(*theme->cursors));
    270 
    271 	if (theme->cursors == NULL) {
    272 		theme->cursor_count = 0;
    273 		return;
    274 	}
    275 
    276 	for (i = 0; i < theme->cursor_count; ++i) {
    277 		theme->cursors[i] =
    278 			wl_cursor_create_from_data(&cursor_metadata[i], theme);
    279 
    280 		if (theme->cursors[i] == NULL)
    281 			break;
    282 	}
    283 	theme->cursor_count = i;
    284 }
    285 
    286 static struct wl_cursor *
    287 wl_cursor_create_from_xcursor_images(XcursorImages *images,
    288 				     struct wl_cursor_theme *theme)
    289 {
    290 	struct cursor *cursor;
    291 	struct cursor_image *image;
    292 	int i, size;
    293 
    294 	cursor = malloc(sizeof *cursor);
    295 	if (!cursor)
    296 		return NULL;
    297 
    298 	cursor->cursor.images =
    299 		malloc(images->nimage * sizeof cursor->cursor.images[0]);
    300 	if (!cursor->cursor.images) {
    301 		free(cursor);
    302 		return NULL;
    303 	}
    304 
    305 	cursor->cursor.name = strdup(images->name);
    306 	cursor->total_delay = 0;
    307 
    308 	for (i = 0; i < images->nimage; i++) {
    309 		image = malloc(sizeof *image);
    310 		if (image == NULL)
    311 			break;
    312 
    313 		image->theme = theme;
    314 		image->buffer = NULL;
    315 
    316 		image->image.width = images->images[i]->width;
    317 		image->image.height = images->images[i]->height;
    318 		image->image.hotspot_x = images->images[i]->xhot;
    319 		image->image.hotspot_y = images->images[i]->yhot;
    320 		image->image.delay = images->images[i]->delay;
    321 
    322 		size = image->image.width * image->image.height * 4;
    323 		image->offset = shm_pool_allocate(theme->pool, size);
    324 		if (image->offset < 0) {
    325 			free(image);
    326 			break;
    327 		}
    328 
    329 		/* copy pixels to shm pool */
    330 		memcpy(theme->pool->data + image->offset,
    331 		       images->images[i]->pixels, size);
    332 		cursor->total_delay += image->image.delay;
    333 		cursor->cursor.images[i] = (struct wl_cursor_image *) image;
    334 	}
    335 	cursor->cursor.image_count = i;
    336 
    337 	if (cursor->cursor.image_count == 0) {
    338 		free(cursor->cursor.name);
    339 		free(cursor->cursor.images);
    340 		free(cursor);
    341 		return NULL;
    342 	}
    343 
    344 	return &cursor->cursor;
    345 }
    346 
    347 static void
    348 load_callback(XcursorImages *images, void *data)
    349 {
    350 	struct wl_cursor_theme *theme = data;
    351 	struct wl_cursor *cursor;
    352 
    353 	if (wl_cursor_theme_get_cursor(theme, images->name)) {
    354 		XcursorImagesDestroy(images);
    355 		return;
    356 	}
    357 
    358 	cursor = wl_cursor_create_from_xcursor_images(images, theme);
    359 
    360 	if (cursor) {
    361 		theme->cursor_count++;
    362 		theme->cursors =
    363 			realloc(theme->cursors,
    364 				theme->cursor_count * sizeof theme->cursors[0]);
    365 
    366 		if (theme->cursors == NULL) {
    367 			theme->cursor_count--;
    368 			free(cursor);
    369 		} else {
    370 			theme->cursors[theme->cursor_count - 1] = cursor;
    371 		}
    372 	}
    373 
    374 	XcursorImagesDestroy(images);
    375 }
    376 
    377 /** Load a cursor theme to memory shared with the compositor
    378  *
    379  * \param name The name of the cursor theme to load. If %NULL, the default
    380  * theme will be loaded.
    381  * \param size Desired size of the cursor images.
    382  * \param shm The compositor's shm interface.
    383  *
    384  * \return An object representing the theme that should be destroyed with
    385  * wl_cursor_theme_destroy() or %NULL on error. If no theme with the given
    386  * name exists, a default theme will be loaded.
    387  */
    388 WL_EXPORT struct wl_cursor_theme *
    389 wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
    390 {
    391 	struct wl_cursor_theme *theme;
    392 
    393 	theme = malloc(sizeof *theme);
    394 	if (!theme)
    395 		return NULL;
    396 
    397 	if (!name)
    398 		name = "default";
    399 
    400 	theme->name = strdup(name);
    401 	if (!theme->name)
    402 		goto out_error_name;
    403 	theme->size = size;
    404 	theme->cursor_count = 0;
    405 	theme->cursors = NULL;
    406 
    407 	theme->pool = shm_pool_create(shm, size * size * 4);
    408 	if (!theme->pool)
    409 		goto out_error_pool;
    410 
    411 	xcursor_load_theme(name, size, load_callback, theme);
    412 
    413 	if (theme->cursor_count == 0)
    414 		load_default_theme(theme);
    415 
    416 	return theme;
    417 
    418 out_error_pool:
    419 	free(theme->name);
    420 out_error_name:
    421 	free(theme);
    422 	return NULL;
    423 }
    424 
    425 /** Destroys a cursor theme object
    426  *
    427  * \param theme The cursor theme to be destroyed
    428  */
    429 WL_EXPORT void
    430 wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
    431 {
    432 	unsigned int i;
    433 
    434 	for (i = 0; i < theme->cursor_count; i++)
    435 		wl_cursor_destroy(theme->cursors[i]);
    436 
    437 	shm_pool_destroy(theme->pool);
    438 
    439 	free(theme->name);
    440 	free(theme->cursors);
    441 	free(theme);
    442 }
    443 
    444 /** Get the cursor for a given name from a cursor theme
    445  *
    446  * \param theme The cursor theme
    447  * \param name Name of the desired cursor
    448  * \return The theme's cursor of the given name or %NULL if there is no
    449  * such cursor
    450  */
    451 WL_EXPORT struct wl_cursor *
    452 wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
    453 			   const char *name)
    454 {
    455 	unsigned int i;
    456 
    457 	for (i = 0; i < theme->cursor_count; i++) {
    458 		if (strcmp(name, theme->cursors[i]->name) == 0)
    459 			return theme->cursors[i];
    460 	}
    461 
    462 	return NULL;
    463 }
    464 
    465 /** Find the frame for a given elapsed time in a cursor animation
    466  *  as well as the time left until next cursor change.
    467  *
    468  * \param cursor The cursor
    469  * \param time Elapsed time in ms since the beginning of the animation
    470  * \param duration pointer to uint32_t to store time left for this image or
    471  *                 zero if the cursor won't change.
    472  *
    473  * \return The index of the image that should be displayed for the
    474  * given time in the cursor animation.
    475  */
    476 WL_EXPORT int
    477 wl_cursor_frame_and_duration(struct wl_cursor *_cursor, uint32_t time,
    478 			     uint32_t *duration)
    479 {
    480 	struct cursor *cursor = (struct cursor *) _cursor;
    481 	uint32_t t;
    482 	int i;
    483 
    484 	if (cursor->cursor.image_count == 1) {
    485 		if (duration)
    486 			*duration = 0;
    487 		return 0;
    488 	}
    489 
    490 	i = 0;
    491 	t = time % cursor->total_delay;
    492 
    493 	/* If there is a 0 delay in the image set then this
    494 	 * loop breaks on it and we display that cursor until
    495 	 * time % cursor->total_delay wraps again.
    496 	 * Since a 0 delay is silly, and we've never actually
    497 	 * seen one in a cursor file, we haven't bothered to
    498 	 * "fix" this.
    499 	 */
    500 	while (t - cursor->cursor.images[i]->delay < t)
    501 		t -= cursor->cursor.images[i++]->delay;
    502 
    503 	if (!duration)
    504 		return i;
    505 
    506 	/* Make sure we don't accidentally tell the caller this is
    507 	 * a static cursor image.
    508 	 */
    509 	if (t >= cursor->cursor.images[i]->delay)
    510 		*duration = 1;
    511 	else
    512 		*duration = cursor->cursor.images[i]->delay - t;
    513 
    514 	return i;
    515 }
    516 
    517 /** Find the frame for a given elapsed time in a cursor animation
    518  *
    519  * \param cursor The cursor
    520  * \param time Elapsed time in ms since the beginning of the animation
    521  *
    522  * \return The index of the image that should be displayed for the
    523  * given time in the cursor animation.
    524  */
    525 WL_EXPORT int
    526 wl_cursor_frame(struct wl_cursor *_cursor, uint32_t time)
    527 {
    528 	return wl_cursor_frame_and_duration(_cursor, time, NULL);
    529 }
    530