mirror of https://github.com/libsdl-org/SDL.git
wayland: Implement the pointer warp protocol
The pointer warp protocol allows us to warp the pointer to a different position on the surface, without any hacks like locking and unlocking the pointer.
This commit is contained in:
parent
558a89fdb6
commit
ec1297199e
|
|
@ -38,6 +38,7 @@
|
|||
#include "cursor-shape-v1-client-protocol.h"
|
||||
#include "pointer-constraints-unstable-v1-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "pointer-warp-v1-client-protocol.h"
|
||||
|
||||
#include "../../SDL_hints_c.h"
|
||||
|
||||
|
|
@ -832,43 +833,50 @@ void Wayland_SeatWarpMouse(SDL_WaylandSeat *seat, SDL_WindowData *window, float
|
|||
SDL_VideoData *d = vd->internal;
|
||||
|
||||
if (seat->pointer.wl_pointer) {
|
||||
bool toggle_lock = !seat->pointer.locked_pointer;
|
||||
bool update_grabs = false;
|
||||
if (d->wp_pointer_warp_v1) {
|
||||
// It's a protocol error to warp the pointer outside of the surface, so clamp the position.
|
||||
const wl_fixed_t f_x = wl_fixed_from_double(SDL_clamp(x / window->pointer_scale.x, 0, window->current.logical_width));
|
||||
const wl_fixed_t f_y = wl_fixed_from_double(SDL_clamp(y / window->pointer_scale.y, 0, window->current.logical_height));
|
||||
wp_pointer_warp_v1_warp_pointer(d->wp_pointer_warp_v1, window->surface, seat->pointer.wl_pointer, f_x, f_y, seat->pointer.enter_serial);
|
||||
} else {
|
||||
bool toggle_lock = !seat->pointer.locked_pointer;
|
||||
bool update_grabs = false;
|
||||
|
||||
/* The pointer confinement protocol allows setting a hint to warp the pointer,
|
||||
* but only when the pointer is locked.
|
||||
*
|
||||
* Lock the pointer, set the position hint, unlock, and hope for the best.
|
||||
*/
|
||||
if (toggle_lock) {
|
||||
if (seat->pointer.confined_pointer) {
|
||||
zwp_confined_pointer_v1_destroy(seat->pointer.confined_pointer);
|
||||
seat->pointer.confined_pointer = NULL;
|
||||
update_grabs = true;
|
||||
/* The pointer confinement protocol allows setting a hint to warp the pointer,
|
||||
* but only when the pointer is locked.
|
||||
*
|
||||
* Lock the pointer, set the position hint, unlock, and hope for the best.
|
||||
*/
|
||||
if (toggle_lock) {
|
||||
if (seat->pointer.confined_pointer) {
|
||||
zwp_confined_pointer_v1_destroy(seat->pointer.confined_pointer);
|
||||
seat->pointer.confined_pointer = NULL;
|
||||
update_grabs = true;
|
||||
}
|
||||
seat->pointer.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(d->pointer_constraints, window->surface,
|
||||
seat->pointer.wl_pointer, NULL,
|
||||
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT);
|
||||
}
|
||||
seat->pointer.locked_pointer = zwp_pointer_constraints_v1_lock_pointer(d->pointer_constraints, window->surface,
|
||||
seat->pointer.wl_pointer, NULL,
|
||||
ZWP_POINTER_CONSTRAINTS_V1_LIFETIME_ONESHOT);
|
||||
}
|
||||
|
||||
const wl_fixed_t f_x = wl_fixed_from_double(x / window->pointer_scale.x);
|
||||
const wl_fixed_t f_y = wl_fixed_from_double(y / window->pointer_scale.y);
|
||||
zwp_locked_pointer_v1_set_cursor_position_hint(seat->pointer.locked_pointer, f_x, f_y);
|
||||
wl_surface_commit(window->surface);
|
||||
const wl_fixed_t f_x = wl_fixed_from_double(x / window->pointer_scale.x);
|
||||
const wl_fixed_t f_y = wl_fixed_from_double(y / window->pointer_scale.y);
|
||||
zwp_locked_pointer_v1_set_cursor_position_hint(seat->pointer.locked_pointer, f_x, f_y);
|
||||
wl_surface_commit(window->surface);
|
||||
|
||||
if (toggle_lock) {
|
||||
zwp_locked_pointer_v1_destroy(seat->pointer.locked_pointer);
|
||||
seat->pointer.locked_pointer = NULL;
|
||||
if (toggle_lock) {
|
||||
zwp_locked_pointer_v1_destroy(seat->pointer.locked_pointer);
|
||||
seat->pointer.locked_pointer = NULL;
|
||||
|
||||
if (update_grabs) {
|
||||
Wayland_SeatUpdatePointerGrab(seat);
|
||||
if (update_grabs) {
|
||||
Wayland_SeatUpdatePointerGrab(seat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* NOTE: There is a pending warp event under discussion that should replace this when available.
|
||||
* https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/340
|
||||
*/
|
||||
SDL_SendMouseMotion(0, window->sdlwindow, seat->pointer.sdl_id, false, x, y);
|
||||
/* NOTE: There is a pending warp event under discussion that should replace this when available.
|
||||
* https://gitlab.freedesktop.org/wayland/wayland/-/merge_requests/340
|
||||
*/
|
||||
SDL_SendMouseMotion(0, window->sdlwindow, seat->pointer.sdl_id, false, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@
|
|||
#include "xdg-shell-client-protocol.h"
|
||||
#include "xdg-toplevel-icon-v1-client-protocol.h"
|
||||
#include "color-management-v1-client-protocol.h"
|
||||
#include "pointer-warp-v1-client-protocol.h"
|
||||
|
||||
#ifdef HAVE_LIBDECOR_H
|
||||
#include <libdecor.h>
|
||||
|
|
@ -1311,6 +1312,8 @@ static void display_handle_global(void *data, struct wl_registry *registry, uint
|
|||
} else if (SDL_strcmp(interface, "wp_color_manager_v1") == 0) {
|
||||
d->wp_color_manager_v1 = wl_registry_bind(d->registry, id, &wp_color_manager_v1_interface, 1);
|
||||
Wayland_InitColorManager(d);
|
||||
} else if (SDL_strcmp(interface, "wp_pointer_warp_v1") == 0) {
|
||||
d->wp_pointer_warp_v1 = wl_registry_bind(d->registry, id, &wp_pointer_warp_v1_interface, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1620,6 +1623,11 @@ static void Wayland_VideoCleanup(SDL_VideoDevice *_this)
|
|||
data->wp_color_manager_v1 = NULL;
|
||||
}
|
||||
|
||||
if (data->wp_pointer_warp_v1) {
|
||||
wp_pointer_warp_v1_destroy(data->wp_pointer_warp_v1);
|
||||
data->wp_pointer_warp_v1 = NULL;
|
||||
}
|
||||
|
||||
if (data->compositor) {
|
||||
wl_compositor_destroy(data->compositor);
|
||||
data->compositor = NULL;
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ struct SDL_VideoData
|
|||
} shell;
|
||||
struct zwp_relative_pointer_manager_v1 *relative_pointer_manager;
|
||||
struct zwp_pointer_constraints_v1 *pointer_constraints;
|
||||
struct wp_pointer_warp_v1 *wp_pointer_warp_v1;
|
||||
struct wp_cursor_shape_manager_v1 *cursor_shape_manager;
|
||||
struct wl_data_device_manager *data_device_manager;
|
||||
struct zwp_primary_selection_device_manager_v1 *primary_selection_device_manager;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,72 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<protocol name="pointer_warp_v1">
|
||||
<copyright>
|
||||
Copyright © 2024 Neal Gompa
|
||||
Copyright © 2024 Xaver Hugl
|
||||
Copyright © 2024 Matthias Klumpp
|
||||
Copyright © 2024 Vlad Zahorodnii
|
||||
|
||||
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.
|
||||
</copyright>
|
||||
|
||||
<interface name="wp_pointer_warp_v1" version="1">
|
||||
<description summary="reposition the pointer to a location on a surface">
|
||||
This global interface allows applications to request the pointer to be
|
||||
moved to a position relative to a wl_surface.
|
||||
|
||||
Note that if the desired behavior is to constrain the pointer to an area
|
||||
or lock it to a position, this protocol does not provide a reliable way
|
||||
to do that. The pointer constraint and pointer lock protocols should be
|
||||
used for those use cases instead.
|
||||
|
||||
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.
|
||||
</description>
|
||||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="destroy the warp manager">
|
||||
Destroy the pointer warp manager.
|
||||
</description>
|
||||
</request>
|
||||
|
||||
<request name="warp_pointer">
|
||||
<description summary="reposition the pointer">
|
||||
Request the compositor to move the pointer to a surface-local position.
|
||||
Whether or not the compositor honors the request is implementation defined,
|
||||
but it should
|
||||
- honor it if the surface has pointer focus, including
|
||||
when it has an implicit pointer grab
|
||||
- reject it if the enter serial is incorrect
|
||||
- reject it if the requested position is outside of the surface
|
||||
|
||||
Note that the enter serial is valid for any surface of the client,
|
||||
and does not have to be from the surface the pointer is warped to.
|
||||
|
||||
</description>
|
||||
<arg name="surface" type="object" interface="wl_surface"
|
||||
summary="surface to position the pointer on"/>
|
||||
<arg name="pointer" type="object" interface="wl_pointer"
|
||||
summary="the pointer that should be repositioned"/>
|
||||
<arg name="x" type="fixed"/>
|
||||
<arg name="y" type="fixed"/>
|
||||
<arg name="serial" type="uint" summary="serial number of the enter event"/>
|
||||
</request>
|
||||
</interface>
|
||||
</protocol>
|
||||
Loading…
Reference in New Issue