xdgforeign: Allow exporting surfaces internally
Without a client asking for it. This way we can send a surface to another helper application, such as the window killer. An ExportedSurface wrapper class is introduced which represents an exported surface in a windowing-system independent way.
This commit is contained in:
parent
2b868edb9e
commit
9b7718459e
5 changed files with 99 additions and 38 deletions
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2017 Marco Martin <notmart@gmail.com>
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
SPDX-FileCopyrightText: 2023 Kai Uwe Broulik <kde@broulik.de>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
@ -15,6 +16,29 @@ namespace KWin
|
|||
static const quint32 s_exporterVersion = 1;
|
||||
static const quint32 s_importerVersion = 1;
|
||||
|
||||
XdgExportedSurface::XdgExportedSurface(SurfaceInterface *surface)
|
||||
: QObject()
|
||||
, m_handle(QUuid::createUuid().toString())
|
||||
, m_surface(surface)
|
||||
{
|
||||
connect(m_surface, &QObject::destroyed, this, &XdgExportedSurface::handleSurfaceDestroyed);
|
||||
}
|
||||
|
||||
QString XdgExportedSurface::handle() const
|
||||
{
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
SurfaceInterface *XdgExportedSurface::surface() const
|
||||
{
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
void XdgExportedSurface::handleSurfaceDestroyed()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
XdgForeignV2InterfacePrivate::XdgForeignV2InterfacePrivate(Display *display, XdgForeignV2Interface *_q)
|
||||
: q(_q)
|
||||
, exporter(new XdgExporterV2Interface(display, _q))
|
||||
|
@ -37,17 +61,38 @@ SurfaceInterface *XdgForeignV2Interface::transientFor(SurfaceInterface *surface)
|
|||
return d->importer->transientFor(surface);
|
||||
}
|
||||
|
||||
XdgExportedSurface *XdgForeignV2Interface::exportSurface(SurfaceInterface *surface)
|
||||
{
|
||||
return d->exporter->exportSurface(surface);
|
||||
}
|
||||
|
||||
XdgExporterV2Interface::XdgExporterV2Interface(Display *display, XdgForeignV2Interface *foreign)
|
||||
: QObject(foreign)
|
||||
, QtWaylandServer::zxdg_exporter_v2(*display, s_exporterVersion)
|
||||
{
|
||||
}
|
||||
|
||||
XdgExportedV2Interface *XdgExporterV2Interface::exportedSurface(const QString &handle)
|
||||
XdgExportedSurface *XdgExporterV2Interface::exportedSurface(const QString &handle) const
|
||||
{
|
||||
return m_exportedSurfaces.value(handle);
|
||||
}
|
||||
|
||||
XdgExportedSurface *XdgExporterV2Interface::exportSurface(SurfaceInterface *surface)
|
||||
{
|
||||
auto *exported = new XdgExportedSurface(surface);
|
||||
addExported(exported);
|
||||
return exported;
|
||||
}
|
||||
|
||||
void XdgExporterV2Interface::addExported(XdgExportedSurface *exported)
|
||||
{
|
||||
const QString handle = exported->handle();
|
||||
connect(exported, &XdgExportedSurface::destroyed, this, [this, handle] {
|
||||
m_exportedSurfaces.remove(handle);
|
||||
});
|
||||
m_exportedSurfaces[handle] = exported;
|
||||
}
|
||||
|
||||
void XdgExporterV2Interface::zxdg_exporter_v2_destroy(Resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource->handle);
|
||||
|
@ -68,15 +113,9 @@ void XdgExporterV2Interface::zxdg_exporter_v2_export_toplevel(Resource *resource
|
|||
}
|
||||
|
||||
XdgExportedV2Interface *exported = new XdgExportedV2Interface(surface, exportedResource);
|
||||
const QString handle = QUuid::createUuid().toString();
|
||||
addExported(exported);
|
||||
|
||||
// a surface not exported anymore
|
||||
connect(exported, &XdgExportedV2Interface::destroyed, this, [this, handle]() {
|
||||
m_exportedSurfaces.remove(handle);
|
||||
});
|
||||
|
||||
m_exportedSurfaces[handle] = exported;
|
||||
exported->send_handle(handle);
|
||||
exported->send_handle(exported->handle());
|
||||
}
|
||||
|
||||
XdgImporterV2Interface::XdgImporterV2Interface(Display *display, XdgForeignV2Interface *foreign)
|
||||
|
@ -110,7 +149,7 @@ void XdgImporterV2Interface::zxdg_importer_v2_import_toplevel(Resource *resource
|
|||
|
||||
// If there is no exported surface with the specified handle, we must still create an
|
||||
// inert xdg_imported object and send the destroyed event right afterwards.
|
||||
XdgExportedV2Interface *exported = m_foreign->d->exporter->exportedSurface(handle);
|
||||
XdgExportedSurface *exported = m_foreign->d->exporter->exportedSurface(handle);
|
||||
if (!exported) {
|
||||
auto imported = new XdgDummyImportedV2Interface(importedResource);
|
||||
imported->send_destroyed();
|
||||
|
@ -175,15 +214,9 @@ void XdgImporterV2Interface::unlink(XdgImportedV2Interface *parent, SurfaceInter
|
|||
}
|
||||
|
||||
XdgExportedV2Interface::XdgExportedV2Interface(SurfaceInterface *surface, wl_resource *resource)
|
||||
: QtWaylandServer::zxdg_exported_v2(resource)
|
||||
, m_surface(surface)
|
||||
: XdgExportedSurface(surface)
|
||||
, QtWaylandServer::zxdg_exported_v2(resource)
|
||||
{
|
||||
connect(surface, &QObject::destroyed, this, &XdgExportedV2Interface::handleSurfaceDestroyed);
|
||||
}
|
||||
|
||||
SurfaceInterface *XdgExportedV2Interface::surface()
|
||||
{
|
||||
return m_surface;
|
||||
}
|
||||
|
||||
void XdgExportedV2Interface::zxdg_exported_v2_destroy(Resource *resource)
|
||||
|
@ -196,11 +229,6 @@ void XdgExportedV2Interface::zxdg_exported_v2_destroy_resource(Resource *resourc
|
|||
delete this;
|
||||
}
|
||||
|
||||
void XdgExportedV2Interface::handleSurfaceDestroyed()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
XdgDummyImportedV2Interface::XdgDummyImportedV2Interface(wl_resource *resource)
|
||||
: QtWaylandServer::zxdg_imported_v2(resource)
|
||||
{
|
||||
|
@ -216,11 +244,11 @@ void XdgDummyImportedV2Interface::zxdg_imported_v2_destroy_resource(Resource *re
|
|||
delete this;
|
||||
}
|
||||
|
||||
XdgImportedV2Interface::XdgImportedV2Interface(XdgExportedV2Interface *exported, wl_resource *resource)
|
||||
XdgImportedV2Interface::XdgImportedV2Interface(XdgExportedSurface *exported, wl_resource *resource)
|
||||
: QtWaylandServer::zxdg_imported_v2(resource)
|
||||
, m_exported(exported)
|
||||
{
|
||||
connect(exported, &QObject::destroyed, this, &XdgImportedV2Interface::handleExportedDestroyed);
|
||||
connect(exported, &XdgExportedSurface::destroyed, this, &XdgImportedV2Interface::handleExportedDestroyed);
|
||||
}
|
||||
|
||||
SurfaceInterface *XdgImportedV2Interface::child() const
|
||||
|
|
|
@ -16,6 +16,23 @@ class Display;
|
|||
class SurfaceInterface;
|
||||
class XdgForeignV2InterfacePrivate;
|
||||
|
||||
class KWIN_EXPORT XdgExportedSurface : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
XdgExportedSurface(SurfaceInterface *surface);
|
||||
|
||||
QString handle() const;
|
||||
SurfaceInterface *surface() const;
|
||||
|
||||
private:
|
||||
void handleSurfaceDestroyed();
|
||||
|
||||
const QString m_handle;
|
||||
SurfaceInterface *m_surface;
|
||||
};
|
||||
|
||||
/**
|
||||
* This class encapsulates the server side logic of the XdgForeign protocol.
|
||||
* a process can export a surface to be identifiable by a server-wide unique
|
||||
|
@ -39,6 +56,13 @@ public:
|
|||
*/
|
||||
SurfaceInterface *transientFor(SurfaceInterface *surface);
|
||||
|
||||
/**
|
||||
* Exports the given surface without creating a Wayland interface object.
|
||||
* @param surface The surface to export
|
||||
* @return The handle, this can then be passed to other clients.
|
||||
*/
|
||||
XdgExportedSurface *exportSurface(SurfaceInterface *surface);
|
||||
|
||||
Q_SIGNALS:
|
||||
/**
|
||||
* A surface got a new imported transient parent
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
/*
|
||||
SPDX-FileCopyrightText: 2017 Marco Martin <notmart@gmail.com>
|
||||
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
||||
SPDX-FileCopyrightText: 2023 Kai Uwe Broulik <kde@broulik.de>
|
||||
|
||||
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
||||
*/
|
||||
|
@ -11,6 +12,8 @@
|
|||
|
||||
#include <qwayland-server-xdg-foreign-unstable-v2.h>
|
||||
|
||||
#include <QPointer>
|
||||
|
||||
namespace KWin
|
||||
{
|
||||
class XdgExportedV2Interface;
|
||||
|
@ -35,14 +38,17 @@ class XdgExporterV2Interface : public QObject, public QtWaylandServer::zxdg_expo
|
|||
public:
|
||||
XdgExporterV2Interface(Display *display, XdgForeignV2Interface *foreign);
|
||||
|
||||
XdgExportedV2Interface *exportedSurface(const QString &handle);
|
||||
XdgExportedSurface *exportedSurface(const QString &handle) const;
|
||||
XdgExportedSurface *exportSurface(SurfaceInterface *surface);
|
||||
|
||||
protected:
|
||||
void zxdg_exporter_v2_destroy(Resource *resource) override;
|
||||
void zxdg_exporter_v2_export_toplevel(Resource *resource, uint32_t id, wl_resource *surface) override;
|
||||
|
||||
private:
|
||||
QHash<QString, XdgExportedV2Interface *> m_exportedSurfaces;
|
||||
void addExported(XdgExportedSurface *exported);
|
||||
|
||||
QHash<QString, XdgExportedSurface *> m_exportedSurfaces;
|
||||
};
|
||||
|
||||
class XdgImporterV2Interface : public QObject, public QtWaylandServer::zxdg_importer_v2
|
||||
|
@ -67,24 +73,16 @@ private:
|
|||
QHash<XdgImportedV2Interface *, SurfaceInterface *> m_children; // parent->child hash
|
||||
};
|
||||
|
||||
class XdgExportedV2Interface : public QObject, public QtWaylandServer::zxdg_exported_v2
|
||||
class XdgExportedV2Interface : public XdgExportedSurface, public QtWaylandServer::zxdg_exported_v2
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit XdgExportedV2Interface(SurfaceInterface *surface, wl_resource *resource);
|
||||
|
||||
SurfaceInterface *surface();
|
||||
|
||||
protected:
|
||||
void zxdg_exported_v2_destroy(Resource *resource) override;
|
||||
void zxdg_exported_v2_destroy_resource(Resource *resource) override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void handleSurfaceDestroyed();
|
||||
|
||||
private:
|
||||
SurfaceInterface *m_surface;
|
||||
};
|
||||
|
||||
class XdgDummyImportedV2Interface : public QtWaylandServer::zxdg_imported_v2
|
||||
|
@ -101,7 +99,7 @@ class XdgImportedV2Interface : public QObject, QtWaylandServer::zxdg_imported_v2
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit XdgImportedV2Interface(XdgExportedV2Interface *exported, wl_resource *resource);
|
||||
explicit XdgImportedV2Interface(XdgExportedSurface *exported, wl_resource *resource);
|
||||
|
||||
SurfaceInterface *child() const;
|
||||
SurfaceInterface *surface() const;
|
||||
|
@ -113,7 +111,7 @@ private Q_SLOTS:
|
|||
void handleExportedDestroyed();
|
||||
|
||||
private:
|
||||
XdgExportedV2Interface *m_exported;
|
||||
XdgExportedSurface *m_exported;
|
||||
QPointer<SurfaceInterface> m_child;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -510,6 +510,11 @@ SurfaceInterface *WaylandServer::findForeignTransientForSurface(SurfaceInterface
|
|||
return m_XdgForeign->transientFor(surface);
|
||||
}
|
||||
|
||||
XdgExportedSurface *WaylandServer::exportAsForeign(SurfaceInterface *surface)
|
||||
{
|
||||
return m_XdgForeign->exportSurface(surface);
|
||||
}
|
||||
|
||||
void WaylandServer::initWorkspace()
|
||||
{
|
||||
auto inputPanelV1Integration = new InputPanelV1Integration(this);
|
||||
|
|
|
@ -36,6 +36,7 @@ class PlasmaVirtualDesktopManagementInterface;
|
|||
class PlasmaWindowManagementInterface;
|
||||
class OutputDeviceV2Interface;
|
||||
class OutputManagementV2Interface;
|
||||
class XdgExportedSurface;
|
||||
class XdgForeignV2Interface;
|
||||
class XdgOutputManagerV1Interface;
|
||||
class DrmClientBufferIntegration;
|
||||
|
@ -153,6 +154,11 @@ public:
|
|||
*/
|
||||
SurfaceInterface *findForeignTransientForSurface(SurfaceInterface *surface);
|
||||
|
||||
/**
|
||||
* Exports a surface with the foreign protocol
|
||||
*/
|
||||
XdgExportedSurface *exportAsForeign(SurfaceInterface *surface);
|
||||
|
||||
/**
|
||||
* @returns file descriptor for Xwayland to connect to.
|
||||
*/
|
||||
|
|
Loading…
Reference in a new issue