diff --git a/generated/wayland/meson.build b/generated/wayland/meson.build index bf0138183e..ec2dc6e7f4 100644 --- a/generated/wayland/meson.build +++ b/generated/wayland/meson.build @@ -19,6 +19,12 @@ if features['wayland_protocols_1_31'] protocols += [[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml']] endif +features += {'wayland_protocols_1_32': wayland['deps'][2].version().version_compare('>=1.32')} +if features['wayland_protocols_1_32'] + protocols += [[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml'], + [wl_protocol_dir, 'unstable/tablet/tablet-unstable-v2.xml']] # required by cursor-shape +endif + foreach p: protocols xml = join_paths(p) wl_protocols_source += custom_target(xml.underscorify() + '_c', diff --git a/video/out/wayland_common.c b/video/out/wayland_common.c index 36dc0f6934..8f0e5838ac 100644 --- a/video/out/wayland_common.c +++ b/video/out/wayland_common.c @@ -51,6 +51,10 @@ #include "generated/wayland/fractional-scale-v1.h" #endif +#if HAVE_WAYLAND_PROTOCOLS_1_32 +#include "generated/wayland/cursor-shape-v1.h" +#endif + #if WAYLAND_VERSION_MAJOR > 1 || WAYLAND_VERSION_MINOR >= 22 #define HAVE_WAYLAND_1_22 #endif @@ -180,6 +184,7 @@ static int spawn_cursor(struct vo_wayland_state *wl); static void add_feedback(struct vo_wayland_feedback_pool *fback_pool, struct wp_presentation_feedback *fback); +static void get_shape_device(struct vo_wayland_state *wl); static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b); static void guess_focus(struct vo_wayland_state *wl); static void remove_feedback(struct vo_wayland_feedback_pool *fback_pool, @@ -482,6 +487,7 @@ static void seat_handle_caps(void *data, struct wl_seat *seat, if ((caps & WL_SEAT_CAPABILITY_POINTER) && !wl->pointer) { wl->pointer = wl_seat_get_pointer(seat); + get_shape_device(wl); wl_pointer_add_listener(wl->pointer, &pointer_listener, wl); } else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && wl->pointer) { wl_pointer_destroy(wl->pointer); @@ -1295,6 +1301,12 @@ static void registry_handle_add(void *data, struct wl_registry *reg, uint32_t id } #endif +#if HAVE_WAYLAND_PROTOCOLS_1_32 + if (!strcmp(interface, wp_cursor_shape_manager_v1_interface.name) && found++) { + wl->cursor_shape_manager = wl_registry_bind(reg, id, &wp_cursor_shape_manager_v1_interface, 1); + } +#endif + if (!strcmp(interface, wp_presentation_interface.name) && found++) { wl->presentation = wl_registry_bind(reg, id, &wp_presentation_interface, 1); wp_presentation_add_listener(wl->presentation, &pres_listener, wl); @@ -1529,7 +1541,18 @@ static int get_mods(struct vo_wayland_state *wl) return modifiers; } -static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b) { +static void get_shape_device(struct vo_wayland_state *wl) +{ +#if HAVE_WAYLAND_PROTOCOLS_1_32 + if (!wl->cursor_shape_device && wl->cursor_shape_manager) { + wl->cursor_shape_device = wp_cursor_shape_manager_v1_get_pointer(wl->cursor_shape_manager, + wl->pointer); + } +#endif +} + +static void greatest_common_divisor(struct vo_wayland_state *wl, int a, int b) +{ // euclidean algorithm int larger; int smaller; @@ -1673,21 +1696,33 @@ static void set_content_type(struct vo_wayland_state *wl) #endif } +static void set_cursor_shape(struct vo_wayland_state *wl) +{ +#if HAVE_WAYLAND_PROTOCOLS_1_32 + wp_cursor_shape_device_v1_set_shape(wl->cursor_shape_device, wl->pointer_id, + WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT); +#endif +} + static int set_cursor_visibility(struct vo_wayland_state *wl, bool on) { wl->cursor_visible = on; if (on) { - if (spawn_cursor(wl)) - return VO_FALSE; - struct wl_cursor_image *img = wl->default_cursor->images[0]; - struct wl_buffer *buffer = wl_cursor_image_get_buffer(img); - if (!buffer) - return VO_FALSE; - wl_pointer_set_cursor(wl->pointer, wl->pointer_id, wl->cursor_surface, - img->hotspot_x/wl->scaling, img->hotspot_y/wl->scaling); - wl_surface_set_buffer_scale(wl->cursor_surface, wl->scaling); - wl_surface_attach(wl->cursor_surface, buffer, 0, 0); - wl_surface_damage_buffer(wl->cursor_surface, 0, 0, img->width, img->height); + if (wl->cursor_shape_device) { + set_cursor_shape(wl); + } else { + if (spawn_cursor(wl)) + return VO_FALSE; + struct wl_cursor_image *img = wl->default_cursor->images[0]; + struct wl_buffer *buffer = wl_cursor_image_get_buffer(img); + if (!buffer) + return VO_FALSE; + wl_pointer_set_cursor(wl->pointer, wl->pointer_id, wl->cursor_surface, + img->hotspot_x/wl->scaling, img->hotspot_y/wl->scaling); + wl_surface_set_buffer_scale(wl->cursor_surface, wl->scaling); + wl_surface_attach(wl->cursor_surface, buffer, 0, 0); + wl_surface_damage_buffer(wl->cursor_surface, 0, 0, img->width, img->height); + } wl_surface_commit(wl->cursor_surface); } else { wl_pointer_set_cursor(wl->pointer, wl->pointer_id, NULL, 0, 0); @@ -1780,6 +1815,9 @@ static void set_window_bounds(struct vo_wayland_state *wl) static int spawn_cursor(struct vo_wayland_state *wl) { + /* Don't use this if we have cursor-shape. */ + if (wl->cursor_shape_device) + return 0; /* Reuse if size is identical */ if (!wl->pointer || wl->allocated_cursor_scale == wl->scaling) return 0; @@ -2315,6 +2353,14 @@ void vo_wayland_uninit(struct vo *vo) if (wl->subcompositor) wl_subcompositor_destroy(wl->subcompositor); +#if HAVE_WAYLAND_PROTOCOLS_1_32 + if (wl->cursor_shape_device) + wp_cursor_shape_device_v1_destroy(wl->cursor_shape_device); + + if (wl->cursor_shape_manager) + wp_cursor_shape_manager_v1_destroy(wl->cursor_shape_manager); +#endif + if (wl->cursor_surface) wl_surface_destroy(wl->cursor_surface); diff --git a/video/out/wayland_common.h b/video/out/wayland_common.h index 32394a24a0..1a26c7faaa 100644 --- a/video/out/wayland_common.h +++ b/video/out/wayland_common.h @@ -88,6 +88,11 @@ struct vo_wayland_state { void *content_type; int current_content_type; + /* cursor-shape */ + /* TODO: unvoid these if required wayland protocols is bumped to 1.32+ */ + void *cursor_shape_manager; + void *cursor_shape_device; + /* fractional-scale */ /* TODO: unvoid these if required wayland protocols is bumped to 1.31+ */ void *fractional_scale_manager; diff --git a/wscript b/wscript index d6f34717dd..758a9469ff 100644 --- a/wscript +++ b/wscript @@ -558,6 +558,11 @@ video_output_features = [ 'desc': 'wayland-protocols version 1.31+', 'deps': 'wayland', 'func': check_pkg_config('wayland-protocols >= 1.31'), + } , { + 'name': 'wayland-protocols-1-32', + 'desc': 'wayland-protocols version 1.32+', + 'deps': 'wayland', + 'func': check_pkg_config('wayland-protocols >= 1.32'), } , { 'name': 'memfd_create', 'desc': "Linux's memfd_create()", diff --git a/wscript_build.py b/wscript_build.py index 9650bf94d3..1de54698ea 100644 --- a/wscript_build.py +++ b/wscript_build.py @@ -163,6 +163,20 @@ def build(ctx): protocol = "staging/fractional-scale/fractional-scale-v1", target = "generated/wayland/fractional-scale-v1.h") + if ctx.dependency_satisfied('wayland-protocols-1-32'): + ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "staging/cursor-shape/cursor-shape-v1", + target = "generated/wayland/cursor-shape-v1.c") + ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "staging/cursor-shape/cursor-shape-v1", + target = "generated/wayland/cursor-shape-v1.h") + ctx.wayland_protocol_code(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "unstable/tablet/tablet-unstable-v2", + target = "generated/wayland/tablet-unstable-v2.c") + ctx.wayland_protocol_header(proto_dir = ctx.env.WL_PROTO_DIR, + protocol = "unstable/tablet/tablet-unstable-v2", + target = "generated/wayland/tablet-unstable-v2.h") + ctx(features = "ebml_header", target = "generated/ebml_types.h") ctx(features = "ebml_definitions", target = "generated/ebml_defs.inc")