diff --git a/platform/linuxbsd/wayland/SCsub b/platform/linuxbsd/wayland/SCsub index 4cceb49977a..f9d3aee706a 100644 --- a/platform/linuxbsd/wayland/SCsub +++ b/platform/linuxbsd/wayland/SCsub @@ -46,6 +46,14 @@ env.NoCache( "protocol/viewporter.gen.h", "#thirdparty/wayland-protocols/stable/viewporter/viewporter.xml" ), env.WAYLAND_API_CODE("protocol/viewporter.gen.c", "#thirdparty/wayland-protocols/stable/viewporter/viewporter.xml"), + env.WAYLAND_API_HEADER( + "protocol/cursor_shape.gen.h", + "#thirdparty/wayland-protocols/staging/cursor-shape/cursor-shape-v1.xml", + ), + env.WAYLAND_API_CODE( + "protocol/cursor_shape.gen.c", + "#thirdparty/wayland-protocols/staging/cursor-shape/cursor-shape-v1.xml", + ), env.WAYLAND_API_HEADER( "protocol/fractional_scale.gen.h", "#thirdparty/wayland-protocols/staging/fractional-scale/fractional-scale-v1.xml", @@ -158,6 +166,7 @@ env.NoCache( source_files = [ "protocol/wayland.gen.c", "protocol/viewporter.gen.c", + "protocol/cursor_shape.gen.c", "protocol/fractional_scale.gen.c", "protocol/xdg_shell.gen.c", "protocol/xdg_system_bell.gen.c", diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp index 51454185858..8122f7495eb 100644 --- a/platform/linuxbsd/wayland/wayland_thread.cpp +++ b/platform/linuxbsd/wayland/wayland_thread.cpp @@ -547,6 +547,12 @@ void WaylandThread::_wl_registry_on_global(void *data, struct wl_registry *wl_re registry->wp_viewporter_name = name; } + if (strcmp(interface, wp_cursor_shape_manager_v1_interface.name) == 0) { + registry->wp_cursor_shape_manager = (struct wp_cursor_shape_manager_v1 *)wl_registry_bind(wl_registry, name, &wp_cursor_shape_manager_v1_interface, 1); + registry->wp_cursor_shape_manager_name = name; + return; + } + if (strcmp(interface, wp_fractional_scale_manager_v1_interface.name) == 0) { registry->wp_fractional_scale_manager = (struct wp_fractional_scale_manager_v1 *)wl_registry_bind(wl_registry, name, &wp_fractional_scale_manager_v1_interface, 1); registry->wp_fractional_scale_manager_name = name; @@ -753,6 +759,25 @@ void WaylandThread::_wl_registry_on_global_remove(void *data, struct wl_registry return; } + if (name == registry->wp_cursor_shape_manager_name) { + if (registry->wp_cursor_shape_manager) { + wp_cursor_shape_manager_v1_destroy(registry->wp_cursor_shape_manager); + registry->wp_cursor_shape_manager = nullptr; + } + + registry->wp_cursor_shape_manager_name = 0; + + for (struct wl_seat *wl_seat : registry->wl_seats) { + SeatState *ss = wl_seat_get_seat_state(wl_seat); + ERR_FAIL_NULL(ss); + + if (ss->wp_cursor_shape_device) { + wp_cursor_shape_device_v1_destroy(ss->wp_cursor_shape_device); + ss->wp_cursor_shape_device = nullptr; + } + } + } + if (name == registry->wp_fractional_scale_manager_name) { for (KeyValue &pair : registry->wayland_thread->windows) { WindowState ws = pair.value; @@ -1454,6 +1479,10 @@ void WaylandThread::_wl_seat_on_capabilities(void *data, struct wl_seat *wl_seat ss->wl_pointer = wl_seat_get_pointer(wl_seat); wl_pointer_add_listener(ss->wl_pointer, &wl_pointer_listener, ss); + if (ss->registry->wp_cursor_shape_manager) { + ss->wp_cursor_shape_device = wp_cursor_shape_manager_v1_get_pointer(ss->registry->wp_cursor_shape_manager, ss->wl_pointer); + } + if (ss->registry->wp_relative_pointer_manager) { ss->wp_relative_pointer = zwp_relative_pointer_manager_v1_get_relative_pointer(ss->registry->wp_relative_pointer_manager, ss->wl_pointer); zwp_relative_pointer_v1_add_listener(ss->wp_relative_pointer, &wp_relative_pointer_listener, ss); @@ -1485,6 +1514,11 @@ void WaylandThread::_wl_seat_on_capabilities(void *data, struct wl_seat *wl_seat ss->wl_pointer = nullptr; } + if (ss->wp_cursor_shape_device) { + wp_cursor_shape_device_v1_destroy(ss->wp_cursor_shape_device); + ss->wp_cursor_shape_device = nullptr; + } + if (ss->wp_relative_pointer) { zwp_relative_pointer_v1_destroy(ss->wp_relative_pointer); ss->wp_relative_pointer = nullptr; @@ -3330,6 +3364,12 @@ void WaylandThread::seat_state_update_cursor(SeatState *p_ss) { // We can't really reasonably scale custom cursors, so we'll let the // compositor do it for us (badly). scale = 1; + } else if (thread->registry.wp_cursor_shape_manager) { + wp_cursor_shape_device_v1_shape wp_shape = thread->standard_cursors[shape]; + wp_cursor_shape_device_v1_set_shape(p_ss->wp_cursor_shape_device, p_ss->pointer_enter_serial, wp_shape); + + // We should avoid calling the `wl_pointer_set_cursor` at the end of this method. + return; } else { struct wl_cursor *wl_cursor = thread->wl_cursors[shape]; @@ -4892,6 +4932,10 @@ void WaylandThread::destroy() { wl_data_device_destroy(ss->wl_data_device); } + if (ss->wp_cursor_shape_device) { + wp_cursor_shape_device_v1_destroy(ss->wp_cursor_shape_device); + } + if (ss->wp_relative_pointer) { zwp_relative_pointer_v1_destroy(ss->wp_relative_pointer); } @@ -4959,6 +5003,10 @@ void WaylandThread::destroy() { zxdg_decoration_manager_v1_destroy(registry.xdg_decoration_manager); } + if (registry.wp_cursor_shape_manager) { + wp_cursor_shape_manager_v1_destroy(registry.wp_cursor_shape_manager); + } + if (registry.wp_fractional_scale_manager) { wp_fractional_scale_manager_v1_destroy(registry.wp_fractional_scale_manager); } diff --git a/platform/linuxbsd/wayland/wayland_thread.h b/platform/linuxbsd/wayland/wayland_thread.h index b70e6a359fe..64e1babcf67 100644 --- a/platform/linuxbsd/wayland/wayland_thread.h +++ b/platform/linuxbsd/wayland/wayland_thread.h @@ -51,10 +51,11 @@ // These must go after the Wayland client include to work properly. #include "wayland/protocol/idle_inhibit.gen.h" #include "wayland/protocol/primary_selection.gen.h" -// These three protocol headers name wl_pointer method arguments as `pointer`, +// These four protocol headers name wl_pointer method arguments as `pointer`, // which is the same name as X11's pointer typedef. This trips some very // annoying shadowing warnings. A `#define` works around this issue. #define pointer wl_pointer +#include "wayland/protocol/cursor_shape.gen.h" #include "wayland/protocol/pointer_constraints.gen.h" #include "wayland/protocol/pointer_gestures.gen.h" #include "wayland/protocol/relative_pointer.gen.h" @@ -187,6 +188,9 @@ public: struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager = nullptr; uint32_t wp_fractional_scale_manager_name = 0; + struct wp_cursor_shape_manager_v1 *wp_cursor_shape_manager = nullptr; + uint32_t wp_cursor_shape_manager_name = 0; + struct zxdg_decoration_manager_v1 *xdg_decoration_manager = nullptr; uint32_t xdg_decoration_manager_name = 0; @@ -416,6 +420,8 @@ public: uint32_t pointer_enter_serial = 0; + struct wp_cursor_shape_device_v1 *wp_cursor_shape_device = nullptr; + struct zwp_relative_pointer_v1 *wp_relative_pointer = nullptr; struct zwp_locked_pointer_v1 *wp_locked_pointer = nullptr; struct zwp_confined_pointer_v1 *wp_confined_pointer = nullptr; @@ -547,9 +553,32 @@ private: // especially as usually screen scales don't change continuously. int cursor_scale = 1; + // Use cursor-shape-v1 protocol if the compositor supports it. + wp_cursor_shape_device_v1_shape standard_cursors[DisplayServer::CURSOR_MAX] = { + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_DEFAULT, //CURSOR_ARROW + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_TEXT, //CURSOR_IBEAM + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_POINTER, //CURSOR_POINTING_HAND + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_CROSSHAIR, //CURSOR_CROSS + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_WAIT, //CURSOR_WAIT + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_PROGRESS, //CURSOR_BUSY + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRAB, //CURSOR_DRAG + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_GRABBING, //CURSOR_CAN_DROP + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NO_DROP, //CURSOR_FORBIDDEN + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NS_RESIZE, //CURSOR_VSIZE + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_EW_RESIZE, //CURSOR_HSIZE + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NESW_RESIZE, //CURSOR_BDIAGSIZE + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_NWSE_RESIZE, //CURSOR_FDIAGSIZE + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_MOVE, //CURSOR_MOVE + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_ROW_RESIZE, //CURSOR_VSPLIT + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_COL_RESIZE, //CURSOR_HSPLIT + wp_cursor_shape_device_v1_shape::WP_CURSOR_SHAPE_DEVICE_V1_SHAPE_HELP, //CURSOR_HELP + }; + + // Fallback to reading $XCURSOR and system themes if the compositor does not. struct wl_cursor_theme *wl_cursor_theme = nullptr; struct wl_cursor *wl_cursors[DisplayServer::CURSOR_MAX] = {}; + // User-defined cursor overrides. Take precedence over standard and wl cursors. HashMap custom_cursors; DisplayServer::CursorShape cursor_shape = DisplayServer::CURSOR_ARROW; diff --git a/thirdparty/wayland-protocols/staging/cursor-shape/README b/thirdparty/wayland-protocols/staging/cursor-shape/README new file mode 100644 index 00000000000..7ca8f5e1d3b --- /dev/null +++ b/thirdparty/wayland-protocols/staging/cursor-shape/README @@ -0,0 +1,4 @@ +cursor-shape protocol + +Maintainers: +Simon Ser (@emersion) diff --git a/thirdparty/wayland-protocols/staging/cursor-shape/cursor-shape-v1.xml b/thirdparty/wayland-protocols/staging/cursor-shape/cursor-shape-v1.xml new file mode 100644 index 00000000000..64b2f9b2c87 --- /dev/null +++ b/thirdparty/wayland-protocols/staging/cursor-shape/cursor-shape-v1.xml @@ -0,0 +1,162 @@ + + + + Copyright 2018 The Chromium Authors + Copyright 2023 Simon Ser + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + + This global offers an alternative, optional way to set cursor images. This + new way uses enumerated cursors instead of a wl_surface like + wl_pointer.set_cursor does. + + Warning! The protocol described in this file is currently in the testing + phase. Backward compatible changes may be added together with the + corresponding interface version bump. Backward incompatible changes can + only be done by creating a new major version of the extension. + + + + + Destroy the cursor shape manager. + + + + + + Obtain a wp_cursor_shape_device_v1 for a wl_pointer object. + + When the pointer capability is removed from the wl_seat, the + wp_cursor_shape_device_v1 object becomes inert. + + + + + + + + Obtain a wp_cursor_shape_device_v1 for a zwp_tablet_tool_v2 object. + + When the zwp_tablet_tool_v2 is removed, the wp_cursor_shape_device_v1 + object becomes inert. + + + + + + + + + This interface allows clients to set the cursor shape. + + + + + This enum describes cursor shapes. + + The names are taken from the CSS W3C specification: + https://w3c.github.io/csswg-drafts/css-ui/#cursor + with a few additions. + + Note that there are some groups of cursor shapes that are related: + The first group is drag-and-drop cursors which are used to indicate + the selected action during dnd operations. The second group is resize + cursors which are used to indicate resizing and moving possibilities + on window borders. It is recommended that the shapes in these groups + should use visually compatible images and metaphors. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Destroy the cursor shape device. + + The device cursor shape remains unchanged. + + + + + + Sets the device cursor to the specified shape. The compositor will + change the cursor image based on the specified shape. + + The cursor actually changes only if the input device focus is one of + the requesting client's surfaces. If any, the previous cursor image + (surface or shape) is replaced. + + The "shape" argument must be a valid enum entry, otherwise the + invalid_shape protocol error is raised. + + This is similar to the wl_pointer.set_cursor and + zwp_tablet_tool_v2.set_cursor requests, but this request accepts a + shape instead of contents in the form of a surface. Clients can mix + set_cursor and set_shape requests. + + The serial parameter must match the latest wl_pointer.enter or + zwp_tablet_tool_v2.proximity_in serial number sent to the client. + Otherwise the request will be ignored. + + + + + +