From fce43c420e4fff2b8cbed5eee4dce740689df637 Mon Sep 17 00:00:00 2001 From: Rob Bradford Date: Mon, 8 Oct 2012 13:25:36 +0100 Subject: [PATCH] wayland: Use wl_cursor_theme to provide a buffer for the Wayland cursor This change switches to the new mechanism for loading a cursor into a buffer. It no longer relies on having a PNG stored in a known location and instead loads from the Wayland cursor theme. Signed-off-by: Rob Bradford --- clutter/wayland/clutter-backend-wayland.c | 174 +++------------------- clutter/wayland/clutter-backend-wayland.h | 4 + 2 files changed, 22 insertions(+), 156 deletions(-) diff --git a/clutter/wayland/clutter-backend-wayland.c b/clutter/wayland/clutter-backend-wayland.c index 3717d4fdf..56b5b5734 100644 --- a/clutter/wayland/clutter-backend-wayland.c +++ b/clutter/wayland/clutter-backend-wayland.c @@ -48,6 +48,7 @@ #include "cogl/clutter-stage-cogl.h" #include +#include #include #include @@ -76,6 +77,12 @@ clutter_backend_wayland_dispose (GObject *gobject) backend_wayland->cursor_buffer = NULL; } + if (backend_wayland->cursor_theme) + { + wl_cursor_theme_destroy (backend_wayland->cursor_theme); + backend_wayland->cursor_theme = NULL; + } + G_OBJECT_CLASS (clutter_backend_wayland_parent_class)->dispose (gobject); } @@ -277,175 +284,30 @@ clutter_backend_wayland_class_init (ClutterBackendWaylandClass *klass) backend_class->get_display = clutter_backend_wayland_get_display; } -/* - * clutter_backend_wayland_load_cursor and the two functions below were copied - * from GTK+ and adapted for clutter - */ -static void -set_pixbuf (GdkPixbuf *pixbuf, - unsigned char *map, - int width, - int height) -{ - int stride, i, n_channels; - unsigned char *pixels, *end, *argb_pixels, *s, *d; - - stride = gdk_pixbuf_get_rowstride (pixbuf); - pixels = gdk_pixbuf_get_pixels (pixbuf); - n_channels = gdk_pixbuf_get_n_channels (pixbuf); - argb_pixels = map; - -#define MULT(_d,c,a,t) \ - do { t = c * a + 0x7f; _d = ((t >> 8) + t) >> 8; } while (0) - - if (n_channels == 4) - { - for (i = 0; i < height; i++) - { - s = pixels + i * stride; - end = s + width * 4; - d = argb_pixels + i * width * 4; - while (s < end) - { - unsigned int t; - - MULT(d[0], s[2], s[3], t); - MULT(d[1], s[1], s[3], t); - MULT(d[2], s[0], s[3], t); - d[3] = s[3]; - s += 4; - d += 4; - } - } - } - else if (n_channels == 3) - { - for (i = 0; i < height; i++) - { - s = pixels + i * stride; - end = s + width * 3; - d = argb_pixels + i * width * 4; - while (s < end) - { - d[0] = s[2]; - d[1] = s[1]; - d[2] = s[0]; - d[3] = 0xff; - s += 3; - d += 4; - } - } - } -} - -static struct wl_buffer * -create_cursor (ClutterBackendWayland *backend_wayland, - GdkPixbuf *pixbuf) -{ - int stride, fd; - char *filename; - GError *error = NULL; - struct wl_shm_pool *pool; - struct wl_buffer *buffer; - gint width, height; - gsize size; - unsigned char *map; - - width = gdk_pixbuf_get_width (pixbuf); - height = gdk_pixbuf_get_height (pixbuf); - stride = width * 4; - size = stride * height; - - fd = g_file_open_tmp ("wayland-shm-XXXXXX", &filename, &error); - if (fd < 0) - { - g_critical (G_STRLOC ": Opening temporary file failed: %s", error->message); - g_error_free (error); - return NULL; - } - - unlink (filename); - g_free (filename); - - if (ftruncate (fd, size) < 0) - { - g_critical (G_STRLOC ": Setting the size of temporary file failed: %s", g_strerror (errno)); - close (fd); - return NULL; - } - - map = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - - if (map == MAP_FAILED) - { - g_critical (G_STRLOC ": Memory mapping file failed: %s", g_strerror (errno)); - close (fd); - return NULL; - } - - set_pixbuf (pixbuf, map, width, height); - - pool = wl_shm_create_pool (backend_wayland->wayland_shm, fd, size); - close (fd); - buffer = wl_shm_pool_create_buffer (pool, - 0, - width, - height, - stride, - WL_SHM_FORMAT_ARGB8888); - wl_shm_pool_destroy (pool); - munmap (map, size); - - return buffer; -} - static void clutter_backend_wayland_load_cursor (ClutterBackendWayland *backend_wayland) { - const gchar * const *directories; - gint j; - GdkPixbuf *pixbuf = NULL; - GError *error = NULL; + struct wl_cursor *cursor; - directories = g_get_system_data_dirs(); + backend_wayland->cursor_theme = + wl_cursor_theme_load (NULL, /* default */ + 32, + backend_wayland->wayland_shm); - for (j = 0; directories[j] != NULL; j++) - { - gchar *filename; - filename = g_build_filename (directories[j], - "weston", - "left_ptr.png", - NULL); - if (g_file_test (filename, G_FILE_TEST_EXISTS)) - { - pixbuf = gdk_pixbuf_new_from_file (filename, &error); + cursor = wl_cursor_theme_get_cursor (backend_wayland->cursor_theme, + "left_ptr"); - if (error != NULL) - { - g_warning ("Failed to load cursor: %s: %s", - filename, error->message); - g_error_free (error); - return; - } - break; - } - } - - if (!pixbuf) - return; - - backend_wayland->cursor_buffer = create_cursor (backend_wayland, pixbuf); + backend_wayland->cursor_buffer = + wl_cursor_image_get_buffer (cursor->images[0]); if (backend_wayland->cursor_buffer) { - backend_wayland->cursor_x = 0; - backend_wayland->cursor_y = 0; + backend_wayland->cursor_x = cursor->images[0]->hotspot_x; + backend_wayland->cursor_y = cursor->images[0]->hotspot_y; } backend_wayland->cursor_surface = wl_compositor_create_surface (backend_wayland->wayland_compositor); - - g_object_unref (pixbuf); } static void diff --git a/clutter/wayland/clutter-backend-wayland.h b/clutter/wayland/clutter-backend-wayland.h index 5788a4590..5cbaa3bc8 100644 --- a/clutter/wayland/clutter-backend-wayland.h +++ b/clutter/wayland/clutter-backend-wayland.h @@ -32,6 +32,9 @@ #include #include +#include +#include + #include "clutter-backend-private.h" G_BEGIN_DECLS @@ -59,6 +62,7 @@ struct _ClutterBackendWayland struct wl_surface *cursor_surface; struct wl_buffer *cursor_buffer; struct wl_output *wayland_output; + struct wl_cursor_theme *cursor_theme; gint cursor_x, cursor_y; gint output_width, output_height;