diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 1636588a..1e21c66f 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -145,4 +145,6 @@ uint32_t get_mouse_button(const char *name, char **error); const char *get_mouse_button_name(uint32_t button); +void handle_request_set_cursor_shape(struct wl_listener *listener, void *data); + #endif diff --git a/include/sway/server.h b/include/sway/server.h index 0e4ec2be..1eb308a4 100644 --- a/include/sway/server.h +++ b/include/sway/server.h @@ -120,6 +120,8 @@ struct sway_server { struct wl_listener xdg_activation_v1_request_activate; struct wl_listener xdg_activation_v1_new_token; + struct wl_listener request_set_cursor_shape; + struct wl_list pending_launcher_ctxs; // launcher_ctx::link // The timeout for transactions, after which a transaction is applied diff --git a/protocols/meson.build b/protocols/meson.build index e6fdec7d..b6fdec8c 100644 --- a/protocols/meson.build +++ b/protocols/meson.build @@ -13,6 +13,7 @@ protocols = [ wl_protocol_dir / 'unstable/tablet/tablet-unstable-v2.xml', wl_protocol_dir / 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml', wl_protocol_dir / 'staging/content-type/content-type-v1.xml', + wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', 'wlr-layer-shell-unstable-v1.xml', 'idle.xml', 'wlr-input-inhibitor-unstable-v1.xml', diff --git a/sway/input/cursor.c b/sway/input/cursor.c index f970e6a2..62c74d04 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -1467,3 +1468,26 @@ void sway_cursor_constrain(struct sway_cursor *cursor, wl_signal_add(&constraint->surface->events.commit, &cursor->constraint_commit); } + +void handle_request_set_cursor_shape(struct wl_listener *listener, void *data) { + const struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data; + struct sway_seat *seat = event->seat_client->seat->data; + + if (!seatop_allows_set_cursor(seat)) { + return; + } + + struct wl_client *focused_client = NULL; + struct wlr_surface *focused_surface = seat->wlr_seat->pointer_state.focused_surface; + if (focused_surface != NULL) { + focused_client = wl_resource_get_client(focused_surface->resource); + } + + // TODO: check cursor mode + if (focused_client == NULL || event->seat_client->client != focused_client) { + sway_log(SWAY_DEBUG, "denying request to set cursor from unfocused client"); + return; + } + + cursor_set_image(seat->cursor, wlr_cursor_shape_v1_name(event->shape), focused_client); +} diff --git a/sway/server.c b/sway/server.c index 3a11088a..50f0a702 100644 --- a/sway/server.c +++ b/sway/server.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -44,6 +45,7 @@ #include "sway/input/input-manager.h" #include "sway/output.h" #include "sway/server.h" +#include "sway/input/cursor.h" #include "sway/tree/root.h" #if HAVE_XWAYLAND @@ -235,6 +237,11 @@ bool server_init(struct sway_server *server) { wl_signal_add(&server->xdg_activation_v1->events.new_token, &server->xdg_activation_v1_new_token); + struct wlr_cursor_shape_manager_v1 *cursor_shape_manager = + wlr_cursor_shape_manager_v1_create(server->wl_display, 1); + server->request_set_cursor_shape.notify = handle_request_set_cursor_shape; + wl_signal_add(&cursor_shape_manager->events.request_set_shape, &server->request_set_cursor_shape); + wl_list_init(&server->pending_launcher_ctxs); // Avoid using "wayland-0" as display socket