Merge branch 'pointer-warp-v1' into 'master'

xwayland: Implement support for the pointer-warp-v1 protocol

See merge request xorg/xserver!2031
This commit is contained in:
Rémi Bernon 2026-01-25 01:42:01 +00:00
commit 8f192c9bc0
6 changed files with 69 additions and 22 deletions

View file

@ -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'

View file

@ -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

View file

@ -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,

View file

@ -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;

View file

@ -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;

View file

@ -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'