Due to being a compositor, kwin has to conform to some certain interfaces. It means a lot of virtual functions and function tables to integrate with C APIs. Naturally, we not always want to use every argument in such functions. Since we get -Wunused-parameter from -Wall, we have to plumb those unused arguments in order to suppress compiler warnings at the moment. However, I don't think that extra work is worth it. We cannot change or alter prototypes in any way to fix the warning the desired way. Q_UNUSED and similar macros are not good indicators of whether an argument is used too, we tend to overlook putting or removing those macros. I've also noticed that Q_UNUSED are not used to guide us with the removal no longer needed parameters. Therefore, I think it's worth adding -Wno-unused-parameter compiler option to stop the compiler producing warnings about unused parameters. It changes nothing except that we don't need to put Q_UNUSED anymore, which can be really cumbersome sometimes. Note that it doesn't affect unused variables, you'll still get a -Wunused-variable compiler warning if a variable is unused.
265 lines
7.6 KiB
C++
265 lines
7.6 KiB
C++
/*
|
|
SPDX-FileCopyrightText: 2017 Marco Martin <notmart@gmail.com>
|
|
SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
|
|
|
|
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
|
|
*/
|
|
|
|
#include "display.h"
|
|
#include "xdgforeign_v2_interface_p.h"
|
|
|
|
#include <QUuid>
|
|
|
|
namespace KWaylandServer
|
|
{
|
|
static const quint32 s_exporterVersion = 1;
|
|
static const quint32 s_importerVersion = 1;
|
|
|
|
XdgForeignV2InterfacePrivate::XdgForeignV2InterfacePrivate(Display *display, XdgForeignV2Interface *_q)
|
|
: q(_q)
|
|
, exporter(new XdgExporterV2Interface(display, _q))
|
|
, importer(new XdgImporterV2Interface(display, _q))
|
|
{
|
|
}
|
|
|
|
XdgForeignV2Interface::XdgForeignV2Interface(Display *display, QObject *parent)
|
|
: QObject(parent)
|
|
, d(new XdgForeignV2InterfacePrivate(display, this))
|
|
{
|
|
}
|
|
|
|
XdgForeignV2Interface::~XdgForeignV2Interface()
|
|
{
|
|
}
|
|
|
|
SurfaceInterface *XdgForeignV2Interface::transientFor(SurfaceInterface *surface)
|
|
{
|
|
return d->importer->transientFor(surface);
|
|
}
|
|
|
|
XdgExporterV2Interface::XdgExporterV2Interface(Display *display, XdgForeignV2Interface *foreign)
|
|
: QObject(foreign)
|
|
, QtWaylandServer::zxdg_exporter_v2(*display, s_exporterVersion)
|
|
, m_foreign(foreign)
|
|
{
|
|
}
|
|
|
|
XdgExportedV2Interface *XdgExporterV2Interface::exportedSurface(const QString &handle)
|
|
{
|
|
return m_exportedSurfaces.value(handle);
|
|
}
|
|
|
|
void XdgExporterV2Interface::zxdg_exporter_v2_destroy(Resource *resource)
|
|
{
|
|
wl_resource_destroy(resource->handle);
|
|
}
|
|
|
|
void XdgExporterV2Interface::zxdg_exporter_v2_export_toplevel(Resource *resource, uint32_t id, wl_resource *surface_resource)
|
|
{
|
|
SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
|
|
if (!surface) {
|
|
wl_resource_post_error(resource->handle, 0, "Invalid surface");
|
|
return;
|
|
}
|
|
|
|
wl_resource *exportedResource = wl_resource_create(resource->client(), &zxdg_exported_v2_interface, resource->version(), id);
|
|
if (!exportedResource) {
|
|
wl_client_post_no_memory(resource->client());
|
|
return;
|
|
}
|
|
|
|
XdgExportedV2Interface *exported = new XdgExportedV2Interface(surface, exportedResource);
|
|
const QString handle = QUuid::createUuid().toString();
|
|
|
|
// a surface not exported anymore
|
|
connect(exported, &XdgExportedV2Interface::destroyed, this, [this, handle]() {
|
|
m_exportedSurfaces.remove(handle);
|
|
});
|
|
|
|
m_exportedSurfaces[handle] = exported;
|
|
exported->send_handle(handle);
|
|
}
|
|
|
|
XdgImporterV2Interface::XdgImporterV2Interface(Display *display, XdgForeignV2Interface *foreign)
|
|
: QObject(foreign)
|
|
, QtWaylandServer::zxdg_importer_v2(*display, s_importerVersion)
|
|
, m_foreign(foreign)
|
|
{
|
|
}
|
|
|
|
SurfaceInterface *XdgImporterV2Interface::transientFor(SurfaceInterface *surface)
|
|
{
|
|
auto it = m_parents.constFind(surface);
|
|
if (it == m_parents.constEnd()) {
|
|
return nullptr;
|
|
}
|
|
return (*it)->surface();
|
|
}
|
|
|
|
void XdgImporterV2Interface::zxdg_importer_v2_destroy(Resource *resource)
|
|
{
|
|
wl_resource_destroy(resource->handle);
|
|
}
|
|
|
|
void XdgImporterV2Interface::zxdg_importer_v2_import_toplevel(Resource *resource, uint32_t id, const QString &handle)
|
|
{
|
|
wl_resource *importedResource = wl_resource_create(resource->client(), &zxdg_imported_v2_interface, resource->version(), id);
|
|
if (!importedResource) {
|
|
wl_client_post_no_memory(resource->client());
|
|
return;
|
|
}
|
|
|
|
// 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);
|
|
if (!exported) {
|
|
auto imported = new XdgDummyImportedV2Interface(importedResource);
|
|
imported->send_destroyed();
|
|
return;
|
|
}
|
|
|
|
XdgImportedV2Interface *imported = new XdgImportedV2Interface(exported, importedResource);
|
|
|
|
connect(imported, &XdgImportedV2Interface::childChanged, this, [this, imported](SurfaceInterface *child) {
|
|
link(imported, child);
|
|
|
|
// child surface destroyed
|
|
connect(child, &QObject::destroyed, this, [this, child]() {
|
|
unlink(nullptr, child);
|
|
});
|
|
});
|
|
|
|
// surface no longer imported
|
|
connect(imported, &XdgImportedV2Interface::destroyed, this, [this, imported]() {
|
|
unlink(imported, nullptr);
|
|
});
|
|
}
|
|
|
|
void XdgImporterV2Interface::link(XdgImportedV2Interface *parent, SurfaceInterface *child)
|
|
{
|
|
// remove any previous association
|
|
auto it = m_children.find(parent);
|
|
if (it != m_children.end()) {
|
|
m_parents.remove(*it);
|
|
m_children.erase(it);
|
|
}
|
|
|
|
m_parents[child] = parent;
|
|
m_children[parent] = child;
|
|
|
|
Q_EMIT m_foreign->transientChanged(child, parent->surface());
|
|
}
|
|
|
|
void XdgImporterV2Interface::unlink(XdgImportedV2Interface *parent, SurfaceInterface *child)
|
|
{
|
|
if (parent) {
|
|
// If the parent endpoint is unlinked, the transientChanged() signal will indicate
|
|
// the orphaned child.
|
|
auto it = m_children.find(parent);
|
|
if (it != m_children.end()) {
|
|
SurfaceInterface *child = *it;
|
|
m_parents.remove(*it);
|
|
m_children.erase(it);
|
|
Q_EMIT m_foreign->transientChanged(child, nullptr);
|
|
}
|
|
} else if (child) {
|
|
// If the child endpoint is unlinked, the transientChanged() signal will indicate
|
|
// what parent has lost a child.
|
|
auto it = m_parents.find(child);
|
|
if (it != m_parents.end()) {
|
|
XdgImportedV2Interface *parent = *it;
|
|
m_children.remove(*it);
|
|
m_parents.erase(it);
|
|
Q_EMIT m_foreign->transientChanged(nullptr, parent->surface());
|
|
}
|
|
}
|
|
}
|
|
|
|
XdgExportedV2Interface::XdgExportedV2Interface(SurfaceInterface *surface, wl_resource *resource)
|
|
: QtWaylandServer::zxdg_exported_v2(resource)
|
|
, m_surface(surface)
|
|
{
|
|
connect(surface, &QObject::destroyed, this, &XdgExportedV2Interface::handleSurfaceDestroyed);
|
|
}
|
|
|
|
SurfaceInterface *XdgExportedV2Interface::surface()
|
|
{
|
|
return m_surface;
|
|
}
|
|
|
|
void XdgExportedV2Interface::zxdg_exported_v2_destroy(Resource *resource)
|
|
{
|
|
wl_resource_destroy(resource->handle);
|
|
}
|
|
|
|
void XdgExportedV2Interface::zxdg_exported_v2_destroy_resource(Resource *resource)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
void XdgExportedV2Interface::handleSurfaceDestroyed()
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
XdgDummyImportedV2Interface::XdgDummyImportedV2Interface(wl_resource *resource)
|
|
: QtWaylandServer::zxdg_imported_v2(resource)
|
|
{
|
|
}
|
|
|
|
void XdgDummyImportedV2Interface::zxdg_imported_v2_destroy(Resource *resource)
|
|
{
|
|
wl_resource_destroy(resource->handle);
|
|
}
|
|
|
|
void XdgDummyImportedV2Interface::zxdg_imported_v2_destroy_resource(Resource *resource)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
XdgImportedV2Interface::XdgImportedV2Interface(XdgExportedV2Interface *exported, wl_resource *resource)
|
|
: QtWaylandServer::zxdg_imported_v2(resource)
|
|
, m_exported(exported)
|
|
{
|
|
connect(exported, &QObject::destroyed, this, &XdgImportedV2Interface::handleExportedDestroyed);
|
|
}
|
|
|
|
SurfaceInterface *XdgImportedV2Interface::child() const
|
|
{
|
|
return m_child;
|
|
}
|
|
|
|
SurfaceInterface *XdgImportedV2Interface::surface() const
|
|
{
|
|
return m_exported->surface();
|
|
}
|
|
|
|
void XdgImportedV2Interface::zxdg_imported_v2_set_parent_of(Resource *resource, wl_resource *surface)
|
|
{
|
|
SurfaceInterface *surf = SurfaceInterface::get(surface);
|
|
|
|
if (!surf) {
|
|
return;
|
|
}
|
|
|
|
m_child = surf;
|
|
Q_EMIT childChanged(surf);
|
|
}
|
|
|
|
void XdgImportedV2Interface::zxdg_imported_v2_destroy(Resource *resource)
|
|
{
|
|
wl_resource_destroy(resource->handle);
|
|
}
|
|
|
|
void XdgImportedV2Interface::zxdg_imported_v2_destroy_resource(Resource *resource)
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
void XdgImportedV2Interface::handleExportedDestroyed()
|
|
{
|
|
send_destroyed();
|
|
delete this;
|
|
}
|
|
|
|
}
|