Skip to content

Commit

Permalink
wayland: add cursor-shape-v1 support
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Dudemanguy committed Jul 3, 2023
1 parent c8a54a8 commit fdc1b94
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 12 deletions.
8 changes: 8 additions & 0 deletions generated/wayland/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ if features['wayland_protocols_1_31']
protocols += [[wl_protocol_dir, 'staging/fractional-scale/fractional-scale-v1.xml']]
endif

# TODO: actually make this a 1.32 check
features += {'wayland_protocols_1_32': wayland['deps'][2].version().version_compare('>=1.31')}
if features['wayland_protocols_1_32']
# cursor-shape requires tablet v2 in order to link
protocols += [[wl_protocol_dir, 'staging/cursor-shape/cursor-shape-v1.xml']]
protocols += [[wl_protocol_dir, 'unstable/tablet/tablet-unstable-v2.xml']]
endif

foreach p: protocols
xml = join_paths(p)
wl_protocols_source += custom_target(xml.underscorify() + '_c',
Expand Down
70 changes: 58 additions & 12 deletions video/out/wayland_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1671,21 +1694,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);
Expand Down Expand Up @@ -1767,6 +1802,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;
Expand Down Expand Up @@ -2300,6 +2338,14 @@ void vo_wayland_uninit(struct vo *vo)
if (wl->current_output && wl->current_output->output)
wl_output_destroy(wl->current_output->output);

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

Expand Down
5 changes: 5 additions & 0 deletions video/out/wayland_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions wscript
Original file line number Diff line number Diff line change
Expand Up @@ -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()",
Expand Down
14 changes: 14 additions & 0 deletions wscript_build.py
Original file line number Diff line number Diff line change
Expand Up @@ -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")

Expand Down

0 comments on commit fdc1b94

Please sign in to comment.