diff --git a/clients/window.c b/clients/window.c index 54f57a33..2dcf421f 100644 --- a/clients/window.c +++ b/clients/window.c @@ -57,6 +57,7 @@ #include #include +#include #include #include @@ -64,6 +65,8 @@ #include "window.h" +struct cursor; + struct display { struct wl_display *display; struct wl_compositor *compositor; @@ -91,7 +94,7 @@ struct display { cairo_surface_t *active_frame, *inactive_frame, *shadow; int frame_radius; struct xkb_desc *xkb; - cairo_surface_t **pointer_surfaces; + struct cursor *cursors; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC image_target_texture_2d; PFNEGLCREATEIMAGEKHRPROC create_image; @@ -172,7 +175,7 @@ struct input { struct wl_input_device *input_device; struct window *pointer_focus; struct window *keyboard_focus; - int current_pointer_image; + int current_cursor; uint32_t modifiers; uint32_t pointer_enter_serial; int32_t sx, sy; @@ -216,6 +219,18 @@ struct menu { menu_func_t func; }; +struct cursor_image { + cairo_surface_t *surface; + int width, height; + int hotspot_x, hotspot_y; + int delay; +}; + +struct cursor { + int n_images; + struct cursor_image *images; +}; + enum { POINTER_DEFAULT = 100, POINTER_UNSET @@ -345,6 +360,14 @@ shm_surface_data_destroy(void *p) munmap(data->map, data->length); } +static void +shm_surface_write(cairo_surface_t *surface, unsigned char *data, int count) +{ + void *dest = cairo_image_surface_get_data(surface); + + memcpy(dest, data, count); +} + static struct wl_shm_pool * make_shm_pool(struct display *display, int size, void **data) { @@ -432,35 +455,6 @@ display_create_shm_surface(struct display *display, return surface; } -static cairo_surface_t * -display_create_shm_surface_from_file(struct display *display, - const char *filename, - struct rectangle *rect) -{ - cairo_surface_t *surface; - pixman_image_t *image; - void *dest; - int size; - - image = load_image(filename); - if (image == NULL) - return NULL; - - surface = display_create_shm_surface(display, rect, 0, NULL); - if (surface == NULL) { - pixman_image_unref(image); - return NULL; - } - - size = pixman_image_get_stride(image) * pixman_image_get_height(image); - dest = cairo_image_surface_get_data(surface); - memcpy(dest, pixman_image_get_data(image), size); - - pixman_image_unref(image); - - return surface; -} - static int check_size(struct rectangle *rect) { @@ -490,70 +484,102 @@ display_create_surface(struct display *display, return display_create_shm_surface(display, rectangle, flags, NULL); } -static cairo_surface_t * -display_create_surface_from_file(struct display *display, - const char *filename, - struct rectangle *rectangle) +static const char *cursors[] = { + "bottom_left_corner", + "bottom_right_corner", + "bottom_side", + "grabbing", + "left_ptr", + "left_side", + "right_side", + "top_left_corner", + "top_right_corner", + "top_side", + "xterm", + "hand1", +}; + +static void +create_cursor_from_images(struct display *display, struct cursor *cursor, + XcursorImages *images) { - if (check_size(rectangle) < 0) - return NULL; + int i; + struct rectangle rect; + XcursorImage *image; + + cursor->images = malloc(images->nimage * sizeof *cursor->images); + cursor->n_images = images->nimage; + + for (i = 0; i < images->nimage; i++) { + image = images->images[i]; + + rect.width = image->width; + rect.height = image->height; + + cursor->images[i].surface = + display_create_shm_surface(display, &rect, 0, NULL); + + shm_surface_write(cursor->images[i].surface, + (unsigned char *) image->pixels, + image->width * image->height * sizeof image->pixels[0]); + + cursor->images[i].width = image->width; + cursor->images[i].height = image->height; + cursor->images[i].hotspot_x = image->xhot; + cursor->images[i].hotspot_y = image->yhot; + cursor->images[i].delay = image->delay; + } - return display_create_shm_surface_from_file(display, filename, rectangle); } - static const struct { - const char *filename; - int hotspot_x, hotspot_y; -} pointer_images[] = { - { DATADIR "/weston/bottom_left_corner.png", 6, 30 }, - { DATADIR "/weston/bottom_right_corner.png", 28, 28 }, - { DATADIR "/weston/bottom_side.png", 16, 20 }, - { DATADIR "/weston/grabbing.png", 20, 17 }, - { DATADIR "/weston/left_ptr.png", 10, 5 }, - { DATADIR "/weston/left_side.png", 10, 20 }, - { DATADIR "/weston/right_side.png", 30, 19 }, - { DATADIR "/weston/top_left_corner.png", 8, 8 }, - { DATADIR "/weston/top_right_corner.png", 26, 8 }, - { DATADIR "/weston/top_side.png", 18, 8 }, - { DATADIR "/weston/xterm.png", 15, 15 }, - { DATADIR "/weston/hand1.png", 18, 11 } -}; static void -create_pointer_surfaces(struct display *display) +create_cursors(struct display *display) { int i, count; - const int width = 32, height = 32; - struct rectangle rect; + struct cursor *cursor; + XcursorImages *images; - count = ARRAY_LENGTH(pointer_images); - display->pointer_surfaces = - malloc(count * sizeof *display->pointer_surfaces); - rect.width = width; - rect.height = height; + count = ARRAY_LENGTH(cursors); + display->cursors = malloc(count * sizeof *display->cursors); for (i = 0; i < count; i++) { - display->pointer_surfaces[i] = - display_create_surface_from_file(display, - pointer_images[i].filename, - &rect); - if (!display->pointer_surfaces[i]) { - fprintf(stderr, "Error loading pointer image: %s\n", - pointer_images[i].filename); + images = XcursorLibraryLoadImages(cursors[i], NULL, 32); + + if (!images) { + fprintf(stderr, "Error loading cursor: %s\n", + cursors[i]); + continue; } + + cursor = &display->cursors[i]; + create_cursor_from_images(display, cursor, images); + + XcursorImagesDestroy(images); } } static void -destroy_pointer_surfaces(struct display *display) +destroy_cursor_images(struct cursor *cursor) +{ + int i; + + for (i = 0; i < cursor->n_images; i++) + if (cursor->images[i].surface) + cairo_surface_destroy(cursor->images[i].surface); + + free(cursor->images); +} + +static void +destroy_cursors(struct display *display) { int i, count; - count = ARRAY_LENGTH(pointer_images); + count = ARRAY_LENGTH(cursors); for (i = 0; i < count; ++i) { - if (display->pointer_surfaces[i]) - cairo_surface_destroy(display->pointer_surfaces[i]); + destroy_cursor_images(&display->cursors[i]); } - free(display->pointer_surfaces); + free(display->cursors); } cairo_surface_t * @@ -561,18 +587,17 @@ display_get_pointer_surface(struct display *display, int pointer, int *width, int *height, int *hotspot_x, int *hotspot_y) { - cairo_surface_t *surface; + struct cursor *cursor = &display->cursors[pointer]; + cairo_surface_t *surface = cursor->images[0].surface; + + /* FIXME returning information for the first image. Something better + * is needed for animated cursors */ - surface = display->pointer_surfaces[pointer]; -#if HAVE_CAIRO_EGL - *width = cairo_gl_surface_get_width(surface); - *height = cairo_gl_surface_get_height(surface); -#else *width = cairo_image_surface_get_width(surface); *height = cairo_image_surface_get_height(surface); -#endif - *hotspot_x = pointer_images[pointer].hotspot_x; - *hotspot_y = pointer_images[pointer].hotspot_y; + + *hotspot_x = cursor->images[0].hotspot_x; + *hotspot_y = cursor->images[0].hotspot_y; return cairo_surface_reference(surface); } @@ -1442,7 +1467,7 @@ input_remove_pointer_focus(struct input *input) input_set_focus_widget(input, NULL, 0, 0); input->pointer_focus = NULL; - input->current_pointer_image = POINTER_UNSET; + input->current_cursor = POINTER_UNSET; } static void @@ -1773,21 +1798,20 @@ input_set_pointer_image(struct input *input, uint32_t time, int pointer) { struct display *display = input->display; struct wl_buffer *buffer; - cairo_surface_t *surface; + struct cursor_image *image; - if (pointer == input->current_pointer_image) + if (pointer == input->current_cursor) return; - input->current_pointer_image = pointer; - surface = display->pointer_surfaces[pointer]; + image = &display->cursors[pointer].images[0]; - if (!surface) + if (!image->surface) return; - buffer = display_get_buffer_for_surface(display, surface); + input->current_cursor = pointer; + buffer = display_get_buffer_for_surface(display, image->surface); wl_input_device_attach(input->input_device, time, buffer, - pointer_images[pointer].hotspot_x, - pointer_images[pointer].hotspot_y); + image->hotspot_x, image->hotspot_y); } struct wl_data_device * @@ -2854,7 +2878,7 @@ display_create(int argc, char *argv[]) d->create_image = (void *) eglGetProcAddress("eglCreateImageKHR"); d->destroy_image = (void *) eglGetProcAddress("eglDestroyImageKHR"); - create_pointer_surfaces(d); + create_cursors(d); display_render_frame(d); @@ -2902,7 +2926,7 @@ display_destroy(struct display *display) cairo_surface_destroy(display->active_frame); cairo_surface_destroy(display->inactive_frame); cairo_surface_destroy(display->shadow); - destroy_pointer_surfaces(display); + destroy_cursors(display); #ifdef HAVE_CAIRO_EGL fini_egl(display); diff --git a/configure.ac b/configure.ac index 6da79224..26c4283d 100644 --- a/configure.ac +++ b/configure.ac @@ -137,7 +137,7 @@ AM_CONDITIONAL(BUILD_CLIENTS, test x$enable_clients = xyes) if test x$enable_clients = xyes; then AC_DEFINE([BUILD_CLIENTS], [1], [Build the Wayland clients]) - PKG_CHECK_MODULES(CLIENT, [wayland-client wayland-egl egl >= 7.10 cairo >= 1.10.0 xkbcommon]) + PKG_CHECK_MODULES(CLIENT, [wayland-client wayland-egl egl >= 7.10 cairo >= 1.10.0 xkbcommon xcursor]) CLIENT_CFLAGS="$CLIENT_CFLAGS $IMAGE_CFLAGS" CLIENT_LIBS="$CLIENT_LIBS $IMAGE_LIBS" diff --git a/data/Makefile.am b/data/Makefile.am index 39b62ffd..ec2723aa 100644 --- a/data/Makefile.am +++ b/data/Makefile.am @@ -1,24 +1,6 @@ westondatadir = $(datadir)/weston dist_westondata_DATA = \ - bottom_left_corner.png \ - bottom_right_corner.png \ - bottom_side.png \ - dnd-copy.png \ - dnd-link.png \ - dnd-move.png \ - grabbing.png \ - hand1.png \ - hand2.png \ - left_ptr.png \ - left_side.png \ - right_side.png \ - sb_h_double_arrow.png \ - sb_v_double_arrow.png \ - top_left_corner.png \ - top_right_corner.png \ - top_side.png \ - xterm.png \ wayland.svg \ $(wayland_icon_png) \ pattern.png \ diff --git a/data/bottom_left_corner.png b/data/bottom_left_corner.png deleted file mode 100644 index 2d4370fe..00000000 Binary files a/data/bottom_left_corner.png and /dev/null differ diff --git a/data/bottom_right_corner.png b/data/bottom_right_corner.png deleted file mode 100644 index 768e7778..00000000 Binary files a/data/bottom_right_corner.png and /dev/null differ diff --git a/data/bottom_side.png b/data/bottom_side.png deleted file mode 100644 index ac7c70e5..00000000 Binary files a/data/bottom_side.png and /dev/null differ diff --git a/data/dnd-copy.png b/data/dnd-copy.png deleted file mode 100644 index fd044ae1..00000000 Binary files a/data/dnd-copy.png and /dev/null differ diff --git a/data/dnd-link.png b/data/dnd-link.png deleted file mode 100644 index 5183bf9f..00000000 Binary files a/data/dnd-link.png and /dev/null differ diff --git a/data/dnd-move.png b/data/dnd-move.png deleted file mode 100644 index c3ccd6e6..00000000 Binary files a/data/dnd-move.png and /dev/null differ diff --git a/data/grabbing.png b/data/grabbing.png deleted file mode 100644 index 04694594..00000000 Binary files a/data/grabbing.png and /dev/null differ diff --git a/data/hand1.png b/data/hand1.png deleted file mode 100644 index c13aa36b..00000000 Binary files a/data/hand1.png and /dev/null differ diff --git a/data/hand2.png b/data/hand2.png deleted file mode 100644 index 016b9a6e..00000000 Binary files a/data/hand2.png and /dev/null differ diff --git a/data/left_ptr.png b/data/left_ptr.png deleted file mode 100644 index c42ac551..00000000 Binary files a/data/left_ptr.png and /dev/null differ diff --git a/data/left_side.png b/data/left_side.png deleted file mode 100644 index 2e2fab54..00000000 Binary files a/data/left_side.png and /dev/null differ diff --git a/data/right_side.png b/data/right_side.png deleted file mode 100644 index d49b1142..00000000 Binary files a/data/right_side.png and /dev/null differ diff --git a/data/sb_h_double_arrow.png b/data/sb_h_double_arrow.png deleted file mode 100644 index 8e55c0aa..00000000 Binary files a/data/sb_h_double_arrow.png and /dev/null differ diff --git a/data/sb_v_double_arrow.png b/data/sb_v_double_arrow.png deleted file mode 100644 index 822f622a..00000000 Binary files a/data/sb_v_double_arrow.png and /dev/null differ diff --git a/data/top_left_corner.png b/data/top_left_corner.png deleted file mode 100644 index 25c4e84d..00000000 Binary files a/data/top_left_corner.png and /dev/null differ diff --git a/data/top_right_corner.png b/data/top_right_corner.png deleted file mode 100644 index fb7727ca..00000000 Binary files a/data/top_right_corner.png and /dev/null differ diff --git a/data/top_side.png b/data/top_side.png deleted file mode 100644 index bf351f13..00000000 Binary files a/data/top_side.png and /dev/null differ diff --git a/data/xterm.png b/data/xterm.png deleted file mode 100644 index dc054c92..00000000 Binary files a/data/xterm.png and /dev/null differ