KWin
Loading...
Searching...
No Matches
xdgforeign_v2.cpp
Go to the documentation of this file.
1/*
2 SPDX-FileCopyrightText: 2017 Marco Martin <notmart@gmail.com>
3 SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <vlad.zahorodnii@kde.org>
4 SPDX-FileCopyrightText: 2023 Kai Uwe Broulik <kde@broulik.de>
5
6 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
7*/
8
9#include "display.h"
10#include "xdgforeign_v2_p.h"
11
12#include <QUuid>
13
14namespace KWin
15{
16static const quint32 s_exporterVersion = 1;
17static const quint32 s_importerVersion = 1;
18
20 : QObject()
21 , m_handle(QUuid::createUuid().toString(QUuid::WithoutBraces))
22 , m_surface(surface)
23{
24 connect(m_surface, &QObject::destroyed, this, &XdgExportedSurface::handleSurfaceDestroyed);
25}
26
28{
29 return m_handle;
30}
31
33{
34 return m_surface;
35}
36
37void XdgExportedSurface::handleSurfaceDestroyed()
38{
39 delete this;
40}
41
43 : q(_q)
44 , exporter(new XdgExporterV2Interface(display, _q))
45 , importer(new XdgImporterV2Interface(display, _q))
46{
47}
48
50 : QObject(parent)
51 , d(new XdgForeignV2InterfacePrivate(display, this))
52{
53}
54
58
60{
61 return d->importer->transientFor(surface);
62}
63
65{
66 return d->exporter->exportSurface(surface);
67}
68
70 : QObject(foreign)
71 , QtWaylandServer::zxdg_exporter_v2(*display, s_exporterVersion)
72{
73}
74
76{
77 return m_exportedSurfaces.value(handle);
78}
79
81{
82 auto *exported = new XdgExportedSurface(surface);
83 addExported(exported);
84 return exported;
85}
86
87void XdgExporterV2Interface::addExported(XdgExportedSurface *exported)
88{
89 const QString handle = exported->handle();
90 connect(exported, &XdgExportedSurface::destroyed, this, [this, handle] {
91 m_exportedSurfaces.remove(handle);
92 });
93 m_exportedSurfaces[handle] = exported;
94}
95
97{
98 wl_resource_destroy(resource->handle);
99}
100
101void XdgExporterV2Interface::zxdg_exporter_v2_export_toplevel(Resource *resource, uint32_t id, wl_resource *surface_resource)
102{
103 SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
104 if (!surface) {
105 wl_resource_post_error(resource->handle, 0, "Invalid surface");
106 return;
107 }
108
109 wl_resource *exportedResource = wl_resource_create(resource->client(), &zxdg_exported_v2_interface, resource->version(), id);
110 if (!exportedResource) {
111 wl_client_post_no_memory(resource->client());
112 return;
113 }
114
115 XdgExportedV2Interface *exported = new XdgExportedV2Interface(surface, exportedResource);
116 addExported(exported);
117
118 exported->send_handle(exported->handle());
119}
120
122 : QObject(foreign)
123 , QtWaylandServer::zxdg_importer_v2(*display, s_importerVersion)
124 , m_foreign(foreign)
125{
126}
127
129{
130 auto it = m_parents.constFind(surface);
131 if (it == m_parents.constEnd()) {
132 return nullptr;
133 }
134 return (*it)->surface();
135}
136
138{
139 wl_resource_destroy(resource->handle);
140}
141
142void XdgImporterV2Interface::zxdg_importer_v2_import_toplevel(Resource *resource, uint32_t id, const QString &handle)
143{
144 wl_resource *importedResource = wl_resource_create(resource->client(), &zxdg_imported_v2_interface, resource->version(), id);
145 if (!importedResource) {
146 wl_client_post_no_memory(resource->client());
147 return;
148 }
149
150 // If there is no exported surface with the specified handle, we must still create an
151 // inert xdg_imported object and send the destroyed event right afterwards.
152 XdgExportedSurface *exported = m_foreign->d->exporter->exportedSurface(handle);
153 if (!exported) {
154 auto imported = new XdgDummyImportedV2Interface(importedResource);
155 imported->send_destroyed();
156 return;
157 }
158
159 XdgImportedV2Interface *imported = new XdgImportedV2Interface(exported, importedResource);
160
161 connect(imported, &XdgImportedV2Interface::childChanged, this, [this, imported](SurfaceInterface *child) {
162 link(imported, child);
163
164 // child surface destroyed
165 connect(child, &QObject::destroyed, this, [this, child]() {
166 unlink(nullptr, child);
167 });
168 });
169
170 // surface no longer imported
171 connect(imported, &XdgImportedV2Interface::destroyed, this, [this, imported]() {
172 unlink(imported, nullptr);
173 });
174}
175
177{
178 // remove any previous association
179 auto it = m_children.find(parent);
180 if (it != m_children.end()) {
181 m_parents.remove(*it);
182 m_children.erase(it);
183 }
184
185 m_parents[child] = parent;
186 m_children[parent] = child;
187
188 Q_EMIT m_foreign->transientChanged(child, parent->surface());
189}
190
192{
193 if (parent) {
194 // If the parent endpoint is unlinked, the transientChanged() signal will indicate
195 // the orphaned child.
196 auto it = m_children.find(parent);
197 if (it != m_children.end()) {
198 SurfaceInterface *child = *it;
199 m_parents.remove(*it);
200 m_children.erase(it);
201 Q_EMIT m_foreign->transientChanged(child, nullptr);
202 }
203 } else if (child) {
204 // If the child endpoint is unlinked, the transientChanged() signal will indicate
205 // what parent has lost a child.
206 auto it = m_parents.find(child);
207 if (it != m_parents.end()) {
208 XdgImportedV2Interface *parent = *it;
209 m_children.remove(*it);
210 m_parents.erase(it);
211 Q_EMIT m_foreign->transientChanged(nullptr, parent->surface());
212 }
213 }
214}
215
217 : XdgExportedSurface(surface)
218 , QtWaylandServer::zxdg_exported_v2(resource)
219{
220}
221
223{
224 wl_resource_destroy(resource->handle);
225}
226
228{
229 delete this;
230}
231
233 : QtWaylandServer::zxdg_imported_v2(resource)
234{
235}
236
238{
239 wl_resource_destroy(resource->handle);
240}
241
243{
244 delete this;
245}
246
248 : QtWaylandServer::zxdg_imported_v2(resource)
249 , m_exported(exported)
250{
251 connect(exported, &XdgExportedSurface::destroyed, this, &XdgImportedV2Interface::handleExportedDestroyed);
252}
253
255{
256 return m_child;
257}
258
260{
261 return m_exported->surface();
262}
263
264void XdgImportedV2Interface::zxdg_imported_v2_set_parent_of(Resource *resource, wl_resource *surface)
265{
267
268 if (!surf) {
269 return;
270 }
271
272 m_child = surf;
273 Q_EMIT childChanged(surf);
274}
275
277{
278 wl_resource_destroy(resource->handle);
279}
280
282{
283 delete this;
284}
285
286void XdgImportedV2Interface::handleExportedDestroyed()
287{
288 send_destroyed();
289 delete this;
290}
291
292}
293
294#include "moc_xdgforeign_v2.cpp"
295#include "moc_xdgforeign_v2_p.cpp"
Class holding the Wayland server display loop.
Definition display.h:34
Resource representing a wl_surface.
Definition surface.h:80
static SurfaceInterface * get(wl_resource *native)
Definition surface.cpp:819
void zxdg_imported_v2_destroy(Resource *resource) override
void zxdg_imported_v2_destroy_resource(Resource *resource) override
XdgDummyImportedV2Interface(wl_resource *resource)
XdgExportedSurface(SurfaceInterface *surface)
SurfaceInterface * surface() const
XdgExportedV2Interface(SurfaceInterface *surface, wl_resource *resource)
void zxdg_exported_v2_destroy_resource(Resource *resource) override
void zxdg_exported_v2_destroy(Resource *resource) override
void zxdg_exporter_v2_destroy(Resource *resource) override
XdgExportedSurface * exportSurface(SurfaceInterface *surface)
XdgExporterV2Interface(Display *display, XdgForeignV2Interface *foreign)
void zxdg_exporter_v2_export_toplevel(Resource *resource, uint32_t id, wl_resource *surface) override
XdgExportedSurface * exportedSurface(const QString &handle) const
void transientChanged(KWin::SurfaceInterface *child, KWin::SurfaceInterface *parent)
XdgExportedSurface * exportSurface(SurfaceInterface *surface)
SurfaceInterface * transientFor(SurfaceInterface *surface)
XdgForeignV2Interface(Display *display, QObject *parent=nullptr)
XdgForeignV2InterfacePrivate(Display *display, XdgForeignV2Interface *q)
void zxdg_imported_v2_destroy(Resource *resource) override
SurfaceInterface * surface() const
void zxdg_imported_v2_destroy_resource(Resource *resource) override
void zxdg_imported_v2_set_parent_of(Resource *resource, wl_resource *surface) override
void childChanged(KWin::SurfaceInterface *child)
SurfaceInterface * child() const
XdgImportedV2Interface(XdgExportedSurface *exported, wl_resource *resource)
void zxdg_importer_v2_import_toplevel(Resource *resource, uint32_t id, const QString &handle) override
void zxdg_importer_v2_destroy(Resource *resource) override
XdgImporterV2Interface(Display *display, XdgForeignV2Interface *foreign)
void link(XdgImportedV2Interface *parent, SurfaceInterface *child)
void unlink(XdgImportedV2Interface *parent, SurfaceInterface *child)
SurfaceInterface * transientFor(SurfaceInterface *surface)