wayland-cursor.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  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. #include "config.h"
  26. #include "xcursor.h"
  27. #include "wayland-cursor.h"
  28. #include "wayland-client.h"
  29. #include <limits.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. #include "os-compatibility.h"
  39. #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
  40. struct shm_pool {
  41. struct wl_shm_pool *pool;
  42. int fd;
  43. unsigned int size;
  44. unsigned int used;
  45. char *data;
  46. };
  47. static struct shm_pool *
  48. shm_pool_create(struct wl_shm *shm, int size)
  49. {
  50. struct shm_pool *pool;
  51. pool = malloc(sizeof *pool);
  52. if (!pool)
  53. return NULL;
  54. pool->fd = os_create_anonymous_file(size);
  55. if (pool->fd < 0)
  56. goto err_free;
  57. pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
  58. pool->fd, 0);
  59. if (pool->data == MAP_FAILED)
  60. goto err_close;
  61. pool->pool = wl_shm_create_pool(shm, pool->fd, size);
  62. if (!pool->pool)
  63. goto err_unmap;
  64. pool->size = size;
  65. pool->used = 0;
  66. return pool;
  67. err_unmap:
  68. munmap(pool->data, size);
  69. err_close:
  70. close(pool->fd);
  71. err_free:
  72. free(pool);
  73. return NULL;
  74. }
  75. static int
  76. shm_pool_resize(struct shm_pool *pool, int size)
  77. {
  78. if (os_resize_anonymous_file(pool->fd, size) < 0)
  79. return 0;
  80. wl_shm_pool_resize(pool->pool, size);
  81. munmap(pool->data, pool->size);
  82. pool->data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED,
  83. pool->fd, 0);
  84. if (pool->data == MAP_FAILED)
  85. return 0;
  86. pool->size = size;
  87. return 1;
  88. }
  89. static int
  90. shm_pool_allocate(struct shm_pool *pool, int size)
  91. {
  92. int offset;
  93. if (pool->used + size > pool->size)
  94. if (!shm_pool_resize(pool, 2 * pool->size + size))
  95. return -1;
  96. offset = pool->used;
  97. pool->used += size;
  98. return offset;
  99. }
  100. static void
  101. shm_pool_destroy(struct shm_pool *pool)
  102. {
  103. munmap(pool->data, pool->size);
  104. wl_shm_pool_destroy(pool->pool);
  105. close(pool->fd);
  106. free(pool);
  107. }
  108. struct wl_cursor_theme {
  109. unsigned int cursor_count;
  110. struct wl_cursor **cursors;
  111. struct wl_shm *shm;
  112. struct shm_pool *pool;
  113. int size;
  114. };
  115. struct cursor_image {
  116. struct wl_cursor_image image;
  117. struct wl_cursor_theme *theme;
  118. struct wl_buffer *buffer;
  119. int offset; /* data offset of this image in the shm pool */
  120. };
  121. struct cursor {
  122. struct wl_cursor cursor;
  123. uint32_t total_delay; /* length of the animation in ms */
  124. };
  125. /** Get an shm buffer for a cursor image
  126. *
  127. * \param image The cursor image
  128. * \return An shm buffer for the cursor image. The user should not destroy
  129. * the returned buffer.
  130. */
  131. WL_EXPORT struct wl_buffer *
  132. wl_cursor_image_get_buffer(struct wl_cursor_image *image)
  133. {
  134. struct cursor_image *img = (struct cursor_image *) image;
  135. struct wl_cursor_theme *theme = img->theme;
  136. if (!img->buffer) {
  137. img->buffer =
  138. wl_shm_pool_create_buffer(theme->pool->pool,
  139. img->offset,
  140. image->width, image->height,
  141. image->width * 4,
  142. WL_SHM_FORMAT_ARGB8888);
  143. };
  144. return img->buffer;
  145. }
  146. static void
  147. wl_cursor_image_destroy(struct wl_cursor_image *image)
  148. {
  149. struct cursor_image *img = (struct cursor_image *) image;
  150. if (img->buffer)
  151. wl_buffer_destroy(img->buffer);
  152. free(img);
  153. }
  154. static void
  155. wl_cursor_destroy(struct wl_cursor *cursor)
  156. {
  157. unsigned int i;
  158. for (i = 0; i < cursor->image_count; i++)
  159. wl_cursor_image_destroy(cursor->images[i]);
  160. free(cursor->images);
  161. free(cursor->name);
  162. free(cursor);
  163. }
  164. #include "cursor-data.h"
  165. static struct wl_cursor *
  166. wl_cursor_create_from_data(struct cursor_metadata *metadata,
  167. struct wl_cursor_theme *theme)
  168. {
  169. struct cursor *cursor;
  170. struct cursor_image *image;
  171. int size;
  172. cursor = malloc(sizeof *cursor);
  173. if (!cursor)
  174. return NULL;
  175. cursor->cursor.image_count = 1;
  176. cursor->cursor.images = malloc(sizeof *cursor->cursor.images);
  177. if (!cursor->cursor.images)
  178. goto err_free_cursor;
  179. cursor->cursor.name = strdup(metadata->name);
  180. cursor->total_delay = 0;
  181. image = malloc(sizeof *image);
  182. if (!image)
  183. goto err_free_images;
  184. cursor->cursor.images[0] = (struct wl_cursor_image *) image;
  185. image->theme = theme;
  186. image->buffer = NULL;
  187. image->image.width = metadata->width;
  188. image->image.height = metadata->height;
  189. image->image.hotspot_x = metadata->hotspot_x;
  190. image->image.hotspot_y = metadata->hotspot_y;
  191. image->image.delay = 0;
  192. size = metadata->width * metadata->height * sizeof(uint32_t);
  193. image->offset = shm_pool_allocate(theme->pool, size);
  194. if (image->offset < 0)
  195. goto err_free_image;
  196. memcpy(theme->pool->data + image->offset,
  197. cursor_data + metadata->offset, size);
  198. return &cursor->cursor;
  199. err_free_image:
  200. free(image);
  201. err_free_images:
  202. free(cursor->cursor.name);
  203. free(cursor->cursor.images);
  204. err_free_cursor:
  205. free(cursor);
  206. return NULL;
  207. }
  208. static void
  209. load_fallback_theme(struct wl_cursor_theme *theme)
  210. {
  211. uint32_t i;
  212. theme->cursor_count = ARRAY_LENGTH(cursor_metadata);
  213. theme->cursors = malloc(theme->cursor_count * sizeof(*theme->cursors));
  214. if (theme->cursors == NULL) {
  215. theme->cursor_count = 0;
  216. return;
  217. }
  218. for (i = 0; i < theme->cursor_count; ++i) {
  219. theme->cursors[i] =
  220. wl_cursor_create_from_data(&cursor_metadata[i], theme);
  221. if (theme->cursors[i] == NULL)
  222. break;
  223. }
  224. theme->cursor_count = i;
  225. }
  226. static struct wl_cursor *
  227. wl_cursor_create_from_xcursor_images(struct xcursor_images *images,
  228. struct wl_cursor_theme *theme)
  229. {
  230. struct cursor *cursor;
  231. struct cursor_image *image;
  232. size_t size;
  233. int i;
  234. cursor = malloc(sizeof *cursor);
  235. if (!cursor)
  236. return NULL;
  237. cursor->cursor.images =
  238. malloc(images->nimage * sizeof cursor->cursor.images[0]);
  239. if (!cursor->cursor.images) {
  240. free(cursor);
  241. return NULL;
  242. }
  243. cursor->cursor.name = strdup(images->name);
  244. cursor->total_delay = 0;
  245. for (i = 0; i < images->nimage; i++) {
  246. image = malloc(sizeof *image);
  247. if (image == NULL)
  248. break;
  249. image->theme = theme;
  250. image->buffer = NULL;
  251. image->image.width = images->images[i]->width;
  252. image->image.height = images->images[i]->height;
  253. image->image.hotspot_x = images->images[i]->xhot;
  254. image->image.hotspot_y = images->images[i]->yhot;
  255. image->image.delay = images->images[i]->delay;
  256. size = (size_t) image->image.width * image->image.height * 4;
  257. if (size > INT_MAX) {
  258. free(image);
  259. break;
  260. }
  261. image->offset = shm_pool_allocate(theme->pool, size);
  262. if (image->offset < 0) {
  263. free(image);
  264. break;
  265. }
  266. /* copy pixels to shm pool */
  267. memcpy(theme->pool->data + image->offset,
  268. images->images[i]->pixels, size);
  269. cursor->total_delay += image->image.delay;
  270. cursor->cursor.images[i] = (struct wl_cursor_image *) image;
  271. }
  272. cursor->cursor.image_count = i;
  273. if (cursor->cursor.image_count == 0) {
  274. free(cursor->cursor.name);
  275. free(cursor->cursor.images);
  276. free(cursor);
  277. return NULL;
  278. }
  279. return &cursor->cursor;
  280. }
  281. static void
  282. load_callback(struct xcursor_images *images, void *data)
  283. {
  284. struct wl_cursor_theme *theme = data;
  285. struct wl_cursor *cursor;
  286. struct wl_cursor **p;
  287. size_t s;
  288. if (wl_cursor_theme_get_cursor(theme, images->name)) {
  289. xcursor_images_destroy(images);
  290. return;
  291. }
  292. cursor = wl_cursor_create_from_xcursor_images(images, theme);
  293. if (cursor) {
  294. s = theme->cursor_count + 1;
  295. p = realloc(theme->cursors, s * sizeof theme->cursors[0]);
  296. if (p == NULL) {
  297. free(cursor);
  298. } else {
  299. theme->cursor_count = s;
  300. theme->cursors = p;
  301. theme->cursors[theme->cursor_count - 1] = cursor;
  302. }
  303. }
  304. xcursor_images_destroy(images);
  305. }
  306. /** Load a cursor theme to memory shared with the compositor
  307. *
  308. * \param name The name of the cursor theme to load. If %NULL, the default
  309. * theme will be loaded.
  310. * \param size Desired size of the cursor images.
  311. * \param shm The compositor's shm interface.
  312. *
  313. * \return An object representing the theme that should be destroyed with
  314. * wl_cursor_theme_destroy() or %NULL on error. If no theme with the given
  315. * name exists, a default theme will be loaded.
  316. */
  317. WL_EXPORT struct wl_cursor_theme *
  318. wl_cursor_theme_load(const char *name, int size, struct wl_shm *shm)
  319. {
  320. struct wl_cursor_theme *theme;
  321. theme = malloc(sizeof *theme);
  322. if (!theme)
  323. return NULL;
  324. if (size < 0 || (size > 0 && INT_MAX / size / 4 < size))
  325. goto err;
  326. if (!name)
  327. name = "default";
  328. theme->size = size;
  329. theme->cursor_count = 0;
  330. theme->cursors = NULL;
  331. theme->pool = shm_pool_create(shm, size * size * 4);
  332. if (!theme->pool)
  333. goto err;
  334. xcursor_load_theme(name, size, load_callback, theme);
  335. if (theme->cursor_count == 0)
  336. xcursor_load_theme(NULL, size, load_callback, theme);
  337. if (theme->cursor_count == 0)
  338. load_fallback_theme(theme);
  339. return theme;
  340. err:
  341. free(theme);
  342. return NULL;
  343. }
  344. /** Destroys a cursor theme object
  345. *
  346. * \param theme The cursor theme to be destroyed
  347. */
  348. WL_EXPORT void
  349. wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
  350. {
  351. unsigned int i;
  352. for (i = 0; i < theme->cursor_count; i++)
  353. wl_cursor_destroy(theme->cursors[i]);
  354. shm_pool_destroy(theme->pool);
  355. free(theme->cursors);
  356. free(theme);
  357. }
  358. /** Get the cursor for a given name from a cursor theme
  359. *
  360. * \param theme The cursor theme
  361. * \param name Name of the desired cursor
  362. * \return The theme's cursor of the given name or %NULL if there is no
  363. * such cursor
  364. */
  365. WL_EXPORT struct wl_cursor *
  366. wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
  367. const char *name)
  368. {
  369. unsigned int i;
  370. for (i = 0; i < theme->cursor_count; i++) {
  371. if (strcmp(name, theme->cursors[i]->name) == 0)
  372. return theme->cursors[i];
  373. }
  374. return NULL;
  375. }
  376. /** Find the frame for a given elapsed time in a cursor animation
  377. * as well as the time left until next cursor change.
  378. *
  379. * \param cursor The cursor
  380. * \param time Elapsed time in ms since the beginning of the animation
  381. * \param duration pointer to uint32_t to store time left for this image or
  382. * zero if the cursor won't change.
  383. *
  384. * \return The index of the image that should be displayed for the
  385. * given time in the cursor animation.
  386. */
  387. WL_EXPORT int
  388. wl_cursor_frame_and_duration(struct wl_cursor *cursor, uint32_t time,
  389. uint32_t *duration)
  390. {
  391. struct cursor *cur = (struct cursor *) cursor;
  392. uint32_t t;
  393. int i;
  394. if (cur->cursor.image_count == 1 || cur->total_delay == 0) {
  395. if (duration)
  396. *duration = 0;
  397. return 0;
  398. }
  399. i = 0;
  400. t = time % cur->total_delay;
  401. /* If there is a 0 delay in the image set then this
  402. * loop breaks on it and we display that cursor until
  403. * time % cursor->total_delay wraps again.
  404. * Since a 0 delay is silly, and we've never actually
  405. * seen one in a cursor file, we haven't bothered to
  406. * "fix" this.
  407. */
  408. while (t - cur->cursor.images[i]->delay < t)
  409. t -= cur->cursor.images[i++]->delay;
  410. if (!duration)
  411. return i;
  412. /* Make sure we don't accidentally tell the caller this is
  413. * a static cursor image.
  414. */
  415. if (t >= cur->cursor.images[i]->delay)
  416. *duration = 1;
  417. else
  418. *duration = cur->cursor.images[i]->delay - t;
  419. return i;
  420. }
  421. /** Find the frame for a given elapsed time in a cursor animation
  422. *
  423. * \param cursor The cursor
  424. * \param time Elapsed time in ms since the beginning of the animation
  425. *
  426. * \return The index of the image that should be displayed for the
  427. * given time in the cursor animation.
  428. */
  429. WL_EXPORT int
  430. wl_cursor_frame(struct wl_cursor *cursor, uint32_t time)
  431. {
  432. return wl_cursor_frame_and_duration(cursor, time, NULL);
  433. }