wayland: Redo cursor loading
Stop using a viewporter to scale cursors. Instead, just pass the surface scale to the cursor loading code, and take the buffer dimensions and hotspot that it returns, unchanged. This avoids problems with cursor themes like Breeze, where buffer dimensions are different from the nominal cursor size. Make the cursor loading code take a floating point scale, and return the closest sized cursor that it can find.
This commit is contained in:
@@ -208,21 +208,16 @@ wl_cursor_destroy(struct wl_cursor *cursor)
|
||||
static struct wl_cursor *
|
||||
wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
const char *name,
|
||||
unsigned int size,
|
||||
unsigned int scale)
|
||||
unsigned int size)
|
||||
{
|
||||
char *path;
|
||||
XcursorImages *images;
|
||||
struct wl_cursor *cursor;
|
||||
struct cursor_image *image;
|
||||
int i, nbytes;
|
||||
unsigned int load_size;
|
||||
int load_scale = 1;
|
||||
|
||||
load_size = size * scale;
|
||||
|
||||
path = g_strconcat (theme->path, "/", name, NULL);
|
||||
images = xcursor_load_images (path, load_size);
|
||||
images = xcursor_load_images (path, size);
|
||||
|
||||
if (!images)
|
||||
{
|
||||
@@ -230,14 +225,6 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
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);
|
||||
@@ -255,7 +242,7 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
}
|
||||
|
||||
cursor->name = strdup(name);
|
||||
cursor->size = load_size;
|
||||
cursor->size = images->images[0]->size;
|
||||
|
||||
for (i = 0; i < images->nimage; i++) {
|
||||
image = malloc(sizeof *image);
|
||||
@@ -265,10 +252,10 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
image->theme = theme;
|
||||
image->buffer = NULL;
|
||||
|
||||
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.width = images->images[i]->width;
|
||||
image->image.height = images->images[i]->height;
|
||||
image->image.hotspot_x = images->images[i]->xhot;
|
||||
image->image.hotspot_y = images->images[i]->yhot;
|
||||
image->image.delay = images->images[i]->delay;
|
||||
|
||||
nbytes = image->image.width * image->image.height * 4;
|
||||
@@ -278,24 +265,9 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
break;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
/* copy pixels to shm pool */
|
||||
memcpy(theme->pool->data + image->offset,
|
||||
images->images[i]->pixels, nbytes);
|
||||
cursor->images[i] = (struct wl_cursor_image *) image;
|
||||
}
|
||||
cursor->image_count = i;
|
||||
@@ -316,12 +288,11 @@ wl_cursor_create_from_xcursor_images(struct wl_cursor_theme *theme,
|
||||
static void
|
||||
load_cursor(struct wl_cursor_theme *theme,
|
||||
const char *name,
|
||||
unsigned int size,
|
||||
unsigned int scale)
|
||||
unsigned int size)
|
||||
{
|
||||
struct wl_cursor *cursor;
|
||||
|
||||
cursor = wl_cursor_create_from_xcursor_images(theme, name, size, scale);
|
||||
cursor = wl_cursor_create_from_xcursor_images(theme, name, size);
|
||||
|
||||
if (cursor) {
|
||||
theme->cursor_count++;
|
||||
@@ -405,12 +376,12 @@ wl_cursor_theme_destroy(struct wl_cursor_theme *theme)
|
||||
struct wl_cursor *
|
||||
wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
|
||||
const char *name,
|
||||
unsigned int scale)
|
||||
float scale)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int size;
|
||||
|
||||
size = theme->size * scale;
|
||||
size = ceil (theme->size * scale);
|
||||
|
||||
for (i = 0; i < theme->cursor_count; i++) {
|
||||
if (size == theme->cursors[i]->size &&
|
||||
@@ -418,11 +389,10 @@ wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
|
||||
return theme->cursors[i];
|
||||
}
|
||||
|
||||
load_cursor (theme, name, theme->size, scale);
|
||||
load_cursor (theme, name, size);
|
||||
|
||||
if (i < theme->cursor_count) {
|
||||
if (size == theme->cursors[i]->size &&
|
||||
strcmp (name, theme->cursors[theme->cursor_count - 1]->name) == 0)
|
||||
if (strcmp (name, theme->cursors[theme->cursor_count - 1]->name) == 0)
|
||||
return theme->cursors[theme->cursor_count - 1];
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ wl_cursor_theme_destroy(struct wl_cursor_theme *theme);
|
||||
struct wl_cursor *
|
||||
wl_cursor_theme_get_cursor(struct wl_cursor_theme *theme,
|
||||
const char *name,
|
||||
unsigned int scale);
|
||||
float scale);
|
||||
|
||||
struct wl_buffer *
|
||||
wl_cursor_image_get_buffer(struct wl_cursor_image *image);
|
||||
|
||||
@@ -119,7 +119,7 @@ name_fallback (const char *name)
|
||||
static struct wl_cursor *
|
||||
gdk_wayland_cursor_load_for_name (GdkWaylandDisplay *display_wayland,
|
||||
struct wl_cursor_theme *theme,
|
||||
int scale,
|
||||
float scale,
|
||||
const char *name)
|
||||
{
|
||||
struct wl_cursor *c;
|
||||
@@ -156,35 +156,30 @@ struct wl_buffer *
|
||||
_gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
|
||||
GdkCursor *cursor,
|
||||
double desired_scale,
|
||||
gboolean use_viewporter,
|
||||
guint image_index,
|
||||
int *hotspot_x,
|
||||
int *hotspot_y,
|
||||
int *width,
|
||||
int *height,
|
||||
double *scale)
|
||||
int *height)
|
||||
{
|
||||
GdkTexture *texture;
|
||||
|
||||
if (gdk_cursor_get_name (cursor))
|
||||
{
|
||||
struct wl_cursor *c;
|
||||
int scale_factor;
|
||||
|
||||
if (g_str_equal (gdk_cursor_get_name (cursor), "none"))
|
||||
{
|
||||
*hotspot_x = *hotspot_y = 0;
|
||||
*width = *height = 0;
|
||||
*scale = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
scale_factor = (int) ceil (desired_scale);
|
||||
|
||||
c = gdk_wayland_cursor_load_for_name (display,
|
||||
display->cursor_theme,
|
||||
scale_factor,
|
||||
desired_scale,
|
||||
gdk_cursor_get_name (cursor));
|
||||
|
||||
if (c && c->image_count > 0)
|
||||
{
|
||||
struct wl_cursor_image *image;
|
||||
@@ -199,22 +194,10 @@ _gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
|
||||
|
||||
image = c->images[image_index];
|
||||
|
||||
*width = display->cursor_theme_size;
|
||||
*height = display->cursor_theme_size;
|
||||
*scale = image->width / (double) *width;
|
||||
*hotspot_x = image->hotspot_x / scale_factor;
|
||||
*hotspot_y = image->hotspot_y / scale_factor;
|
||||
|
||||
if (*scale != scale_factor && !use_viewporter)
|
||||
{
|
||||
g_warning (G_STRLOC " cursor image size (%d) not an integer "
|
||||
"multiple of theme size (%d)", image->width, *width);
|
||||
*width = image->width;
|
||||
*height = image->height;
|
||||
*hotspot_x = image->hotspot_x;
|
||||
*hotspot_y = image->hotspot_y;
|
||||
*scale = 1;
|
||||
}
|
||||
*width = image->width;
|
||||
*height = image->height;
|
||||
*hotspot_x = image->hotspot_x;
|
||||
*hotspot_y = image->hotspot_y;
|
||||
|
||||
return wl_cursor_image_get_buffer (image);
|
||||
}
|
||||
@@ -248,7 +231,6 @@ from_texture:
|
||||
*hotspot_y = gdk_cursor_get_hotspot_y (cursor);
|
||||
*width = gdk_texture_get_width (texture);
|
||||
*height = gdk_texture_get_height (texture);
|
||||
*scale = 1;
|
||||
|
||||
cairo_surface_reference (surface);
|
||||
buffer = _gdk_wayland_shm_surface_get_wl_buffer (surface);
|
||||
@@ -260,14 +242,9 @@ from_texture:
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!use_viewporter)
|
||||
*scale = ceil (desired_scale);
|
||||
else
|
||||
*scale = desired_scale;
|
||||
|
||||
texture = gdk_cursor_get_texture_for_size (cursor,
|
||||
display->cursor_theme_size,
|
||||
*scale,
|
||||
desired_scale,
|
||||
width,
|
||||
height,
|
||||
hotspot_x,
|
||||
@@ -302,11 +279,9 @@ from_texture:
|
||||
return _gdk_wayland_cursor_get_buffer (display,
|
||||
gdk_cursor_get_fallback (cursor),
|
||||
desired_scale,
|
||||
use_viewporter,
|
||||
image_index,
|
||||
hotspot_x, hotspot_y,
|
||||
width, height,
|
||||
scale);
|
||||
width, height);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -62,7 +62,6 @@ struct _GdkWaylandPointerData {
|
||||
uint32_t grab_time;
|
||||
|
||||
struct wl_surface *pointer_surface;
|
||||
struct wp_viewport *pointer_surface_viewport;
|
||||
guint cursor_is_default: 1;
|
||||
GdkCursor *cursor;
|
||||
guint cursor_timeout_id;
|
||||
|
||||
@@ -261,26 +261,19 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
|
||||
gdk_wayland_device_get_pointer (wayland_device);
|
||||
struct wl_buffer *buffer;
|
||||
int x, y, w, h;
|
||||
double scale;
|
||||
guint next_image_index, next_image_delay;
|
||||
gboolean retval = G_SOURCE_REMOVE;
|
||||
GdkWaylandTabletData *tablet;
|
||||
gboolean use_viewport = FALSE;
|
||||
|
||||
tablet = gdk_wayland_seat_find_tablet (seat, device);
|
||||
|
||||
if (pointer->pointer_surface_viewport &&
|
||||
g_getenv ("USE_POINTER_VIEWPORT"))
|
||||
use_viewport = TRUE;
|
||||
|
||||
if (pointer->cursor)
|
||||
{
|
||||
buffer = _gdk_wayland_cursor_get_buffer (GDK_WAYLAND_DISPLAY (seat->display),
|
||||
pointer->cursor,
|
||||
pointer->current_output_scale,
|
||||
use_viewport,
|
||||
pointer->cursor_image_index,
|
||||
&x, &y, &w, &h, &scale);
|
||||
&x, &y, &w, &h);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -317,17 +310,6 @@ gdk_wayland_device_update_surface_cursor (GdkDevice *device)
|
||||
if (buffer)
|
||||
{
|
||||
wl_surface_attach (pointer->pointer_surface, buffer, 0, 0);
|
||||
if (use_viewport)
|
||||
{
|
||||
wp_viewport_set_source (pointer->pointer_surface_viewport,
|
||||
wl_fixed_from_int (0),
|
||||
wl_fixed_from_int (0),
|
||||
wl_fixed_from_double (w * scale),
|
||||
wl_fixed_from_double (h * scale));
|
||||
wp_viewport_set_destination (pointer->pointer_surface_viewport, w, h);
|
||||
}
|
||||
else if (wl_surface_get_version (pointer->pointer_surface) >= WL_SURFACE_SET_BUFFER_SCALE_SINCE_VERSION)
|
||||
wl_surface_set_buffer_scale (pointer->pointer_surface, scale);
|
||||
wl_surface_damage (pointer->pointer_surface, 0, 0, w, h);
|
||||
wl_surface_commit (pointer->pointer_surface);
|
||||
}
|
||||
|
||||
@@ -117,13 +117,11 @@ void gdk_wayland_display_system_bell (GdkDisplay *display,
|
||||
struct wl_buffer *_gdk_wayland_cursor_get_buffer (GdkWaylandDisplay *display,
|
||||
GdkCursor *cursor,
|
||||
double desired_scale,
|
||||
gboolean use_viewporter,
|
||||
guint image_index,
|
||||
int *hotspot_x,
|
||||
int *hotspot_y,
|
||||
int *w,
|
||||
int *h,
|
||||
double *scale);
|
||||
int *h);
|
||||
guint _gdk_wayland_cursor_get_next_image_index (GdkWaylandDisplay *display,
|
||||
GdkCursor *cursor,
|
||||
guint scale,
|
||||
|
||||
@@ -3894,7 +3894,6 @@ gdk_wayland_pointer_data_finalize (GdkWaylandPointerData *pointer)
|
||||
g_clear_object (&pointer->cursor);
|
||||
wl_surface_destroy (pointer->pointer_surface);
|
||||
g_slist_free (pointer->pointer_surface_outputs);
|
||||
g_clear_pointer (&pointer->pointer_surface_viewport, wp_viewport_destroy);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -4261,9 +4260,6 @@ init_pointer_data (GdkWaylandPointerData *pointer_data,
|
||||
wl_surface_add_listener (pointer_data->pointer_surface,
|
||||
&pointer_surface_listener,
|
||||
logical_device);
|
||||
|
||||
if (display_wayland->viewporter)
|
||||
pointer_data->pointer_surface_viewport = wp_viewporter_get_viewport (display_wayland->viewporter, pointer_data->pointer_surface);
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user