From 0b223c16f3abda5e47bfccaa3f0237671301e1d0 Mon Sep 17 00:00:00 2001 From: MoetaYuko Date: Sat, 22 Apr 2023 22:40:03 +0800 Subject: [PATCH] Wayland: Apply scaling to cursor surface Loading cursor theme and creating cursor surface are postponed to wayland_pointer_enter because we don't know the display scale in the early wayland_display_setup. Partially fixes #45 --- include/wayland-internal.h | 1 + source/wayland/display.c | 83 ++++++++++++++++++++++++-------------- 2 files changed, 54 insertions(+), 30 deletions(-) diff --git a/include/wayland-internal.h b/include/wayland-internal.h index f6e6101bd..cf475ee97 100644 --- a/include/wayland-internal.h +++ b/include/wayland-internal.h @@ -56,6 +56,7 @@ typedef struct { struct wl_cursor_image *image; struct wl_surface *surface; struct wl_callback *frame_cb; + guint scale; } cursor; GHashTable *seats; GHashTable *seats_by_name; diff --git a/source/wayland/display.c b/source/wayland/display.c index 0293ef440..c4240b0a0 100644 --- a/source/wayland/display.c +++ b/source/wayland/display.c @@ -490,6 +490,8 @@ static const struct wl_keyboard_listener wayland_keyboard_listener = { .repeat_info = wayland_keyboard_repeat_info, }; +static gboolean wayland_cursor_reload_theme(guint scale); + static void wayland_cursor_set_image(int i) { struct wl_buffer *buffer; struct wl_cursor_image *image; @@ -497,6 +499,7 @@ static void wayland_cursor_set_image(int i) { wayland->cursor.image = image; buffer = wl_cursor_image_get_buffer(wayland->cursor.image); + wl_surface_set_buffer_scale(wayland->cursor.surface, wayland->scale); wl_surface_attach(wayland->cursor.surface, buffer, 0, 0); wl_surface_damage(wayland->cursor.surface, 0, 0, wayland->cursor.image->width, wayland->cursor.image->height); @@ -592,8 +595,11 @@ static void wayland_pointer_enter(void *data, struct wl_pointer *pointer, wl_fixed_t x, wl_fixed_t y) { wayland_seat *self = data; - if (wayland->cursor.surface == NULL) { + if (!wayland_cursor_reload_theme(wayland->scale)) return; + + if (wayland->cursor.surface == NULL) { + wayland->cursor.surface = wl_compositor_create_surface(wayland->compositor); } if (wayland->cursor.cursor->image_count < 2) { @@ -602,9 +608,10 @@ static void wayland_pointer_enter(void *data, struct wl_pointer *pointer, wayland_cursor_frame_callback(wayland, wayland->cursor.frame_cb, 0); } - wl_pointer_set_cursor(self->pointer, serial, wayland->cursor.surface, - wayland->cursor.image->hotspot_x, - wayland->cursor.image->hotspot_y); + wl_pointer_set_cursor( + self->pointer, serial, wayland->cursor.surface, + wayland->cursor.image->hotspot_x / wayland->cursor.scale, + wayland->cursor.image->hotspot_y / wayland->cursor.scale); } static void wayland_pointer_leave(void *data, struct wl_pointer *pointer, @@ -1121,6 +1128,7 @@ static void wayland_registry_handle_global_remove(void *data, wayland->cursor.image = NULL; wayland->cursor.cursor = NULL; wayland->cursor.theme = NULL; + wayland->cursor.scale = 0; } GHashTableIter iter; @@ -1182,6 +1190,47 @@ static gboolean wayland_error(gpointer user_data) { return G_SOURCE_REMOVE; } +static gboolean wayland_cursor_reload_theme(guint scale) { + if (wayland->cursor.theme != NULL) { + if (wayland->cursor.scale == scale) + return TRUE; + + wl_cursor_theme_destroy(wayland->cursor.theme); + wayland->cursor.theme = NULL; + wayland->cursor.cursor = NULL; + } + + guint64 cursor_size = 24; + char *env_cursor_size = (char *)g_getenv("XCURSOR_SIZE"); + if (env_cursor_size && strlen(env_cursor_size) > 0) { + guint64 size = g_ascii_strtoull(env_cursor_size, NULL, 10); + if (0 < size && size < G_MAXUINT64) { + cursor_size = size; + } + } + cursor_size *= scale; + + wayland->cursor.theme = + wl_cursor_theme_load(wayland->cursor.theme_name, cursor_size, wayland->shm); + if (wayland->cursor.theme != NULL) { + const char *const *cname = (const char *const *)wayland->cursor.name; + for (cname = (cname != NULL) ? cname : wayland_cursor_names; + (wayland->cursor.cursor == NULL) && (*cname != NULL); ++cname) { + wayland->cursor.cursor = + wl_cursor_theme_get_cursor(wayland->cursor.theme, *cname); + } + if (wayland->cursor.cursor == NULL) { + wl_cursor_theme_destroy(wayland->cursor.theme); + wayland->cursor.theme = NULL; + return FALSE; + } else { + wayland->cursor.scale = scale; + return TRUE; + } + } + return FALSE; +} + static gboolean wayland_display_setup(GMainLoop *main_loop, NkBindings *bindings) { wayland->main_loop = main_loop; @@ -1221,32 +1270,6 @@ static gboolean wayland_display_setup(GMainLoop *main_loop, return FALSE; } - guint64 cursor_size = 24; - char *env_cursor_size = (char *)g_getenv("XCURSOR_SIZE"); - if (env_cursor_size && strlen(env_cursor_size) > 0) { - guint64 size = g_ascii_strtoull(env_cursor_size, NULL, 10); - if (0 < size && size < G_MAXUINT64) { - cursor_size = size; - } - } - wayland->cursor.theme = - wl_cursor_theme_load(wayland->cursor.theme_name, cursor_size, wayland->shm); - if (wayland->cursor.theme != NULL) { - const char *const *cname = (const char *const *)wayland->cursor.name; - for (cname = (cname != NULL) ? cname : wayland_cursor_names; - (wayland->cursor.cursor == NULL) && (*cname != NULL); ++cname) { - wayland->cursor.cursor = - wl_cursor_theme_get_cursor(wayland->cursor.theme, *cname); - } - if (wayland->cursor.cursor == NULL) { - wl_cursor_theme_destroy(wayland->cursor.theme); - wayland->cursor.theme = NULL; - } else { - wayland->cursor.surface = - wl_compositor_create_surface(wayland->compositor); - } - } - wayland->surface = wl_compositor_create_surface(wayland->compositor); wayland->bindings_seat = nk_bindings_seat_new(bindings, XKB_CONTEXT_NO_FLAGS);