2 * Copyright © 2012 Intel Corporation
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.
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
24 #include "wayland-cursor.h"
25 #include "wayland-client.h"
33 struct wl_shm_pool *pool;
40 static struct shm_pool *
41 shm_pool_create(struct wl_shm *shm, int size)
43 struct shm_pool *pool;
44 char filename[] = "/tmp/wayland-shm-XXXXXX";
46 pool = malloc(sizeof *pool);
50 pool->fd = mkstemp(filename);
54 if (ftruncate(pool->fd, size) < 0) {
59 pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
63 if (pool->data == MAP_FAILED) {
68 pool->pool = wl_shm_create_pool(shm, pool->fd, size);
76 shm_pool_resize(struct shm_pool *pool, int size)
78 if (ftruncate(pool->fd, size) < 0)
81 wl_shm_pool_resize(pool->pool, size);
83 munmap(pool->data, pool->size);
85 pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
93 shm_pool_allocate(struct shm_pool *pool, int size)
97 if (pool->used + size > pool->size)
98 if (!shm_pool_resize(pool, 2 * pool->size + size))
108 shm_pool_destroy(struct shm_pool *pool)
110 munmap(pool->data, pool->size);
111 wl_shm_pool_destroy(pool->pool);
116 static const char *cursor_names[] = {
117 "bottom_left_corner",
118 "bottom_right_corner",
131 struct wl_cursor_theme {
132 unsigned int cursor_count;
133 struct wl_cursor **cursors;
135 struct shm_pool *pool;
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 */
147 /** Get an shm buffer for a cursor image
149 * \param image The cursor image
150 * \return An shm buffer for the cursor image. The user should not destroy
151 * the returned buffer.
153 WL_EXPORT struct wl_buffer *
154 wl_cursor_image_get_buffer(struct wl_cursor_image *_img)
156 struct cursor_image *image = (struct cursor_image *) _img;
157 struct wl_cursor_theme *theme = image->theme;
159 if (!image->buffer) {
161 wl_shm_pool_create_buffer(theme->pool->pool,
163 _img->width, _img->height,
165 WL_SHM_FORMAT_ARGB8888);
168 return image->buffer;
172 wl_cursor_image_destroy(struct wl_cursor_image *_img)
174 struct cursor_image *image = (struct cursor_image *) _img;
177 wl_buffer_destroy(image->buffer);
183 wl_cursor_destroy(struct wl_cursor *cursor)
187 for (i = 0; i < cursor->image_count; i++)
188 wl_cursor_image_destroy(cursor->images[i]);
194 static struct wl_cursor *
195 load_cursor(struct wl_cursor_theme *theme, const char *name)
197 XcursorImages *images;
198 struct wl_cursor *cursor;
199 struct cursor_image *image;
202 images = XcursorLibraryLoadImages(name, theme->name, theme->size);
206 cursor = malloc(sizeof *cursor);
208 XcursorImagesDestroy(images);
212 cursor->image_count = images->nimage;
213 cursor->images = malloc(images->nimage * sizeof cursor->images[0]);
214 if (!cursor->images) {
215 XcursorImagesDestroy(images);
220 cursor->name = strdup(name);
222 for (i = 0; i < images->nimage; i++) {
223 image = malloc(sizeof *image);
224 cursor->images[i] = (struct wl_cursor_image *) image;
226 image->theme = theme;
227 image->buffer = NULL;
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;
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);
242 XcursorImagesDestroy(images);
247 /** Load a cursor theme to memory shared with the compositor
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.
254 * \return An object representing the theme that should be destroyed with
255 * wl_cursor_theme_destroy() or %NULL on error.
257 WL_EXPORT struct wl_cursor_theme *
258 wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
260 struct wl_cursor_theme *theme;
263 theme = malloc(sizeof *theme);
270 theme->name = strdup(name);
272 theme->cursor_count = ARRAY_LENGTH(cursor_names);
275 malloc(theme->cursor_count * sizeof theme->cursors[0]);
276 if (!theme->cursors) {
282 shm_pool_create(shm, theme->cursor_count * size * size * 4);
284 for (i = 0; i < theme->cursor_count; i++)
285 theme->cursors[i] = load_cursor(theme, cursor_names[i]);
290 /** Destroys a cursor theme object
292 * \param theme The cursor theme to be destroyed
295 wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
299 for (i = 0; i < theme->cursor_count; i++)
300 wl_cursor_destroy(theme->cursors[i]);
302 shm_pool_destroy(theme->pool);
304 free(theme->cursors);
308 /** Get the cursor for a given type from a cursor theme
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
315 WL_EXPORT struct wl_cursor *
316 wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
317 enum wl_cursor_type type)
319 if (type < theme->cursor_count)
320 return theme->cursors[type];
325 /** Get the cursor for a given name from a cursor theme
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
332 WL_EXPORT struct wl_cursor *
333 wl_cursor_theme_get_cursor_by_name(struct wl_cursor_theme *theme,
337 struct wl_cursor *cursor;
339 for (i = 0; i < theme->cursor_count; i++) {
340 if (strcmp(name, theme->cursors[i]->name) == 0)
341 return theme->cursors[i];
344 cursor = load_cursor(theme, name);
348 theme->cursor_count++;
350 realloc(theme->cursors,
351 theme->cursor_count * sizeof theme->cursors[0]);
353 theme->cursors[theme->cursor_count - 1] = cursor;