Skip to content

Commit 7a42499

Browse files
committed
[Wayland] Add support for pointer-warp-v1 protocol
Only allow this while an implicit grab is held, so that it is not assumed to be a generic warping mechanism.
1 parent 5a4956e commit 7a42499

9 files changed

Lines changed: 282 additions & 0 deletions

src/meson.build

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,8 @@ if have_wayland
546546
'wayland/meta-wayland-pointer-gestures.h',
547547
'wayland/meta-wayland-pointer-gesture-swipe.c',
548548
'wayland/meta-wayland-pointer-gesture-swipe.h',
549+
'wayland/meta-wayland-pointer-warp.c',
550+
'wayland/meta-wayland-pointer-warp.h',
549551
'wayland/meta-wayland-pointer.h',
550552
'wayland/meta-wayland-popup.c',
551553
'wayland/meta-wayland-popup.h',
@@ -813,6 +815,7 @@ if have_wayland
813815
['linux-dmabuf', 'unstable', 'v1', ],
814816
['pointer-constraints', 'unstable', 'v1', ],
815817
['pointer-gestures', 'unstable', 'v1', ],
818+
['pointer-warp-v1', 'private',],
816819
['primary-selection', 'unstable', 'v1', ],
817820
['relative-pointer', 'unstable', 'v1', ],
818821
['tablet', 'unstable', 'v2', ],
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
* Wayland Support
3+
*
4+
* Copyright (C) 2025 Red Hat Inc.
5+
*
6+
* This library is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 2 of the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
18+
*
19+
* Author: Carlos Garnacho <carlosg@gnome.org>
20+
*/
21+
22+
#include "config.h"
23+
24+
#include "meta-wayland-pointer-warp.h"
25+
26+
#include "meta-wayland-private.h"
27+
#include "meta-wayland-seat.h"
28+
#include "meta-wayland-surface.h"
29+
30+
#include "pointer-warp-v1-server-protocol.h"
31+
32+
struct _MetaWaylandPointerWarp
33+
{
34+
MetaWaylandSeat *seat;
35+
struct wl_list resource_list;
36+
};
37+
38+
static void
39+
pointer_warp_destroy (struct wl_client *client,
40+
struct wl_resource *resource)
41+
{
42+
wl_resource_destroy (resource);
43+
}
44+
45+
static void
46+
pointer_warp_perform (struct wl_client *client,
47+
struct wl_resource *resource,
48+
struct wl_resource *surface_resource,
49+
struct wl_resource *pointer_resource,
50+
wl_fixed_t x,
51+
wl_fixed_t y,
52+
uint32_t serial)
53+
{
54+
ClutterSeat *seat;
55+
MetaWaylandSurface *surface = wl_resource_get_user_data (surface_resource);
56+
MetaWaylandPointer *pointer = wl_resource_get_user_data (pointer_resource);
57+
MetaSurfaceActor *surface_actor = meta_wayland_surface_get_actor (surface);
58+
graphene_point3d_t coords =
59+
GRAPHENE_POINT3D_INIT ((float) wl_fixed_to_double (x),
60+
(float) wl_fixed_to_double (y),
61+
0.0);
62+
63+
/* Not focused and implicitly grabbed */
64+
if (!meta_wayland_pointer_get_grab_info (pointer, surface, serial, TRUE,
65+
NULL, NULL, NULL))
66+
return;
67+
68+
/* Outside of actor */
69+
if (!surface_actor ||
70+
x < 0 || x > clutter_actor_get_width (CLUTTER_ACTOR (surface_actor)) ||
71+
y < 0 || y > clutter_actor_get_height (CLUTTER_ACTOR (surface_actor)))
72+
return;
73+
74+
clutter_actor_apply_transform_to_point (CLUTTER_ACTOR (surface_actor),
75+
&coords, &coords);
76+
77+
seat = clutter_backend_get_default_seat (clutter_get_default_backend ());
78+
79+
clutter_seat_warp_pointer (seat, (int) coords.x, (int) coords.y);
80+
}
81+
82+
static struct wp_pointer_warp_v1_interface pointer_warp_interface = {
83+
pointer_warp_destroy,
84+
pointer_warp_perform,
85+
};
86+
87+
static void
88+
unbind_resource (struct wl_resource *resource)
89+
{
90+
wl_list_remove (wl_resource_get_link (resource));
91+
}
92+
93+
static void
94+
bind_pointer_warp (struct wl_client *client,
95+
void *data,
96+
uint32_t version,
97+
uint32_t id)
98+
{
99+
MetaWaylandPointerWarp *pointer_warp = data;
100+
struct wl_resource *resource;
101+
102+
resource = wl_resource_create (client, &wp_pointer_warp_v1_interface,
103+
MIN (version, META_WP_POINTER_WARP_VERSION),
104+
id);
105+
wl_resource_set_implementation (resource, &pointer_warp_interface,
106+
pointer_warp, unbind_resource);
107+
wl_resource_set_user_data (resource, pointer_warp);
108+
wl_list_insert (&pointer_warp->resource_list,
109+
wl_resource_get_link (resource));
110+
}
111+
112+
MetaWaylandPointerWarp *
113+
meta_wayland_pointer_warp_new (MetaWaylandSeat *seat)
114+
{
115+
MetaWaylandCompositor *compositor = meta_wayland_compositor_get_default ();
116+
MetaWaylandPointerWarp *pointer_warp;
117+
118+
pointer_warp = g_new0 (MetaWaylandPointerWarp, 1);
119+
pointer_warp->seat = seat;
120+
wl_list_init (&pointer_warp->resource_list);
121+
122+
wl_global_create (compositor->wayland_display,
123+
&wp_pointer_warp_v1_interface,
124+
META_WP_POINTER_WARP_VERSION,
125+
pointer_warp, bind_pointer_warp);
126+
127+
return pointer_warp;
128+
}
129+
130+
void
131+
meta_wayland_pointer_warp_destroy (MetaWaylandPointerWarp *pointer_warp)
132+
{
133+
wl_list_remove (&pointer_warp->resource_list);
134+
g_free (pointer_warp);
135+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/*
2+
* Wayland Support
3+
*
4+
* Copyright (C) 2025 Red Hat Inc.
5+
*
6+
* This library is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 2 of the License, or (at your option) any later version.
10+
*
11+
* This library is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public
17+
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
18+
*
19+
* Author: Carlos Garnacho <carlosg@gnome.org>
20+
*/
21+
22+
#pragma once
23+
24+
#include <glib.h>
25+
#include <wayland-server.h>
26+
27+
#include "wayland/meta-wayland-types.h"
28+
29+
typedef struct _MetaWaylandPointerWarp MetaWaylandPointerWarp;
30+
31+
MetaWaylandPointerWarp * meta_wayland_pointer_warp_new (MetaWaylandSeat *seat);
32+
33+
void meta_wayland_pointer_warp_destroy (MetaWaylandPointerWarp *pointer_warp);

src/wayland/meta-wayland-pointer.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1292,6 +1292,32 @@ meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer,
12921292
pointer_can_grab_surface (pointer, surface));
12931293
}
12941294

1295+
gboolean
1296+
meta_wayland_pointer_get_grab_info (MetaWaylandPointer *pointer,
1297+
MetaWaylandSurface *surface,
1298+
uint32_t serial,
1299+
gboolean require_pressed,
1300+
ClutterInputDevice **device_out,
1301+
float *x,
1302+
float *y)
1303+
{
1304+
if ((!require_pressed || pointer->button_count > 0) &&
1305+
meta_wayland_pointer_can_grab_surface (pointer, surface, serial))
1306+
{
1307+
if (device_out)
1308+
*device_out = pointer->device;
1309+
1310+
if (x)
1311+
*x = pointer->grab_x;
1312+
if (y)
1313+
*y = pointer->grab_y;
1314+
1315+
return TRUE;
1316+
}
1317+
1318+
return FALSE;
1319+
}
1320+
12951321
gboolean
12961322
meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer, uint32_t serial)
12971323
{

src/wayland/meta-wayland-pointer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,14 @@ gboolean meta_wayland_pointer_can_grab_surface (MetaWaylandPointer *pointer,
143143
MetaWaylandSurface *surface,
144144
uint32_t serial);
145145

146+
gboolean meta_wayland_pointer_get_grab_info (MetaWaylandPointer *pointer,
147+
MetaWaylandSurface *surface,
148+
uint32_t serial,
149+
gboolean require_pressed,
150+
ClutterInputDevice **device_out,
151+
float *x,
152+
float *y);
153+
146154
gboolean meta_wayland_pointer_can_popup (MetaWaylandPointer *pointer,
147155
uint32_t serial);
148156

src/wayland/meta-wayland-seat.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ meta_wayland_seat_new (MetaWaylandCompositor *compositor,
236236
NULL);
237237

238238
seat->text_input = meta_wayland_text_input_new (seat);
239+
seat->pointer_warp = meta_wayland_pointer_warp_new (seat);
239240

240241
meta_wayland_data_device_init (&seat->data_device);
241242
meta_wayland_data_device_primary_init (&seat->primary_data_device);
@@ -274,6 +275,7 @@ meta_wayland_seat_free (MetaWaylandSeat *seat)
274275
g_object_unref (seat->keyboard);
275276
g_object_unref (seat->touch);
276277
meta_wayland_text_input_destroy (seat->text_input);
278+
meta_wayland_pointer_warp_destroy (seat->pointer_warp);
277279

278280
g_free (seat);
279281
}

src/wayland/meta-wayland-seat.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "wayland/meta-wayland-input-device.h"
3131
#include "wayland/meta-wayland-keyboard.h"
3232
#include "wayland/meta-wayland-pointer.h"
33+
#include "wayland/meta-wayland-pointer-warp.h"
3334
#include "wayland/meta-wayland-tablet-tool.h"
3435
#include "wayland/meta-wayland-text-input.h"
3536
#include "wayland/meta-wayland-touch.h"
@@ -48,6 +49,7 @@ struct _MetaWaylandSeat
4849
MetaWaylandDataDevicePrimary primary_data_device;
4950

5051
MetaWaylandTextInput *text_input;
52+
MetaWaylandPointerWarp *pointer_warp;
5153

5254
guint capabilities;
5355
};

src/wayland/meta-wayland-versions.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,5 +60,6 @@
6060
#define META_ZWP_PRIMARY_SELECTION_V1_VERSION 1
6161
#define META_XDG_TOPLEVEL_TAG_V1_VERSION 1
6262
#define META_WP_CURSOR_SHAPE_VERSION 2
63+
#define META_WP_POINTER_WARP_VERSION 1
6364

6465
#endif
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<protocol name="pointer_warp_v1">
3+
<copyright>
4+
Copyright © 2024 Neal Gompa
5+
Copyright © 2024 Xaver Hugl
6+
Copyright © 2024 Matthias Klumpp
7+
Copyright © 2024 Vlad Zahorodnii
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a
10+
copy of this software and associated documentation files (the "Software"),
11+
to deal in the Software without restriction, including without limitation
12+
the rights to use, copy, modify, merge, publish, distribute, sublicense,
13+
and/or sell copies of the Software, and to permit persons to whom the
14+
Software is furnished to do so, subject to the following conditions:
15+
The above copyright notice and this permission notice (including the next
16+
paragraph) shall be included in all copies or substantial portions of the
17+
Software.
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21+
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24+
DEALINGS IN THE SOFTWARE.
25+
</copyright>
26+
27+
<interface name="wp_pointer_warp_v1" version="1">
28+
<description summary="reposition the pointer to a location on a surface">
29+
This global interface allows applications to request the pointer to be
30+
moved to a position relative to a wl_surface.
31+
32+
Note that if the desired behavior is to constrain the pointer to an area
33+
or lock it to a position, this protocol does not provide a reliable way
34+
to do that. The pointer constraint and pointer lock protocols should be
35+
used for those use cases instead.
36+
37+
Warning! The protocol described in this file is currently in the testing
38+
phase. Backward compatible changes may be added together with the
39+
corresponding interface version bump. Backward incompatible changes can
40+
only be done by creating a new major version of the extension.
41+
</description>
42+
43+
<request name="destroy" type="destructor">
44+
<description summary="destroy the warp manager">
45+
Destroy the pointer warp manager.
46+
</description>
47+
</request>
48+
49+
<request name="warp_pointer">
50+
<description summary="reposition the pointer">
51+
Request the compositor to move the pointer to a surface-local position.
52+
Whether or not the compositor honors the request is implementation defined,
53+
but it should
54+
- honor it if the surface has pointer focus, including
55+
when it has an implicit pointer grab
56+
- reject it if the enter serial is incorrect
57+
- reject it if the requested position is outside of the surface
58+
59+
Note that the enter serial is valid for any surface of the client,
60+
and does not have to be from the surface the pointer is warped to.
61+
62+
</description>
63+
<arg name="surface" type="object" interface="wl_surface"
64+
summary="surface to position the pointer on"/>
65+
<arg name="pointer" type="object" interface="wl_pointer"
66+
summary="the pointer that should be repositioned"/>
67+
<arg name="x" type="fixed"/>
68+
<arg name="y" type="fixed"/>
69+
<arg name="serial" type="uint" summary="serial number of the enter event"/>
70+
</request>
71+
</interface>
72+
</protocol>

0 commit comments

Comments
 (0)