1
0
mirror of https://github.com/mpv-player/mpv synced 2025-01-03 13:32:16 +00:00

wayland: add cursor-shape-v1 support

This protocol no longer requires us to draw a separate cursor surface
and all of that horrible stuff. We can just ask the compositor for the
default cursor instead since that's literally all mpv cares about.
This commit is contained in:
Dudemanguy 2023-05-19 17:07:25 -05:00
parent fc3e28f1e9
commit 589da09e5a
5 changed files with 88 additions and 12 deletions

View File

@ -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',

View File

@ -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);

View File

@ -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;

View File

@ -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()",

View File

@ -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")