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 *
shm_pool_create(struct wl_shm * shm,int size)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
shm_pool_resize(struct shm_pool * pool,int size)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
shm_pool_allocate(struct shm_pool * pool,int size)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
shm_pool_destroy(struct shm_pool * pool)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 *
wl_cursor_image_get_buffer(struct wl_cursor_image * _img)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
wl_cursor_image_destroy(struct wl_cursor_image * _img)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
wl_cursor_destroy(struct wl_cursor * cursor)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 *
wl_cursor_create_from_data(struct cursor_metadata * metadata,struct wl_cursor_theme * theme)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
load_default_theme(struct wl_cursor_theme * theme)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 *
wl_cursor_create_from_xcursor_images(XcursorImages * images,struct wl_cursor_theme * theme)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
load_callback(XcursorImages * images,void * data)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 *
wl_cursor_theme_load(const char * name,int size,struct wl_shm * shm)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
wl_cursor_theme_destroy(struct wl_cursor_theme * theme)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 *
wl_cursor_theme_get_cursor(struct wl_cursor_theme * theme,const char * name)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
wl_cursor_frame_and_duration(struct wl_cursor * _cursor,uint32_t time,uint32_t * duration)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
wl_cursor_frame(struct wl_cursor * _cursor,uint32_t time)526 wl_cursor_frame(struct wl_cursor *_cursor, uint32_t time)
527 {
528 return wl_cursor_frame_and_duration(_cursor, time, NULL);
529 }
530