diff options
author | Xaver Hugl <[email protected]> | 2025-06-16 18:08:23 +0300 |
---|---|---|
committer | David Edmundson <[email protected]> | 2025-06-25 16:56:10 +0100 |
commit | 91ef07052720b01478e82860798feac5fc76ebd2 (patch) | |
tree | 3c537931451580d6ed8ed335301fda7b2699e82c | |
parent | bc6f4c5db46e1d8263e32e02f2ca6e49d6b4082d (diff) |
This supports partial usage of QCursor::setPos to move the mouse cursor.
The wayland protocol only supports moving the cursor within the bounds
of the window with pointer focus. Co-ordinates are mapped from global
space to be relative to the focussed window.
[ChangeLog][Third-Party Code] New protocol synced from wayland-protocols
Fixes: QTBUG-127077
Pick-to: 6.10
Change-Id: Ic10142b2771fc9e6afc723b115b1b013a671e711
Reviewed-by: David Redondo <[email protected]>
7 files changed, 128 insertions, 2 deletions
diff --git a/src/3rdparty/wayland/protocols/pointer-warp/REUSE.toml b/src/3rdparty/wayland/protocols/pointer-warp/REUSE.toml new file mode 100644 index 00000000000..61332b79db6 --- /dev/null +++ b/src/3rdparty/wayland/protocols/pointer-warp/REUSE.toml @@ -0,0 +1,10 @@ +version = 1 + +[[annotations]] +path = "pointer-warp-v1.xml" +precedence = "closest" +SPDX-FileCopyrightText = ["Copyright © 2024 Neal Gompa", + "Copyright © 2024 Xaver Hugl", + "Copyright © 2024 Matthias Klumpp", + "Copyright © 2024 Vlad Zahorodnii"] +SPDX-License-Identifier = "MIT" diff --git a/src/3rdparty/wayland/protocols/pointer-warp/pointer-warp-v1.xml b/src/3rdparty/wayland/protocols/pointer-warp/pointer-warp-v1.xml new file mode 100644 index 00000000000..158dad83c5d --- /dev/null +++ b/src/3rdparty/wayland/protocols/pointer-warp/pointer-warp-v1.xml @@ -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> diff --git a/src/3rdparty/wayland/protocols/pointer-warp/qt_attribution.json b/src/3rdparty/wayland/protocols/pointer-warp/qt_attribution.json new file mode 100644 index 00000000000..83cd73c3570 --- /dev/null +++ b/src/3rdparty/wayland/protocols/pointer-warp/qt_attribution.json @@ -0,0 +1,17 @@ +[ + { + "Id": "wayland-pointer-warp-protocol", + "Name": "Wayland Pointer Warp Protocol", + "QDocModule": "qtwaylandcompositor", + "QtUsage": "Used in the Qt Wayland platform plugin", + "Files": "pointer-warp-v1.xml", + "Description": "", + "Homepage": "https://wayland.freedesktop.org/", + "Version": "version 1", + "DownloadLocation": "https://cgit.freedesktop.org/wayland/wayland-protocols/plain/staging/pointer-warp/pointer-warp-v1.xml", + "LicenseId": "MIT", + "License": "MIT License", + "LicenseFile": "../MIT_LICENSE.txt", + "Copyright": "Copyright © 2024 Neal Gompa\nCopyright © 2024 Xaver Hugl\nCopyright © 2024 Matthias Klumpp\nCopyright © 2024 Vlad Zahorodnii" + } +] diff --git a/src/plugins/platforms/wayland/CMakeLists.txt b/src/plugins/platforms/wayland/CMakeLists.txt index ac90eeadfa2..32a4ae34228 100644 --- a/src/plugins/platforms/wayland/CMakeLists.txt +++ b/src/plugins/platforms/wayland/CMakeLists.txt @@ -163,6 +163,7 @@ qt6_generate_wayland_protocol_client_sources(WaylandClient ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wayland/extensions/hardware-integration.xml ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wayland/extensions/server-buffer-extension.xml ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wayland/protocols/color-management/xx-color-management-v4.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/wayland/protocols/pointer-warp/pointer-warp-v1.xml ) #### Keys ignored in scope 1:.:.:client.pro:<TRUE>: diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp index 04ab7e6a50f..4967f9d46f4 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -7,6 +7,7 @@ #include "qwaylanddisplay_p.h" #include "qwaylandinputdevice_p.h" #include "qwaylandshmbackingstore_p.h" +#include "qwayland-pointer-warp-v1.h" #include <QtGui/private/qguiapplication_p.h> #include <qpa/qplatformtheme.h> @@ -346,8 +347,22 @@ QPoint QWaylandCursor::pos() const void QWaylandCursor::setPos(const QPoint &pos) { - Q_UNUSED(pos); - qCWarning(lcQpaWayland) << "Setting cursor position is not possible on wayland"; + if (mDisplay->pointerWarp()) { + const auto seats = mDisplay->inputDevices(); + for (auto *seat : seats) { + if (!seat->pointer() || !seat->pointer()->focusWindow()) { + continue; + } + const auto focus = seat->pointer()->focusWindow(); + if (!focus->windowFrameGeometry().contains(pos)) { + continue; + } + mDisplay->pointerWarp()->warp_pointer(focus->surface(), seat->pointer()->object(), wl_fixed_from_double(pos.x() - focus->windowFrameGeometry().x()), wl_fixed_from_double(pos.y() - focus->windowFrameGeometry().y()), seat->pointer()->mEnterSerial); + return; + } + } else { + qCWarning(lcQpaWayland) << "Setting cursor position requires pointer warp v1 protocol support"; + } } void QWaylandCursor::setPosFromEnterEvent(const QPoint &pos) diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index c4cdbecf6ae..071ad78f91c 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -56,6 +56,7 @@ #include <QtWaylandClient/private/qwayland-xdg-system-bell-v1.h> #include <QtWaylandClient/private/qwayland-xdg-toplevel-drag-v1.h> #include <QtWaylandClient/private/qwayland-wlr-data-control-unstable-v1.h> +#include <QtWaylandClient/private/qwayland-pointer-warp-v1.h> #include <QtCore/private/qcore_unix_p.h> @@ -798,8 +799,12 @@ void QWaylandDisplay::registry_global(uint32_t id, const QString &interface, uin mGlobals.colorManager = std::make_unique<ColorManager>(registry, id, 1); // we need a roundtrip to receive the features the compositor supports forceRoundTrip(); + } else if (interface == QLatin1String(QtWayland::wp_pointer_warp_v1::interface()->name)) { + mGlobals.pointerWarp.reset(new WithDestructor<QtWayland::wp_pointer_warp_v1, wp_pointer_warp_v1_destroy>( + registry, id, 1)); } + mRegistryGlobals.append(RegistryGlobal(id, interface, version, registry)); emit globalAdded(mRegistryGlobals.back()); diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index c8ba4935cf6..29952886421 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -58,6 +58,7 @@ namespace QtWayland { class wp_viewporter; class xdg_system_bell_v1; class xdg_toplevel_drag_manager_v1; + class wp_pointer_warp_v1; } namespace QtWaylandClient { @@ -225,6 +226,10 @@ public: { return mGlobals.colorManager.get(); } + QtWayland::wp_pointer_warp_v1 *pointerWarp() const + { + return mGlobals.pointerWarp.get(); + } struct RegistryGlobal { uint32_t id; @@ -360,6 +365,7 @@ private: std::unique_ptr<QWaylandWindowManagerIntegration> windowManagerIntegration; std::unique_ptr<QWaylandAppMenuManager> appMenuManager; std::unique_ptr<ColorManager> colorManager; + std::unique_ptr<QtWayland::wp_pointer_warp_v1> pointerWarp; } mGlobals; int mFd = -1; |