Provide a handle for desktop portal via xdg-exporter
Change-Id: I6b2034c1833ae497ef05af7c377e4bfd3747b6fe Reviewed-by: David Edmundson <davidedmundson@kde.org>
This commit is contained in:
parent
95edea11f1
commit
4132a63f14
@ -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."
|
||||
},
|
||||
]
|
||||
|
200
src/3rdparty/wayland/protocols/xdg-foreign-unstable-v2.xml
vendored
Normal file
200
src/3rdparty/wayland/protocols/xdg-foreign-unstable-v2.xml
vendored
Normal file
@ -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>
|
@ -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>:
|
||||
|
@ -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
|
@ -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
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user