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