Merge branch 'wayland-cursor-scale-for-4-6' into 'gtk-4-6'

wayland: Sanity check cursor image size

See merge request GNOME/gtk!4762
This commit is contained in:
Matthias Clasen 2022-05-27 11:48:21 +00:00
commit 92b6c59f80
2 changed files with 50 additions and 17 deletions

View File

@ -203,12 +203,16 @@ static struct wl_cursor *
wl_cursor_create_from_xcursor_images(XcursorImages *images, wl_cursor_create_from_xcursor_images(XcursorImages *images,
struct wl_cursor_theme *theme, struct wl_cursor_theme *theme,
const char *name, const char *name,
unsigned int load_size) unsigned int size,
unsigned int scale)
{ {
struct cursor *cursor; struct cursor *cursor;
struct cursor_image *image; struct cursor_image *image;
int i, size; int i, nbytes;
unsigned int load_size;
int width, height;
load_size = size * scale;
cursor = malloc(sizeof *cursor); cursor = malloc(sizeof *cursor);
if (!cursor) if (!cursor)
return NULL; return NULL;
@ -232,22 +236,37 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images,
image->theme = theme; image->theme = theme;
image->buffer = NULL; image->buffer = NULL;
image->image.width = images->images[i]->width; /* ensure that width and height are multiples of scale */
image->image.height = images->images[i]->height; 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_x = images->images[i]->xhot;
image->image.hotspot_y = images->images[i]->yhot; image->image.hotspot_y = images->images[i]->yhot;
image->image.delay = images->images[i]->delay; image->image.delay = images->images[i]->delay;
size = image->image.width * image->image.height * 4; nbytes = image->image.width * image->image.height * 4;
image->offset = shm_pool_allocate(theme->pool, size); image->offset = shm_pool_allocate(theme->pool, nbytes);
if (image->offset < 0) { if (image->offset < 0) {
free(image); free(image);
break; break;
} }
/* copy pixels to shm pool */ /* copy pixels to shm pool */
memcpy(theme->pool->data + image->offset, /* pad at the right and bottom with transparent pixels */
images->images[i]->pixels, size); 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);
}
cursor->total_delay += image->image.delay; cursor->total_delay += image->image.delay;
cursor->cursor.images[i] = (struct wl_cursor_image *) image; cursor->cursor.images[i] = (struct wl_cursor_image *) image;
} }
@ -264,20 +283,23 @@ wl_cursor_create_from_xcursor_images(XcursorImages *images,
} }
static void static void
load_cursor(struct wl_cursor_theme *theme, const char *name, unsigned int size) load_cursor(struct wl_cursor_theme *theme,
const char *name,
unsigned int size,
unsigned int scale)
{ {
XcursorImages *images; XcursorImages *images;
struct wl_cursor *cursor; struct wl_cursor *cursor;
char *path; char *path;
path = g_strconcat (theme->path, "/", name, NULL); path = g_strconcat (theme->path, "/", name, NULL);
images = xcursor_load_images (path, size); images = xcursor_load_images (path, size * scale);
g_free (path); g_free (path);
if (!images) if (!images)
return; return;
cursor = wl_cursor_create_from_xcursor_images(images, theme, name, size); cursor = wl_cursor_create_from_xcursor_images(images, theme, name, size, scale);
if (cursor) { if (cursor) {
theme->cursor_count++; theme->cursor_count++;
@ -373,7 +395,7 @@ wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
return theme->cursors[i]; return theme->cursors[i];
} }
load_cursor (theme, name, size); load_cursor (theme, name, theme->size, scale);
if (i < theme->cursor_count) { if (i < theme->cursor_count) {
if (size == theme->cursors[i]->size && if (size == theme->cursors[i]->size &&

View File

@ -178,6 +178,7 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
if (c) if (c)
{ {
struct wl_cursor_image *image; struct wl_cursor_image *image;
int cursor_scale;
if (image_index >= c->image_count) if (image_index >= c->image_count)
{ {
@ -189,12 +190,22 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
image = c->images[image_index]; image = c->images[image_index];
*hotspot_x = image->hotspot_x / desired_scale; cursor_scale = desired_scale;
*hotspot_y = image->hotspot_y / desired_scale; if ((image->width % cursor_scale != 0) ||
(image->height % cursor_scale != 0))
{
g_warning (G_STRLOC " cursor image size (%dx%d) not an integer"
"multiple of scale (%d)", image->width, image->height,
cursor_scale);
cursor_scale = 1;
}
*width = image->width / desired_scale; *hotspot_x = image->hotspot_x / cursor_scale;
*height = image->height / desired_scale; *hotspot_y = image->hotspot_y / cursor_scale;
*scale = desired_scale;
*width = image->width / cursor_scale;
*height = image->height / cursor_scale;
*scale = cursor_scale;
return wl_cursor_image_get_buffer (image); return wl_cursor_image_get_buffer (image);
} }