summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnder Conselvan de Oliveira <ander.conselvan.de.oliveira@intel.com>2012-05-03 12:29:46 +0300
committerKristian Høgsberg <krh@bitplanet.net>2012-05-03 10:14:04 -0400
commit1493d2ae1cc8187684bb8f8939d0ec0335ed60f8 (patch)
treec4f14002bcefcf9e9fafddf01ee8d719618b4c4c
parentd51624f915bbb8c0ccb3e98f8f98c3325263f030 (diff)
downloadweston-1493d2ae1cc8187684bb8f8939d0ec0335ed60f8.tar.gz
weston-1493d2ae1cc8187684bb8f8939d0ec0335ed60f8.tar.bz2
weston-1493d2ae1cc8187684bb8f8939d0ec0335ed60f8.zip
window: use libXcursor for loading pointer images
-rw-r--r--clients/window.c214
-rw-r--r--configure.ac2
-rw-r--r--data/Makefile.am18
-rw-r--r--data/bottom_left_corner.pngbin1100 -> 0 bytes
-rw-r--r--data/bottom_right_corner.pngbin1033 -> 0 bytes
-rw-r--r--data/bottom_side.pngbin994 -> 0 bytes
-rw-r--r--data/dnd-copy.pngbin1244 -> 0 bytes
-rw-r--r--data/dnd-link.pngbin1321 -> 0 bytes
-rw-r--r--data/dnd-move.pngbin1213 -> 0 bytes
-rw-r--r--data/grabbing.pngbin1004 -> 0 bytes
-rw-r--r--data/hand1.pngbin1117 -> 0 bytes
-rw-r--r--data/hand2.pngbin1108 -> 0 bytes
-rw-r--r--data/left_ptr.pngbin1046 -> 0 bytes
-rw-r--r--data/left_side.pngbin1141 -> 0 bytes
-rw-r--r--data/right_side.pngbin1051 -> 0 bytes
-rw-r--r--data/sb_h_double_arrow.pngbin1287 -> 0 bytes
-rw-r--r--data/sb_v_double_arrow.pngbin1140 -> 0 bytes
-rw-r--r--data/top_left_corner.pngbin1251 -> 0 bytes
-rw-r--r--data/top_right_corner.pngbin1163 -> 0 bytes
-rw-r--r--data/top_side.pngbin1116 -> 0 bytes
-rw-r--r--data/xterm.pngbin615 -> 0 bytes
21 files changed, 120 insertions, 114 deletions
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 <xkbcommon/xkbcommon.h>
#include <X11/X.h>
+#include <X11/Xcursor/Xcursor.h>
#include <linux/input.h>
#include <wayland-client.h>
@@ -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
--- a/data/bottom_left_corner.png
+++ /dev/null
Binary files differ
diff --git a/data/bottom_right_corner.png b/data/bottom_right_corner.png
deleted file mode 100644
index 768e7778..00000000
--- a/data/bottom_right_corner.png
+++ /dev/null
Binary files differ
diff --git a/data/bottom_side.png b/data/bottom_side.png
deleted file mode 100644
index ac7c70e5..00000000
--- a/data/bottom_side.png
+++ /dev/null
Binary files differ
diff --git a/data/dnd-copy.png b/data/dnd-copy.png
deleted file mode 100644
index fd044ae1..00000000
--- a/data/dnd-copy.png
+++ /dev/null
Binary files differ
diff --git a/data/dnd-link.png b/data/dnd-link.png
deleted file mode 100644
index 5183bf9f..00000000
--- a/data/dnd-link.png
+++ /dev/null
Binary files differ
diff --git a/data/dnd-move.png b/data/dnd-move.png
deleted file mode 100644
index c3ccd6e6..00000000
--- a/data/dnd-move.png
+++ /dev/null
Binary files differ
diff --git a/data/grabbing.png b/data/grabbing.png
deleted file mode 100644
index 04694594..00000000
--- a/data/grabbing.png
+++ /dev/null
Binary files differ
diff --git a/data/hand1.png b/data/hand1.png
deleted file mode 100644
index c13aa36b..00000000
--- a/data/hand1.png
+++ /dev/null
Binary files differ
diff --git a/data/hand2.png b/data/hand2.png
deleted file mode 100644
index 016b9a6e..00000000
--- a/data/hand2.png
+++ /dev/null
Binary files differ
diff --git a/data/left_ptr.png b/data/left_ptr.png
deleted file mode 100644
index c42ac551..00000000
--- a/data/left_ptr.png
+++ /dev/null
Binary files differ
diff --git a/data/left_side.png b/data/left_side.png
deleted file mode 100644
index 2e2fab54..00000000
--- a/data/left_side.png
+++ /dev/null
Binary files differ
diff --git a/data/right_side.png b/data/right_side.png
deleted file mode 100644
index d49b1142..00000000
--- a/data/right_side.png
+++ /dev/null
Binary files differ
diff --git a/data/sb_h_double_arrow.png b/data/sb_h_double_arrow.png
deleted file mode 100644
index 8e55c0aa..00000000
--- a/data/sb_h_double_arrow.png
+++ /dev/null
Binary files differ
diff --git a/data/sb_v_double_arrow.png b/data/sb_v_double_arrow.png
deleted file mode 100644
index 822f622a..00000000
--- a/data/sb_v_double_arrow.png
+++ /dev/null
Binary files differ
diff --git a/data/top_left_corner.png b/data/top_left_corner.png
deleted file mode 100644
index 25c4e84d..00000000
--- a/data/top_left_corner.png
+++ /dev/null
Binary files differ
diff --git a/data/top_right_corner.png b/data/top_right_corner.png
deleted file mode 100644
index fb7727ca..00000000
--- a/data/top_right_corner.png
+++ /dev/null
Binary files differ
diff --git a/data/top_side.png b/data/top_side.png
deleted file mode 100644
index bf351f13..00000000
--- a/data/top_side.png
+++ /dev/null
Binary files differ
diff --git a/data/xterm.png b/data/xterm.png
deleted file mode 100644
index dc054c92..00000000
--- a/data/xterm.png
+++ /dev/null
Binary files differ