From a1d455b0c52bb7315426471b97acc7e8aea3fdf3 Mon Sep 17 00:00:00 2001 From: Andri Yngvason Date: Tue, 14 Jul 2020 20:44:18 +0000 Subject: [PATCH] pointer: Set cursor on pointer enter --- include/pointer.h | 6 +++++ meson.build | 2 ++ src/pointer.c | 63 +++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/include/pointer.h b/include/pointer.h index 469f154..cca04e7 100644 --- a/include/pointer.h +++ b/include/pointer.h @@ -18,6 +18,8 @@ #include +struct wl_cursor_theme; + enum pointer_button_mask { POINTER_BUTTON_LEFT = 1 << 0, POINTER_BUTTON_MIDDLE = 1 << 1, @@ -29,8 +31,12 @@ struct pointer { struct wl_pointer* wl_pointer; struct wl_list link; + uint32_t serial; enum pointer_button_mask pressed; wl_fixed_t x, y; + + struct wl_cursor_theme* cursor_theme; + struct wl_surface* cursor_surface; }; struct pointer_collection { diff --git a/meson.build b/meson.build index 55e3904..8a4a8d8 100644 --- a/meson.build +++ b/meson.build @@ -30,6 +30,7 @@ librt = cc.find_library('rt', required: false) xkbcommon = dependency('xkbcommon') pixman = dependency('pixman-1') wayland_client = dependency('wayland-client') +wayland_cursor = dependency('wayland-cursor') libvncclient = dependency('libvncclient') aml_project = subproject('aml', required: false) @@ -60,6 +61,7 @@ dependencies = [ pixman, aml, wayland_client, + wayland_cursor, libvncclient, client_protos, ] diff --git a/src/pointer.c b/src/pointer.c index c414c0b..18d5078 100644 --- a/src/pointer.c +++ b/src/pointer.c @@ -19,10 +19,30 @@ #include #include #include +#include #include #include "pointer.h" +extern struct wl_shm* wl_shm; +extern struct wl_compositor* wl_compositor; + +static struct wl_cursor_theme* pointer_load_cursor_theme(void) +{ + const char* xcursor_theme = getenv("XCURSOR_THEME"); + const char* xcursor_size_str = getenv("XCURSOR_SIZE"); + + unsigned long xcursor_size = 24; + if (xcursor_size_str) { + char* end; + unsigned long size = strtoul(xcursor_size_str, &end, 10); + if (!*end && *xcursor_size_str) + xcursor_size = size; + } + + return wl_cursor_theme_load(xcursor_theme, xcursor_size, wl_shm); +} + struct pointer* pointer_new(struct wl_pointer* wl_pointer) { struct pointer* self = calloc(1, sizeof(*self)); @@ -30,6 +50,8 @@ struct pointer* pointer_new(struct wl_pointer* wl_pointer) return NULL; self->wl_pointer = wl_pointer; + self->cursor_theme = pointer_load_cursor_theme(); + self->cursor_surface = wl_compositor_create_surface(wl_compositor); return self; } @@ -37,6 +59,8 @@ struct pointer* pointer_new(struct wl_pointer* wl_pointer) void pointer_destroy(struct pointer* self) { wl_pointer_destroy(self->wl_pointer); + wl_cursor_theme_destroy(self->cursor_theme); + wl_surface_destroy(self->cursor_surface); free(self); } @@ -75,17 +99,50 @@ struct pointer* pointer_collection_find_wl_pointer( return NULL; } +static void pointer_update_cursor(struct pointer* self) +{ + struct wl_cursor* cursor = wl_cursor_theme_get_cursor( + self->cursor_theme, "left_ptr"); + assert(cursor && cursor->image_count > 0); + + struct wl_cursor_image* image = cursor->images[0]; + + // TODO Set buffer scale + wl_surface_attach(self->cursor_surface, + wl_cursor_image_get_buffer(image), 0, 0); + wl_pointer_set_cursor(self->wl_pointer, self->serial, + self->cursor_surface, image->hotspot_x, + image->hotspot_y); + wl_surface_damage_buffer(self->cursor_surface, 0, 0, image->width, + image->height); + wl_surface_commit(self->cursor_surface); +} + static void pointer_enter(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t x, wl_fixed_t y) { - // TODO + struct pointer_collection* self = data; + struct pointer* pointer = + pointer_collection_find_wl_pointer(self, wl_pointer); + assert(pointer); + + pointer->serial = serial; + + pointer_update_cursor(pointer); } static void pointer_leave(void* data, struct wl_pointer* wl_pointer, uint32_t serial, struct wl_surface* surface) { - // TODO + struct pointer_collection* self = data; + struct pointer* pointer = + pointer_collection_find_wl_pointer(self, wl_pointer); + assert(pointer); + + pointer->serial = serial; + + // Do nothing? } static void pointer_motion(void* data, struct wl_pointer* wl_pointer, @@ -122,6 +179,8 @@ static void pointer_button(void* data, struct wl_pointer* wl_pointer, pointer_collection_find_wl_pointer(self, wl_pointer); assert(pointer); + pointer->serial = serial; + switch (button) { case BTN_LEFT: pointer_set_button_state(pointer, POINTER_BUTTON_LEFT, state);