diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 22aadf97c..4ed145bf3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ variables: REPO_URL_XORGPROTO: 'https://gitlab.freedesktop.org/xorg/proto/xorgproto.git' XORG_DEBIAN_VERSION: 'bullseye-slim' XORG_DEBIAN_EXEC: 'env FDO_CI_CONCURRENT=${FDO_CI_CONCURRENT} bash .gitlab-ci/debian-install.sh' - XORG_DEBIAN_TAG: '2025-02-26-xcb-deps' + XORG_DEBIAN_TAG: '2025-07-01-wayland-protocols-1-45' XORG_FREEBSD_VERSION: '14.2' XORG_FREEBSD_EXEC: '' XORG_FREEBSD_TAG: '2025-02-18-vm-image' diff --git a/.gitlab-ci/debian-install.sh b/.gitlab-ci/debian-install.sh index e4f1eb6e2..76577bc23 100644 --- a/.gitlab-ci/debian-install.sh +++ b/.gitlab-ci/debian-install.sh @@ -155,16 +155,16 @@ make -j${FDO_CI_CONCURRENT:-4} install popd rm -rf xorgproto -# wayland-protocols requires wayland-scanner 1.20, but Debian bullseye has 1.18 only -git clone https://gitlab.freedesktop.org/wayland/wayland.git --depth 1 --branch=1.21.0 +# wayland-protocols requires wayland-scanner 1.23, but Debian bullseye has 1.18 only +git clone https://gitlab.freedesktop.org/wayland/wayland.git --depth 1 --branch=1.23.0 cd wayland meson -Dtests=false -Ddocumentation=false -Ddtd_validation=false _build ninja -C _build -j${FDO_CI_CONCURRENT:-4} install cd .. rm -rf wayland -# Xwayland requires wayland-protocols >= 1.38, but Debian bullseye has 1.20 only -git clone https://gitlab.freedesktop.org/wayland/wayland-protocols.git --depth 1 --branch=1.38 +# Xwayland requires wayland-protocols >= 1.45, but Debian bullseye has 1.20 only +git clone https://gitlab.freedesktop.org/wayland/wayland-protocols.git --depth 1 --branch=1.45 cd wayland-protocols meson _build ninja -C _build -j${FDO_CI_CONCURRENT:-4} install diff --git a/hw/xwayland/meson.build b/hw/xwayland/meson.build index bee2eb324..ba9e35508 100644 --- a/hw/xwayland/meson.build +++ b/hw/xwayland/meson.build @@ -52,6 +52,7 @@ tearing_xml = join_paths(protodir, 'staging', 'tearing-control', 'tearing-contro fractional_scale_xml = join_paths(protodir, 'staging', 'fractional-scale', 'fractional-scale-v1.xml') syncobj_xml = join_paths(protodir, 'staging', 'linux-drm-syncobj', 'linux-drm-syncobj-v1.xml') system_bell_xml = join_paths(protodir, 'staging', 'xdg-system-bell', 'xdg-system-bell-v1.xml') +pointer_warp_xml = join_paths(protodir, 'staging', 'pointer-warp', 'pointer-warp-v1.xml') proto_xml = [ relative_xml, @@ -70,6 +71,7 @@ proto_xml = [ fractional_scale_xml, syncobj_xml, system_bell_xml, + pointer_warp_xml, ] client_header = generator(scanner, diff --git a/hw/xwayland/xwayland-input.c b/hw/xwayland/xwayland-input.c index 6fe183e93..a2d2f6889 100644 --- a/hw/xwayland/xwayland-input.c +++ b/hw/xwayland/xwayland-input.c @@ -59,6 +59,7 @@ #include "xwayland-keyboard-grab-unstable-v1-client-protocol.h" #include "keyboard-shortcuts-inhibit-unstable-v1-client-protocol.h" #include "xdg-system-bell-v1-client-protocol.h" +#include "pointer-warp-v1-client-protocol.h" #define SCROLL_AXIS_HORIZ 2 #define SCROLL_AXIS_VERT 3 @@ -3123,6 +3124,15 @@ init_system_bell(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version) 1); } +static void +init_pointer_warp(struct xwl_screen *xwl_screen, uint32_t id, uint32_t version) +{ + xwl_screen->pointer_warp = + wl_registry_bind(xwl_screen->registry, id, + &wp_pointer_warp_v1_interface, + 1); +} + /* The compositor may send us wl_seat and its capabilities before sending e.g. relative_pointer_manager or pointer_gesture interfaces. This would result in devices being created in capabilities handler, but listeners not, because @@ -3176,6 +3186,8 @@ input_handler(void *data, struct wl_registry *registry, uint32_t id, init_keyboard_shortcuts_inhibit(xwl_screen, id, version); } else if (strcmp(interface, xdg_system_bell_v1_interface.name) == 0) { init_system_bell(xwl_screen, id, version); + } else if (strcmp(interface, wp_pointer_warp_v1_interface.name) == 0) { + init_pointer_warp(xwl_screen, id, version); } } @@ -3319,33 +3331,47 @@ xwl_seat_clear_touch(struct xwl_seat *xwl_seat, struct xwl_window *xwl_window) } } +static Bool +xwl_seat_get_warp_location(struct xwl_seat *xwl_seat, int x, int y, + struct wl_surface **surface, + wl_fixed_t *sx, wl_fixed_t *sy) +{ + WindowPtr window; + + if (!xwl_seat->focus_window) + return FALSE; + + window = xwl_seat->focus_window->toplevel; + if (x >= window->drawable.x || + y >= window->drawable.y || + x < (window->drawable.x + window->drawable.width) || + y < (window->drawable.y + window->drawable.height)) { + *surface = xwl_seat->focus_window->surface; + *sx = wl_fixed_from_int(x - window->drawable.x); + *sy = wl_fixed_from_int(y - window->drawable.y); + return TRUE; + } + + return FALSE; +} + static void xwl_pointer_warp_emulator_set_fake_pos(struct xwl_pointer_warp_emulator *warp_emulator, int x, int y) { + struct xwl_seat *xwl_seat = warp_emulator->xwl_seat; struct zwp_locked_pointer_v1 *locked_pointer = warp_emulator->locked_pointer; - WindowPtr window; - int sx, sy; + struct wl_surface *surface; + wl_fixed_t sx, sy; if (!warp_emulator->locked_pointer) return; - if (!warp_emulator->xwl_seat->focus_window) - return; - - window = warp_emulator->xwl_seat->focus_window->toplevel; - if (x >= window->drawable.x || - y >= window->drawable.y || - x < (window->drawable.x + window->drawable.width) || - y < (window->drawable.y + window->drawable.height)) { - sx = x - window->drawable.x; - sy = y - window->drawable.y; - zwp_locked_pointer_v1_set_cursor_position_hint(locked_pointer, - wl_fixed_from_int(sx), - wl_fixed_from_int(sy)); - wl_surface_commit(warp_emulator->xwl_seat->focus_window->surface); + if (xwl_seat_get_warp_location(xwl_seat, x, y, &surface, &sx, &sy)) { + zwp_locked_pointer_v1_set_cursor_position_hint(locked_pointer, sx, sy); + wl_surface_commit(surface); } } @@ -3502,6 +3528,8 @@ xwl_seat_can_emulate_pointer_warp(struct xwl_seat *xwl_seat) return FALSE; xwl_screen = xwl_seat->xwl_screen; + if (xwl_screen->pointer_warp) + return TRUE; if (!xwl_screen->relative_pointer_manager) return FALSE; @@ -3521,6 +3549,22 @@ xwl_seat_emulate_pointer_warp(struct xwl_seat *xwl_seat, if (!xwl_seat_can_emulate_pointer_warp(xwl_seat)) return; + if (xwl_seat->xwl_screen->pointer_warp) { + struct wp_pointer_warp_v1 *pointer_warp = + xwl_seat->xwl_screen->pointer_warp; + struct wl_surface *surface; + wl_fixed_t sx, sy; + + if (xwl_seat_get_warp_location(xwl_seat, x, y, &surface, &sx, &sy)) { + wp_pointer_warp_v1_warp_pointer(pointer_warp, surface, + xwl_seat->wl_pointer, sx, sy, + xwl_seat->pointer_enter_serial); + wl_surface_commit(surface); + } + + return; + } + if (xwl_seat->x_cursor != NULL) return; diff --git a/hw/xwayland/xwayland-screen.h b/hw/xwayland/xwayland-screen.h index ffbaa09e7..414b35e81 100644 --- a/hw/xwayland/xwayland-screen.h +++ b/hw/xwayland/xwayland-screen.h @@ -119,6 +119,7 @@ struct xwl_screen { struct wp_fractional_scale_manager_v1 *fractional_scale_manager; struct wp_linux_drm_syncobj_manager_v1 *explicit_sync; struct xdg_system_bell_v1 *system_bell; + struct wp_pointer_warp_v1 *pointer_warp; struct xorg_list drm_lease_devices; struct xorg_list queued_drm_lease_devices; struct xorg_list drm_leases; diff --git a/meson.build b/meson.build index 1556491eb..23f57fcd6 100644 --- a/meson.build +++ b/meson.build @@ -67,7 +67,7 @@ libselinux_req = '>= 2.0.86' xext_req = '>= 1.0.99.4' xproto_req = '>= 7.0.31' wayland_req = '>= 1.21.0' -wayland_protocols_req = '>= 1.38' +wayland_protocols_req = '>= 1.45' gbm_req = '>= 10.2' xf86dgaproto_req = '>= 2.0.99.1' xshmfence_req = '>= 1.1'