File indexing completed on 2024-05-19 16:35:32
0001 /* 0002 SPDX-FileCopyrightText: 2017 Marco Martin <notmart@gmail.com> 0003 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "display.h" 0009 #include "xdgforeign_v2_interface_p.h" 0010 0011 #include <QUuid> 0012 0013 namespace KWaylandServer 0014 { 0015 static const quint32 s_exporterVersion = 1; 0016 static const quint32 s_importerVersion = 1; 0017 0018 XdgForeignV2InterfacePrivate::XdgForeignV2InterfacePrivate(Display *display, XdgForeignV2Interface *_q) 0019 : q(_q) 0020 , exporter(new XdgExporterV2Interface(display, _q)) 0021 , importer(new XdgImporterV2Interface(display, _q)) 0022 { 0023 } 0024 0025 XdgForeignV2Interface::XdgForeignV2Interface(Display *display, QObject *parent) 0026 : QObject(parent) 0027 , d(new XdgForeignV2InterfacePrivate(display, this)) 0028 { 0029 } 0030 0031 XdgForeignV2Interface::~XdgForeignV2Interface() 0032 { 0033 } 0034 0035 SurfaceInterface *XdgForeignV2Interface::transientFor(SurfaceInterface *surface) 0036 { 0037 return d->importer->transientFor(surface); 0038 } 0039 0040 XdgExporterV2Interface::XdgExporterV2Interface(Display *display, XdgForeignV2Interface *foreign) 0041 : QObject(foreign) 0042 , QtWaylandServer::zxdg_exporter_v2(*display, s_exporterVersion) 0043 , m_foreign(foreign) 0044 { 0045 } 0046 0047 XdgExportedV2Interface *XdgExporterV2Interface::exportedSurface(const QString &handle) 0048 { 0049 return m_exportedSurfaces.value(handle); 0050 } 0051 0052 void XdgExporterV2Interface::zxdg_exporter_v2_destroy(Resource *resource) 0053 { 0054 wl_resource_destroy(resource->handle); 0055 } 0056 0057 void XdgExporterV2Interface::zxdg_exporter_v2_export_toplevel(Resource *resource, uint32_t id, wl_resource *surface_resource) 0058 { 0059 SurfaceInterface *surface = SurfaceInterface::get(surface_resource); 0060 if (!surface) { 0061 wl_resource_post_error(resource->handle, 0, "Invalid surface"); 0062 return; 0063 } 0064 0065 wl_resource *exportedResource = wl_resource_create(resource->client(), &zxdg_exported_v2_interface, resource->version(), id); 0066 if (!exportedResource) { 0067 wl_client_post_no_memory(resource->client()); 0068 return; 0069 } 0070 0071 XdgExportedV2Interface *exported = new XdgExportedV2Interface(surface, exportedResource); 0072 const QString handle = QUuid::createUuid().toString(); 0073 0074 // a surface not exported anymore 0075 connect(exported, &XdgExportedV2Interface::destroyed, this, [this, handle]() { 0076 m_exportedSurfaces.remove(handle); 0077 }); 0078 0079 m_exportedSurfaces[handle] = exported; 0080 exported->send_handle(handle); 0081 } 0082 0083 XdgImporterV2Interface::XdgImporterV2Interface(Display *display, XdgForeignV2Interface *foreign) 0084 : QObject(foreign) 0085 , QtWaylandServer::zxdg_importer_v2(*display, s_importerVersion) 0086 , m_foreign(foreign) 0087 { 0088 } 0089 0090 SurfaceInterface *XdgImporterV2Interface::transientFor(SurfaceInterface *surface) 0091 { 0092 auto it = m_parents.constFind(surface); 0093 if (it == m_parents.constEnd()) { 0094 return nullptr; 0095 } 0096 return (*it)->surface(); 0097 } 0098 0099 void XdgImporterV2Interface::zxdg_importer_v2_destroy(Resource *resource) 0100 { 0101 wl_resource_destroy(resource->handle); 0102 } 0103 0104 void XdgImporterV2Interface::zxdg_importer_v2_import_toplevel(Resource *resource, uint32_t id, const QString &handle) 0105 { 0106 wl_resource *importedResource = wl_resource_create(resource->client(), &zxdg_imported_v2_interface, resource->version(), id); 0107 if (!importedResource) { 0108 wl_client_post_no_memory(resource->client()); 0109 return; 0110 } 0111 0112 // If there is no exported surface with the specified handle, we must still create an 0113 // inert xdg_imported object and send the destroyed event right afterwards. 0114 XdgExportedV2Interface *exported = m_foreign->d->exporter->exportedSurface(handle); 0115 if (!exported) { 0116 auto imported = new XdgDummyImportedV2Interface(importedResource); 0117 imported->send_destroyed(); 0118 return; 0119 } 0120 0121 XdgImportedV2Interface *imported = new XdgImportedV2Interface(exported, importedResource); 0122 0123 connect(imported, &XdgImportedV2Interface::childChanged, this, [this, imported](SurfaceInterface *child) { 0124 link(imported, child); 0125 0126 // child surface destroyed 0127 connect(child, &QObject::destroyed, this, [this, child]() { 0128 unlink(nullptr, child); 0129 }); 0130 }); 0131 0132 // surface no longer imported 0133 connect(imported, &XdgImportedV2Interface::destroyed, this, [this, imported]() { 0134 unlink(imported, nullptr); 0135 }); 0136 } 0137 0138 void XdgImporterV2Interface::link(XdgImportedV2Interface *parent, SurfaceInterface *child) 0139 { 0140 // remove any previous association 0141 auto it = m_children.find(parent); 0142 if (it != m_children.end()) { 0143 m_parents.remove(*it); 0144 m_children.erase(it); 0145 } 0146 0147 m_parents[child] = parent; 0148 m_children[parent] = child; 0149 0150 Q_EMIT m_foreign->transientChanged(child, parent->surface()); 0151 } 0152 0153 void XdgImporterV2Interface::unlink(XdgImportedV2Interface *parent, SurfaceInterface *child) 0154 { 0155 if (parent) { 0156 // If the parent endpoint is unlinked, the transientChanged() signal will indicate 0157 // the orphaned child. 0158 auto it = m_children.find(parent); 0159 if (it != m_children.end()) { 0160 SurfaceInterface *child = *it; 0161 m_parents.remove(*it); 0162 m_children.erase(it); 0163 Q_EMIT m_foreign->transientChanged(child, nullptr); 0164 } 0165 } else if (child) { 0166 // If the child endpoint is unlinked, the transientChanged() signal will indicate 0167 // what parent has lost a child. 0168 auto it = m_parents.find(child); 0169 if (it != m_parents.end()) { 0170 XdgImportedV2Interface *parent = *it; 0171 m_children.remove(*it); 0172 m_parents.erase(it); 0173 Q_EMIT m_foreign->transientChanged(nullptr, parent->surface()); 0174 } 0175 } 0176 } 0177 0178 XdgExportedV2Interface::XdgExportedV2Interface(SurfaceInterface *surface, wl_resource *resource) 0179 : QtWaylandServer::zxdg_exported_v2(resource) 0180 , m_surface(surface) 0181 { 0182 connect(surface, &QObject::destroyed, this, &XdgExportedV2Interface::handleSurfaceDestroyed); 0183 } 0184 0185 SurfaceInterface *XdgExportedV2Interface::surface() 0186 { 0187 return m_surface; 0188 } 0189 0190 void XdgExportedV2Interface::zxdg_exported_v2_destroy(Resource *resource) 0191 { 0192 wl_resource_destroy(resource->handle); 0193 } 0194 0195 void XdgExportedV2Interface::zxdg_exported_v2_destroy_resource(Resource *resource) 0196 { 0197 delete this; 0198 } 0199 0200 void XdgExportedV2Interface::handleSurfaceDestroyed() 0201 { 0202 delete this; 0203 } 0204 0205 XdgDummyImportedV2Interface::XdgDummyImportedV2Interface(wl_resource *resource) 0206 : QtWaylandServer::zxdg_imported_v2(resource) 0207 { 0208 } 0209 0210 void XdgDummyImportedV2Interface::zxdg_imported_v2_destroy(Resource *resource) 0211 { 0212 wl_resource_destroy(resource->handle); 0213 } 0214 0215 void XdgDummyImportedV2Interface::zxdg_imported_v2_destroy_resource(Resource *resource) 0216 { 0217 delete this; 0218 } 0219 0220 XdgImportedV2Interface::XdgImportedV2Interface(XdgExportedV2Interface *exported, wl_resource *resource) 0221 : QtWaylandServer::zxdg_imported_v2(resource) 0222 , m_exported(exported) 0223 { 0224 connect(exported, &QObject::destroyed, this, &XdgImportedV2Interface::handleExportedDestroyed); 0225 } 0226 0227 SurfaceInterface *XdgImportedV2Interface::child() const 0228 { 0229 return m_child; 0230 } 0231 0232 SurfaceInterface *XdgImportedV2Interface::surface() const 0233 { 0234 return m_exported->surface(); 0235 } 0236 0237 void XdgImportedV2Interface::zxdg_imported_v2_set_parent_of(Resource *resource, wl_resource *surface) 0238 { 0239 SurfaceInterface *surf = SurfaceInterface::get(surface); 0240 0241 if (!surf) { 0242 return; 0243 } 0244 0245 m_child = surf; 0246 Q_EMIT childChanged(surf); 0247 } 0248 0249 void XdgImportedV2Interface::zxdg_imported_v2_destroy(Resource *resource) 0250 { 0251 wl_resource_destroy(resource->handle); 0252 } 0253 0254 void XdgImportedV2Interface::zxdg_imported_v2_destroy_resource(Resource *resource) 0255 { 0256 delete this; 0257 } 0258 0259 void XdgImportedV2Interface::handleExportedDestroyed() 0260 { 0261 send_destroyed(); 0262 delete this; 0263 } 0264 0265 }