diff --git a/gdk/wayland/cursor/wayland-cursor.c b/gdk/wayland/cursor/wayland-cursor.c index 071824d914..4be8f9a4d4 100644 --- a/gdk/wayland/cursor/wayland-cursor.c +++ b/gdk/wayland/cursor/wayland-cursor.c @@ -200,27 +200,51 @@ wl_cursor_destroy(struct wl_cursor *cursor) } static struct wl_cursor * -wl_cursor_create_from_xcursor_images(XcursorImages *images, - struct wl_cursor_theme *theme, +wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme, const char *name, unsigned int size, unsigned int scale) { + char *path; + XcursorImages *images; struct cursor *cursor; struct cursor_image *image; int i, nbytes; unsigned int load_size; - int width, height; + int load_scale = 1; load_size = size * scale; + + path = g_strconcat (theme->path, "/", name, NULL); + images = xcursor_load_images (path, load_size); + + if (!images) + { + g_free (path); + return NULL; + } + + if (images->images[0]->width != load_size || + images->images[0]->height != load_size) + { + xcursor_images_destroy (images); + images = xcursor_load_images (path, size); + load_scale = scale; + } + + g_free (path); + cursor = malloc(sizeof *cursor); - if (!cursor) + if (!cursor) { + xcursor_images_destroy (images); return NULL; + } cursor->cursor.images = malloc(images->nimage * sizeof cursor->cursor.images[0]); if (!cursor->cursor.images) { free(cursor); + xcursor_images_destroy (images); return NULL; } @@ -236,19 +260,10 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images, image->theme = theme; image->buffer = NULL; - /* ensure that width and height are multiples of scale */ - width = images->images[i]->width; - if ((width % scale) != 0) - width = (width / scale + 1) * scale; - - height = images->images[i]->height; - if ((height % scale) != 0) - height = (height / scale + 1) * scale; - - image->image.width = width; - image->image.height = height; - image->image.hotspot_x = images->images[i]->xhot; - image->image.hotspot_y = images->images[i]->yhot; + image->image.width = images->images[i]->width * load_scale; + image->image.height = images->images[i]->height * load_scale; + image->image.hotspot_x = images->images[i]->xhot * load_scale; + image->image.hotspot_y = images->images[i]->yhot * load_scale; image->image.delay = images->images[i]->delay; nbytes = image->image.width * image->image.height * 4; @@ -258,15 +273,24 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images, break; } - /* copy pixels to shm pool */ - /* pad at the right and bottom with transparent pixels */ - memset (theme->pool->data + image->offset, 0, nbytes); - for (int y = 0; y < height; y++) - { - memcpy(theme->pool->data + image->offset + y * width * 4, - images->images[i]->pixels + y * images->images[i]->width * 4, - images->images[i]->width * 4); - } + if (load_scale == 1) { + /* copy pixels to shm pool */ + memcpy(theme->pool->data + image->offset, + images->images[i]->pixels, nbytes); + } + else { + /* scale image up while copying it */ + for (int y = 0; y < image->image.height; y++) { + char *p = theme->pool->data + image->offset + y * image->image.width * 4; + char *q = ((char *)images->images[i]->pixels) + (y / load_scale) * images->images[i]->width * 4; + for (int x = 0; x < image->image.width; x++) { + p[4 * x] = q[4 * (x/load_scale)]; + p[4 * x + 1] = q[4 * (x/load_scale) + 1]; + p[4 * x + 2] = q[4 * (x/load_scale) + 2]; + p[4 * x + 3] = q[4 * (x/load_scale) + 3]; + } + } + } cursor->total_delay += image->image.delay; cursor->cursor.images[i] = (struct wl_cursor_image *) image; } @@ -276,9 +300,12 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images, free(cursor->cursor.name); free(cursor->cursor.images); free(cursor); + xcursor_images_destroy (images); return NULL; } + xcursor_images_destroy (images); + return &cursor->cursor; } @@ -288,18 +315,9 @@ load_cursor(struct wl_cursor_theme *theme, unsigned int size, unsigned int scale) { - XcursorImages *images; struct wl_cursor *cursor; - char *path; - path = g_strconcat (theme->path, "/", name, NULL); - images = xcursor_load_images (path, size * scale); - g_free (path); - - if (!images) - return; - - cursor = wl_cursor_create_from_xcursor_images(images, theme, name, size, scale); + cursor = wl_cursor_create_from_xcursor_images(theme, name, size, scale); if (cursor) { theme->cursor_count++; @@ -314,8 +332,6 @@ load_cursor(struct wl_cursor_theme *theme, theme->cursors[theme->cursor_count - 1] = cursor; } } - - xcursor_images_destroy (images); } /** Load a cursor theme to memory shared with the compositor