diff options
Diffstat (limited to 'src')
10 files changed, 359 insertions, 1 deletions
diff --git a/src/3rdparty/protocol/qt_attribution.json b/src/3rdparty/protocol/qt_attribution.json index f51599de..76d8d3f0 100644 --- a/src/3rdparty/protocol/qt_attribution.json +++ b/src/3rdparty/protocol/qt_attribution.json @@ -301,5 +301,22 @@ "License": "MIT License", "LicenseFile": "MIT_LICENSE.txt", "Copyright": "Copyright © 2013, 2014 Collabora, Ltd." - } + }, + + { + "Id": "xdg-foreign-unstable-v2", + "Name": "Wayland XDG Foreign Protocol", + "QDocModule": "qtwaylandcompositor", + "QtUsage": "Used in the Qt Wayland platform plugin", + "Files": "xdg-foreign-unstable-v2.xml", + + "Description": "Allows referencing surfaces of different clients", + "Homepage": "https://wayland.freedesktop.org", + "Version": "1", + "DownloadLocation": "https://gitlab.freedesktop.org/wayland/wayland-protocols/-/raw/1.25/unstable/xdg-foreign/xdg-foreign-unstable-v2.xml", + "LicenseId": "MIT", + "License": "MIT License", + "LicenseFile": "MIT_LICENSE.txt", + "Copyright": "Copyright © 2015-2016 Red Hat Inc." + }, ] diff --git a/src/3rdparty/protocol/xdg-foreign-unstable-v2.xml b/src/3rdparty/protocol/xdg-foreign-unstable-v2.xml new file mode 100644 index 00000000..cc3271dc --- /dev/null +++ b/src/3rdparty/protocol/xdg-foreign-unstable-v2.xml @@ -0,0 +1,200 @@ +<?xml version="1.0" encoding="UTF-8"?> +<protocol name="xdg_foreign_unstable_v2"> + + <copyright> + Copyright © 2015-2016 Red Hat Inc. + + 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> + + <description summary="Protocol for exporting xdg surface handles"> + This protocol specifies a way for making it possible to reference a surface + of a different client. With such a reference, a client can, by using the + interfaces provided by this protocol, manipulate the relationship between + its own surfaces and the surface of some other client. For example, stack + some of its own surface above the other clients surface. + + In order for a client A to get a reference of a surface of client B, client + B must first export its surface using xdg_exporter.export_toplevel. Upon + doing this, client B will receive a handle (a unique string) that it may + share with client A in some way (for example D-Bus). After client A has + received the handle from client B, it may use xdg_importer.import_toplevel + to create a reference to the surface client B just exported. See the + corresponding requests for details. + + A possible use case for this is out-of-process dialogs. For example when a + sandboxed client without file system access needs the user to select a file + on the file system, given sandbox environment support, it can export its + surface, passing the exported surface handle to an unsandboxed process that + can show a file browser dialog and stack it above the sandboxed client's + surface. + + Warning! The protocol described in this file is experimental and backward + incompatible changes may be made. Backward compatible changes may be added + together with the corresponding interface version bump. Backward + incompatible changes are done by bumping the version number in the protocol + and interface names and resetting the interface version. Once the protocol + is to be declared stable, the 'z' prefix and the version number in the + protocol and interface names are removed and the interface version number is + reset. + </description> + + <interface name="zxdg_exporter_v2" version="1"> + <description summary="interface for exporting surfaces"> + A global interface used for exporting surfaces that can later be imported + using xdg_importer. + </description> + + <request name="destroy" type="destructor"> + <description summary="destroy the xdg_exporter object"> + Notify the compositor that the xdg_exporter object will no longer be + used. + </description> + </request> + + <enum name="error"> + <description summary="error values"> + These errors can be emitted in response to invalid xdg_exporter + requests. + </description> + <entry name="invalid_surface" value="0" summary="surface is not an xdg_toplevel"/> + </enum> + + <request name="export_toplevel"> + <description summary="export a toplevel surface"> + The export_toplevel request exports the passed surface so that it can later be + imported via xdg_importer. When called, a new xdg_exported object will + be created and xdg_exported.handle will be sent immediately. See the + corresponding interface and event for details. + + A surface may be exported multiple times, and each exported handle may + be used to create an xdg_imported multiple times. Only xdg_toplevel + equivalent surfaces may be exported, otherwise an invalid_surface + protocol error is sent. + </description> + <arg name="id" type="new_id" interface="zxdg_exported_v2" + summary="the new xdg_exported object"/> + <arg name="surface" type="object" interface="wl_surface" + summary="the surface to export"/> + </request> + </interface> + + <interface name="zxdg_importer_v2" version="1"> + <description summary="interface for importing surfaces"> + A global interface used for importing surfaces exported by xdg_exporter. + With this interface, a client can create a reference to a surface of + another client. + </description> + + <request name="destroy" type="destructor"> + <description summary="destroy the xdg_importer object"> + Notify the compositor that the xdg_importer object will no longer be + used. + </description> + </request> + + <request name="import_toplevel"> + <description summary="import a toplevel surface"> + The import_toplevel request imports a surface from any client given a handle + retrieved by exporting said surface using xdg_exporter.export_toplevel. + When called, a new xdg_imported object will be created. This new object + represents the imported surface, and the importing client can + manipulate its relationship using it. See xdg_imported for details. + </description> + <arg name="id" type="new_id" interface="zxdg_imported_v2" + summary="the new xdg_imported object"/> + <arg name="handle" type="string" + summary="the exported surface handle"/> + </request> + </interface> + + <interface name="zxdg_exported_v2" version="1"> + <description summary="an exported surface handle"> + An xdg_exported object represents an exported reference to a surface. The + exported surface may be referenced as long as the xdg_exported object not + destroyed. Destroying the xdg_exported invalidates any relationship the + importer may have established using xdg_imported. + </description> + + <request name="destroy" type="destructor"> + <description summary="unexport the exported surface"> + Revoke the previously exported surface. This invalidates any + relationship the importer may have set up using the xdg_imported created + given the handle sent via xdg_exported.handle. + </description> + </request> + + <event name="handle"> + <description summary="the exported surface handle"> + The handle event contains the unique handle of this exported surface + reference. It may be shared with any client, which then can use it to + import the surface by calling xdg_importer.import_toplevel. A handle + may be used to import the surface multiple times. + </description> + <arg name="handle" type="string" summary="the exported surface handle"/> + </event> + </interface> + + <interface name="zxdg_imported_v2" version="1"> + <description summary="an imported surface handle"> + An xdg_imported object represents an imported reference to surface exported + by some client. A client can use this interface to manipulate + relationships between its own surfaces and the imported surface. + </description> + + <enum name="error"> + <description summary="error values"> + These errors can be emitted in response to invalid xdg_imported + requests. + </description> + <entry name="invalid_surface" value="0" summary="surface is not an xdg_toplevel"/> + </enum> + + <request name="destroy" type="destructor"> + <description summary="destroy the xdg_imported object"> + Notify the compositor that it will no longer use the xdg_imported + object. Any relationship that may have been set up will at this point + be invalidated. + </description> + </request> + + <request name="set_parent_of"> + <description summary="set as the parent of some surface"> + Set the imported surface as the parent of some surface of the client. + The passed surface must be an xdg_toplevel equivalent, otherwise an + invalid_surface protocol error is sent. Calling this function sets up + a surface to surface relation with the same stacking and positioning + semantics as xdg_toplevel.set_parent. + </description> + <arg name="surface" type="object" interface="wl_surface" + summary="the child surface"/> + </request> + + <event name="destroyed"> + <description summary="the imported surface handle has been destroyed"> + The imported surface handle has been destroyed and any relationship set + up has been invalidated. This may happen for various reasons, for + example if the exported surface or the exported surface handle has been + destroyed, if the handle used for importing was invalid. + </description> + </event> + </interface> + +</protocol> diff --git a/src/client/qwaylandshellsurface_p.h b/src/client/qwaylandshellsurface_p.h index c133269a..5e269510 100644 --- a/src/client/qwaylandshellsurface_p.h +++ b/src/client/qwaylandshellsurface_p.h @@ -71,6 +71,8 @@ public: virtual void setXdgActivationToken(const QString &token); virtual void requestXdgActivationToken(quint32 serial); + virtual QString externWindowHandle() { return QString(); } + inline QWaylandWindow *window() { return m_window; } QPlatformWindow *platformWindow(); struct wl_surface *wlSurface(); diff --git a/src/client/qwaylandwindowmanagerintegration.cpp b/src/client/qwaylandwindowmanagerintegration.cpp index b394d69b..dababe7c 100644 --- a/src/client/qwaylandwindowmanagerintegration.cpp +++ b/src/client/qwaylandwindowmanagerintegration.cpp @@ -5,6 +5,7 @@ #include "qwaylandscreen_p.h" #include "qwaylandwindow_p.h" #include "qwaylanddisplay_p.h" +#include "qwaylandshellsurface_p.h" #include <stdint.h> #include <QtCore/QEvent> @@ -106,6 +107,17 @@ bool QWaylandWindowManagerIntegration::openDocument(const QUrl &url) return QGenericUnixServices::openDocument(url); } +QString QWaylandWindowManagerIntegration::portalWindowIdentifier(QWindow *window) +{ + if (window && window->handle()) { + auto shellSurface = static_cast<QWaylandWindow *>(window->handle())->shellSurface(); + if (shellSurface) { + const QString handle = shellSurface->externWindowHandle(); + return QLatin1String("wayland:") + handle; + } + } + return QString(); +} } QT_END_NAMESPACE diff --git a/src/client/qwaylandwindowmanagerintegration_p.h b/src/client/qwaylandwindowmanagerintegration_p.h index ea57911f..18eb171b 100644 --- a/src/client/qwaylandwindowmanagerintegration_p.h +++ b/src/client/qwaylandwindowmanagerintegration_p.h @@ -42,6 +42,7 @@ public: bool openUrl(const QUrl &url) override; bool openDocument(const QUrl &url) override; + QString portalWindowIdentifier(QWindow *window) override; bool showIsFullScreen() const; diff --git a/src/plugins/shellintegration/xdg-shell/CMakeLists.txt b/src/plugins/shellintegration/xdg-shell/CMakeLists.txt index 1ae0d5ff..df691d55 100644 --- a/src/plugins/shellintegration/xdg-shell/CMakeLists.txt +++ b/src/plugins/shellintegration/xdg-shell/CMakeLists.txt @@ -16,6 +16,7 @@ qt_internal_add_plugin(QWaylandXdgShellIntegrationPlugin qwaylandxdgactivationv1.cpp qwaylandxdgactivationv1_p.h qwaylandxdgshell.cpp qwaylandxdgshell_p.h qwaylandxdgshellintegration.cpp qwaylandxdgshellintegration_p.h + qwaylandxdgexporterv2.cpp qwaylandxdgexporterv2_p.h LIBRARIES Qt::Core Qt::Gui @@ -29,6 +30,7 @@ qt6_generate_wayland_protocol_client_sources(QWaylandXdgShellIntegrationPlugin ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/protocol/xdg-decoration-unstable-v1.xml ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/protocol/xdg-shell.xml ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/protocol/xdg-activation-v1.xml + ${CMAKE_CURRENT_SOURCE_DIR}/../../../3rdparty/protocol/xdg-foreign-unstable-v2.xml ) #### Keys ignored in scope 1:.:.:xdg-shell.pro:<TRUE>: diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgexporterv2.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgexporterv2.cpp new file mode 100644 index 00000000..58baad02 --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgexporterv2.cpp @@ -0,0 +1,47 @@ +// Copyright (C) 2022 David Reondo <kde@david-redondo.de> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include "qwaylandxdgexporterv2_p.h" + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +QWaylandXdgExportedV2::QWaylandXdgExportedV2(::zxdg_exported_v2 *object) + : QtWayland::zxdg_exported_v2(object) +{ +} + +QWaylandXdgExportedV2::~QWaylandXdgExportedV2() +{ + destroy(); +} + +void QWaylandXdgExportedV2::zxdg_exported_v2_handle(const QString &handle) +{ + mHandle = handle; +} + +QString QWaylandXdgExportedV2::handle() const +{ + return mHandle; +} + +QWaylandXdgExporterV2::QWaylandXdgExporterV2(wl_registry *registry, uint32_t id, int version) + : QtWayland::zxdg_exporter_v2(registry, id, qMin(version, 1)) +{ +} + +QWaylandXdgExporterV2::~QWaylandXdgExporterV2() +{ + destroy(); +} + +QtWaylandClient::QWaylandXdgExportedV2 *QWaylandXdgExporterV2::exportToplevel(wl_surface *surface) +{ + return new QWaylandXdgExportedV2(export_toplevel(surface)); +} + +} + +QT_END_NAMESPACE diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgexporterv2_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgexporterv2_p.h new file mode 100644 index 00000000..b260dbac --- /dev/null +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgexporterv2_p.h @@ -0,0 +1,50 @@ +// Copyright (C) 2022 David Reondo <kde@david-redondo.de> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QWAYLANDXDGEXPORTERV2_H +#define QWAYLANDXDGEXPORTERV2_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <qwayland-xdg-foreign-unstable-v2.h> + +#include <QtWaylandClient/qtwaylandclientglobal.h> + +QT_BEGIN_NAMESPACE + +namespace QtWaylandClient { + +class QWaylandXdgExportedV2 : public QtWayland::zxdg_exported_v2 +{ +public: + explicit QWaylandXdgExportedV2(::zxdg_exported_v2 *object); + ~QWaylandXdgExportedV2() override; + QString handle() const; + +private: + void zxdg_exported_v2_handle(const QString &handle) override; + QString mHandle; +}; + +class QWaylandXdgExporterV2 : public QtWayland::zxdg_exporter_v2 +{ +public: + QWaylandXdgExporterV2(wl_registry *registry, uint32_t id, int version); + ~QWaylandXdgExporterV2() override; + QWaylandXdgExportedV2 *exportToplevel(wl_surface *surface); +}; + +} + +QT_END_NAMESPACE + +#endif // QWAYLANDXDGEXPORTERV2_H diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp index c4b1942b..87152fbd 100644 --- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell.cpp @@ -4,6 +4,8 @@ #include "qwaylandxdgshell_p.h" +#include "qwaylandxdgexporterv2_p.h" + #include <QtWaylandClient/private/qwaylanddisplay_p.h> #include <QtWaylandClient/private/qwaylandwindow_p.h> #include <QtWaylandClient/private/qwaylandinputdevice_p.h> @@ -537,6 +539,19 @@ void QWaylandXdgSurface::setXdgActivationToken(const QString &token) } } +QString QWaylandXdgSurface::externWindowHandle() +{ + if (!m_toplevel || !m_shell->exporter()) { + return QString(); + } + if (!m_toplevel->m_exported) { + m_toplevel->m_exported.reset(m_shell->exporter()->exportToplevel(m_window->wlSurface())); + // handle events is sent immediately + m_shell->display()->forceRoundTrip(); + } + return m_toplevel->m_exported->handle(); +} + QWaylandXdgShell::QWaylandXdgShell(QWaylandDisplay *display, uint32_t id, uint32_t availableVersion) : QtWayland::xdg_wm_base(display->wl_registry(), id, qMin(availableVersion, 2u)) , m_display(display) @@ -570,6 +585,10 @@ void QWaylandXdgShell::handleRegistryGlobal(void *data, wl_registry *registry, u if (interface == QLatin1String(QWaylandXdgActivationV1::interface()->name)) { xdgShell->m_xdgActivation.reset(new QWaylandXdgActivationV1(registry, id, version)); } + + if (interface == QLatin1String(QWaylandXdgExporterV2::interface()->name)) { + xdgShell->m_xdgExporter.reset(new QWaylandXdgExporterV2(registry, id, version)); + } } } diff --git a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h index 8410253c..d3cdb9d4 100644 --- a/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h +++ b/src/plugins/shellintegration/xdg-shell/qwaylandxdgshell_p.h @@ -37,6 +37,8 @@ namespace QtWaylandClient { class QWaylandDisplay; class QWaylandInputDevice; class QWaylandXdgShell; +class QWaylandXdgExportedV2; +class QWaylandXdgExporterV2; class Q_WAYLANDCLIENT_EXPORT QWaylandXdgSurface : public QWaylandShellSurface, public QtWayland::xdg_surface { @@ -62,6 +64,7 @@ public: bool requestActivate() override; void setXdgActivationToken(const QString &token) override; void requestXdgActivationToken(quint32 serial) override; + QString externWindowHandle() override; void setSizeHints(); @@ -98,6 +101,7 @@ private: QWaylandXdgSurface *m_xdgSurface = nullptr; QWaylandXdgToplevelDecorationV1 *m_decoration = nullptr; + QScopedPointer<QWaylandXdgExportedV2> m_exported; }; class Popup : public QtWayland::xdg_popup { @@ -138,8 +142,11 @@ public: QWaylandXdgShell(QWaylandDisplay *display, uint32_t id, uint32_t availableVersion); ~QWaylandXdgShell() override; + QWaylandDisplay *display() const { return m_display; } + QWaylandXdgDecorationManagerV1 *decorationManager() { return m_xdgDecorationManager.data(); } QWaylandXdgActivationV1 *activation() const { return m_xdgActivation.data(); } + QWaylandXdgExporterV2 *exporter() const { return m_xdgExporter.data(); } QWaylandXdgSurface *getXdgSurface(QWaylandWindow *window); protected: @@ -152,6 +159,7 @@ private: QWaylandDisplay *m_display = nullptr; QScopedPointer<QWaylandXdgDecorationManagerV1> m_xdgDecorationManager; QScopedPointer<QWaylandXdgActivationV1> m_xdgActivation; + QScopedPointer<QWaylandXdgExporterV2> m_xdgExporter; QWaylandXdgSurface::Popup *m_topmostGrabbingPopup = nullptr; friend class QWaylandXdgSurface; |