Wayland: Add missing extern "C"
[profile/ivi/wayland.git] / cursor / wayland-cursor.c
1 /*
2  * Copyright © 2012 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include "xcursor.h"
24 #include "wayland-cursor.h"
25 #include "wayland-client.h"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <sys/mman.h>
31
32 struct shm_pool {
33         struct wl_shm_pool *pool;
34         int fd;
35         unsigned int size;
36         unsigned int used;
37         char *data;
38 };
39
40 static struct shm_pool *
41 shm_pool_create(struct wl_shm *shm, int size)
42 {
43         struct shm_pool *pool;
44         char filename[] = "/tmp/wayland-shm-XXXXXX";
45
46         pool = malloc(sizeof *pool);
47         if (!pool)
48                 return NULL;
49
50         pool->fd = mkstemp(filename);
51         if (pool->fd < 0)
52                 return NULL;
53
54         if (ftruncate(pool->fd, size) < 0) {
55                 close(pool->fd);
56                 return NULL;
57         }
58
59         pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
60                           pool->fd, 0);
61         unlink(filename);
62
63         if (pool->data == MAP_FAILED) {
64                 close(pool->fd);
65                 return NULL;
66         }
67
68         pool->pool = wl_shm_create_pool(shm, pool->fd, size);
69         pool->size = size;
70         pool->used = 0;
71
72         return pool;
73 }
74
75 static int
76 shm_pool_resize(struct shm_pool *pool, int size)
77 {
78         if (ftruncate(pool->fd, size) < 0)
79                 return 0;
80
81         wl_shm_pool_resize(pool->pool, size);
82
83         munmap(pool->data, pool->size);
84
85         pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
86                           pool->fd, 0);
87         pool->size = size;
88
89         return 1;
90 }
91
92 static int
93 shm_pool_allocate(struct shm_pool *pool, int size)
94 {
95         int offset;
96
97         if (pool->used + size > pool->size)
98                 if (!shm_pool_resize(pool, 2 * pool->size + size))
99                         return -1;
100
101         offset = pool->used;
102         pool->used += size;
103
104         return offset;
105 }
106
107 static void
108 shm_pool_destroy(struct shm_pool *pool)
109 {
110         munmap(pool->data, pool->size);
111         wl_shm_pool_destroy(pool->pool);
112         free(pool);
113 }
114
115
116 static const char *cursor_names[] = {
117         "bottom_left_corner",
118         "bottom_right_corner",
119         "bottom_side",
120         "grabbing",
121         "left_ptr",
122         "left_side",
123         "right_side",
124         "top_left_corner",
125         "top_right_corner",
126         "top_side",
127         "xterm",
128         "hand1",
129 };
130
131 struct wl_cursor_theme {
132         unsigned int cursor_count;
133         struct wl_cursor **cursors;
134         struct wl_shm *shm;
135         struct shm_pool *pool;
136         char *name;
137         int size;
138 };
139
140 struct cursor_image {
141         struct wl_cursor_image image;
142         struct wl_cursor_theme *theme;
143         struct wl_buffer *buffer;
144         int offset; /* data offset of this image in the shm pool */
145 };
146
147 /** Get an shm buffer for a cursor image
148  *
149  * \param image The cursor image
150  * \return An shm buffer for the cursor image. The user should not destroy
151  * the returned buffer.
152  */
153 WL_EXPORT struct wl_buffer *
154 wl_cursor_image_get_buffer(struct wl_cursor_image *_img)
155 {
156         struct cursor_image *image = (struct cursor_image *) _img;
157         struct wl_cursor_theme *theme = image->theme;
158
159         if (!image->buffer) {
160                 image->buffer =
161                         wl_shm_pool_create_buffer(theme->pool->pool,
162                                                   image->offset,
163                                                   _img->width, _img->height,
164                                                   _img->width * 4,
165                                                   WL_SHM_FORMAT_ARGB8888);
166         };
167
168         return image->buffer;
169 }
170
171 static void
172 wl_cursor_image_destroy(struct wl_cursor_image *_img)
173 {
174         struct cursor_image *image = (struct cursor_image *) _img;
175
176         if (image->buffer)
177                 wl_buffer_destroy(image->buffer);
178
179         free(image);
180 }
181
182 static void
183 wl_cursor_destroy(struct wl_cursor *cursor)
184 {
185         unsigned int i;
186
187         for (i = 0; i < cursor->image_count; i++)
188                 wl_cursor_image_destroy(cursor->images[i]);
189
190         free(cursor->name);
191         free(cursor);
192 }
193
194 static struct wl_cursor *
195 load_cursor(struct wl_cursor_theme *theme, const char *name)
196 {
197         XcursorImages *images;
198         struct wl_cursor *cursor;
199         struct cursor_image *image;
200         int i, size;
201
202         images = XcursorLibraryLoadImages(name, theme->name, theme->size);
203         if (!images)
204                 return NULL;
205
206         cursor = malloc(sizeof *cursor);
207         if (!cursor) {
208                 XcursorImagesDestroy(images);
209                 return NULL;
210         }
211
212         cursor->image_count = images->nimage;
213         cursor->images = malloc(images->nimage * sizeof cursor->images[0]);
214         if (!cursor->images) {
215                 XcursorImagesDestroy(images);
216                 free(cursor);
217                 return NULL;
218         }
219
220         cursor->name = strdup(name);
221
222         for (i = 0; i < images->nimage; i++) {
223                 image = malloc(sizeof *image);
224                 cursor->images[i] = (struct wl_cursor_image *) image;
225
226                 image->theme = theme;
227                 image->buffer = NULL;
228
229                 image->image.width = images->images[i]->width;
230                 image->image.height = images->images[i]->height;
231                 image->image.hotspot_x = images->images[i]->xhot;
232                 image->image.hotspot_y = images->images[i]->yhot;
233                 image->image.delay = images->images[i]->delay;
234
235                 /* copy pixels to shm pool */
236                 size = image->image.width * image->image.height * 4;
237                 image->offset = shm_pool_allocate(theme->pool, size);
238                 memcpy(theme->pool->data + image->offset,
239                        images->images[i]->pixels, size);
240         }
241
242         XcursorImagesDestroy(images);
243
244         return cursor;
245 }
246
247 /** Load a cursor theme to memory shared with the compositor
248  *
249  * \param name The name of the cursor theme to load. If %NULL, the default
250  * theme will be loaded.
251  * \param size Desired size of the cursor images.
252  * \param shm The compositor's shm interface.
253  *
254  * \return An object representing the theme that should be destroyed with
255  * wl_cursor_theme_destroy() or %NULL on error.
256  */
257 WL_EXPORT struct wl_cursor_theme *
258 wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
259 {
260         struct wl_cursor_theme *theme;
261         unsigned int i;
262
263         theme = malloc(sizeof *theme);
264         if (!theme)
265                 return NULL;
266
267         if (!name)
268                 name = "default";
269
270         theme->name = strdup(name);
271         theme->size = size;
272         theme->cursor_count = ARRAY_LENGTH(cursor_names);
273
274         theme->cursors =
275                 malloc(theme->cursor_count * sizeof theme->cursors[0]);
276         if (!theme->cursors) {
277                 free(theme);
278                 return NULL;
279         }
280
281         theme->pool =
282                 shm_pool_create(shm, theme->cursor_count * size * size * 4);
283
284         for (i = 0; i < theme->cursor_count; i++)
285                 theme->cursors[i] = load_cursor(theme, cursor_names[i]);
286
287         return theme;
288 }
289
290 /** Destroys a cursor theme object
291  *
292  * \param theme The cursor theme to be destroyed
293  */
294 WL_EXPORT void
295 wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
296 {
297         unsigned int i;
298
299         for (i = 0; i < theme->cursor_count; i++)
300                 wl_cursor_destroy(theme->cursors[i]);
301
302         shm_pool_destroy(theme->pool);
303
304         free(theme->cursors);
305         free(theme);
306 }
307
308 /** Get the cursor for a given type from a cursor theme
309  *
310  * \param theme The cursor theme
311  * \patam type The desired cursor type
312  * \return The theme's cursor of the given type or %NULL if there is no
313  * such cursor
314  */
315 WL_EXPORT struct wl_cursor *
316 wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
317                            enum wl_cursor_type type)
318 {
319         if (type < theme->cursor_count)
320                 return theme->cursors[type];
321
322         return NULL;
323 }
324
325 /** Get the cursor for a given name from a cursor theme
326  *
327  * \param theme The cursor theme
328  * \param name Name of the desired cursor
329  * \return The theme's cursor of the given name or %NULL if there is no
330  * such cursor
331  */
332 WL_EXPORT struct wl_cursor *
333 wl_cursor_theme_get_cursor_by_name(struct wl_cursor_theme *theme,
334                                    const char *name)
335 {
336         unsigned int i;
337         struct wl_cursor *cursor;
338
339         for (i = 0; i < theme->cursor_count; i++) {
340                 if (strcmp(name, theme->cursors[i]->name) == 0)
341                         return theme->cursors[i];
342         }
343
344         cursor = load_cursor(theme, name);
345         if (!cursor)
346                 return NULL;
347
348         theme->cursor_count++;
349         theme->cursors =
350                 realloc(theme->cursors,
351                         theme->cursor_count * sizeof theme->cursors[0]);
352
353         theme->cursors[theme->cursor_count - 1] = cursor;
354
355         return cursor;
356 }