Commit a6e85e63 authored by Jonas Ådahl's avatar Jonas Ådahl Committed by Adam Jackson

xwayland: Add pointer warp emulator

Emulate pointer warps by locking the pointer and sending relative
motion events instead of absolute. X will keep track of the "fake"
pointer cursor position given the relative motion events, and the
client warping the cursor will warp the faked cursor position.

Various requirements need to be met for the pointer warp emulator to

The cursor must be invisible: since it would not be acceptable that a
fake cursor position would be different from the visual representation
of the cursor, emulation can only be done when there is no visual
representation done by the Wayland compositor. Thus, for the emulator
to enable, the cursor must be hidden, and would the cursor be displayed
while the emulator is active, the emulator would be destroyed.

The window that is warped within must be likely to have pointer focus.
For example, warping outside of the window region will be ignored.

The pointer warp emulator will disable itself once the fake cursor
position leaves the window region, or the cursor is made visible.

This makes various games depending on pointer warping (such as 3D
first-person shooters and stategy games using click-to-drag-map like
things) work.
Signed-off-by: Jonas Ådahl's avatarJonas Ådahl <>
parent 467ab142
......@@ -169,12 +169,19 @@ xwl_set_cursor(DeviceIntPtr device,
ScreenPtr screen, CursorPtr cursor, int x, int y)
struct xwl_seat *xwl_seat;
Bool cursor_visibility_changed;
xwl_seat = device->public.devicePrivate;
if (xwl_seat == NULL)
cursor_visibility_changed = !!xwl_seat->x_cursor ^ !!cursor;
xwl_seat->x_cursor = cursor;
if (cursor_visibility_changed)
This diff is collapsed.
......@@ -164,6 +164,28 @@ xwl_screen_get_default_seat(struct xwl_screen *xwl_screen)
static void
xwl_cursor_warped_to(DeviceIntPtr device,
ScreenPtr screen,
ClientPtr client,
WindowPtr window,
SpritePtr sprite,
int x, int y)
struct xwl_screen *xwl_screen = xwl_screen_get(screen);
struct xwl_seat *xwl_seat = device->public.devicePrivate;
struct xwl_window *xwl_window;
if (!xwl_seat)
xwl_seat = xwl_screen_get_default_seat(xwl_screen);
xwl_window = xwl_window_from_window(window);
if (!xwl_window)
xwl_seat_emulate_pointer_warp(xwl_seat, xwl_window, sprite, x, y);
static void
xwl_cursor_confined_to(DeviceIntPtr device,
ScreenPtr screen,
......@@ -384,6 +406,10 @@ xwl_unrealize_window(WindowPtr window)
if (xwl_seat->cursor_confinement_window &&
xwl_seat->cursor_confinement_window->window == window)
if (xwl_seat->pointer_warp_emulator &&
xwl_seat->pointer_warp_emulator->locked_window &&
xwl_seat->pointer_warp_emulator->locked_window->window == window)
xwl_seat_clear_touch(xwl_seat, window);
......@@ -810,6 +836,7 @@ xwl_screen_init(ScreenPtr pScreen, int argc, char **argv)
xwl_screen->CloseScreen = pScreen->CloseScreen;
pScreen->CloseScreen = xwl_close_screen;
pScreen->CursorWarpedTo = xwl_cursor_warped_to;
pScreen->CursorConfinedTo = xwl_cursor_confined_to;
return ret;
......@@ -120,6 +120,12 @@ struct xwl_touch {
struct xorg_list link_touch;
struct xwl_pointer_warp_emulator {
struct xwl_seat *xwl_seat;
struct xwl_window *locked_window;
struct zwp_locked_pointer_v1 *locked_pointer;
struct xwl_seat {
DeviceIntPtr pointer;
DeviceIntPtr relative_pointer;
......@@ -150,6 +156,8 @@ struct xwl_seat {
struct xorg_list sync_pending;
struct xwl_pointer_warp_emulator *pointer_warp_emulator;
struct xwl_window *cursor_confinement_window;
struct zwp_confined_pointer_v1 *confined_pointer;
......@@ -191,6 +199,15 @@ void xwl_seat_destroy(struct xwl_seat *xwl_seat);
void xwl_seat_clear_touch(struct xwl_seat *xwl_seat, WindowPtr window);
void xwl_seat_emulate_pointer_warp(struct xwl_seat *xwl_seat,
struct xwl_window *xwl_window,
SpritePtr sprite,
int x, int y);
void xwl_seat_destroy_pointer_warp_emulator(struct xwl_seat *xwl_seat);
void xwl_seat_cursor_visibility_changed(struct xwl_seat *xwl_seat);
void xwl_seat_confine_pointer(struct xwl_seat *xwl_seat,
struct xwl_window *xwl_window);
void xwl_seat_unconfine_pointer(struct xwl_seat *xwl_seat);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment