From 5d2f5946260a06caa5d5ca55a13726c99eb0c1f1 Mon Sep 17 00:00:00 2001 From: Consus Date: Sat, 2 Dec 2023 17:56:32 +0300 Subject: [PATCH] Implement cursor-shape-v1 protocol This protocol allows Wayland clients to request a buffer for a cursor shape from a compositor. Tested with foot. --- include/labwc.h | 1 + protocols/meson.build | 1 + src/input/cursor.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/include/labwc.h b/include/labwc.h index f288de35..86198a03 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -175,6 +175,7 @@ struct seat { struct wl_listener swipe_end; struct wl_listener request_cursor; + struct wl_listener request_set_shape; struct wl_listener request_set_selection; struct wl_listener request_set_primary_selection; diff --git a/protocols/meson.build b/protocols/meson.build index d2f7fc7e..527f9d4c 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -16,6 +16,7 @@ wayland_scanner_server = generator( server_protocols = [ wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml', wl_protocol_dir / 'unstable/pointer-constraints/pointer-constraints-unstable-v1.xml', + wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', wl_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml', 'wlr-layer-shell-unstable-v1.xml', 'wlr-input-inhibitor-unstable-v1.xml', diff --git a/src/input/cursor.c b/src/input/cursor.c index a98866dc..cb3f67bc 100644 --- a/src/input/cursor.c +++ b/src/input/cursor.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include "action.h" @@ -22,6 +23,8 @@ #include "ssd.h" #include "view.h" +#define LAB_CURSOR_SHAPE_V1_VERSION 1 + static const char * const *cursor_names = NULL; /* Usual cursor names */ @@ -158,6 +161,33 @@ request_cursor_notify(struct wl_listener *listener, void *data) } } +static void +request_set_shape_notify(struct wl_listener *listener, void *data) +{ + struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; + const char *shape_name = wlr_cursor_shape_v1_name(event->shape); + struct seat *seat = wl_container_of(listener, seat, request_set_shape); + struct wlr_seat_client *focused_client = seat->seat->pointer_state.focused_client; + + /* Prevent setting a cursor image when moving or resizing */ + if (seat->server->input_mode != LAB_INPUT_STATE_PASSTHROUGH) { + return; + } + + /* + * This can be sent by any client, so we check to make sure this one + * actually has pointer focus first. + */ + if (event->seat_client != focused_client) { + wlr_log(WLR_INFO, "seat client %p != focused client %p", + event->seat_client, focused_client); + return; + } + + wlr_log(WLR_DEBUG, "set xcursor to shape %s", shape_name); + wlr_cursor_set_xcursor(seat->cursor, seat->xcursor_manager, shape_name); +} + static void request_set_selection_notify(struct wl_listener *listener, void *data) { @@ -1225,6 +1255,18 @@ cursor_init(struct seat *seat) seat->request_cursor.notify = request_cursor_notify; wl_signal_add(&seat->seat->events.request_set_cursor, &seat->request_cursor); + + struct wlr_cursor_shape_manager_v1 *cursor_shape_manager = + wlr_cursor_shape_manager_v1_create(seat->server->wl_display, + LAB_CURSOR_SHAPE_V1_VERSION); + if (!cursor_shape_manager) { + wlr_log(WLR_ERROR, "unable to create cursor_shape interface"); + exit(EXIT_FAILURE); + } + seat->request_set_shape.notify = request_set_shape_notify; + wl_signal_add(&cursor_shape_manager->events.request_set_shape, + &seat->request_set_shape); + seat->request_set_selection.notify = request_set_selection_notify; wl_signal_add(&seat->seat->events.request_set_selection, &seat->request_set_selection); @@ -1249,6 +1291,7 @@ void cursor_finish(struct seat *seat) touch_finish(seat); wl_list_remove(&seat->request_cursor.link); + wl_list_remove(&seat->request_set_shape.link); wl_list_remove(&seat->request_set_selection.link); wlr_xcursor_manager_destroy(seat->xcursor_manager);