KWaylandServer

xdgforeign_v2_interface.cpp
1 /*
2  SPDX-FileCopyrightText: 2017 Marco Martin <[email protected]>
3  SPDX-FileCopyrightText: 2021 Vlad Zahorodnii <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7 
8 #include "display.h"
9 #include "xdgforeign_v2_interface_p.h"
10 
11 #include <QUuid>
12 
13 namespace KWaylandServer
14 {
15 static const quint32 s_exporterVersion = 1;
16 static const quint32 s_importerVersion = 1;
17 
18 XdgForeignV2InterfacePrivate::XdgForeignV2InterfacePrivate(Display *display, XdgForeignV2Interface *_q)
19  : q(_q)
20  , exporter(new XdgExporterV2Interface(display, _q))
21  , importer(new XdgImporterV2Interface(display, _q))
22 {
23 }
24 
25 XdgForeignV2Interface::XdgForeignV2Interface(Display *display, QObject *parent)
26  : QObject(parent)
27  , d(new XdgForeignV2InterfacePrivate(display, this))
28 {
29 }
30 
31 XdgForeignV2Interface::~XdgForeignV2Interface()
32 {
33 }
34 
36 {
37  return d->importer->transientFor(surface);
38 }
39 
40 XdgExporterV2Interface::XdgExporterV2Interface(Display *display, XdgForeignV2Interface *foreign)
41  : QObject(foreign)
42  , QtWaylandServer::zxdg_exporter_v2(*display, s_exporterVersion)
43  , m_foreign(foreign)
44 {
45 }
46 
47 XdgExportedV2Interface *XdgExporterV2Interface::exportedSurface(const QString &handle)
48 {
49  return m_exportedSurfaces.value(handle);
50 }
51 
52 void XdgExporterV2Interface::zxdg_exporter_v2_destroy(Resource *resource)
53 {
54  wl_resource_destroy(resource->handle);
55 }
56 
57 void XdgExporterV2Interface::zxdg_exporter_v2_export_toplevel(Resource *resource, uint32_t id, wl_resource *surface_resource)
58 {
59  SurfaceInterface *surface = SurfaceInterface::get(surface_resource);
60  if (!surface) {
61  wl_resource_post_error(resource->handle, 0, "Invalid surface");
62  return;
63  }
64 
65  wl_resource *exportedResource = wl_resource_create(resource->client(), &zxdg_exported_v2_interface, resource->version(), id);
66  if (!exportedResource) {
67  wl_client_post_no_memory(resource->client());
68  return;
69  }
70 
71  XdgExportedV2Interface *exported = new XdgExportedV2Interface(surface, exportedResource);
72  const QString handle = QUuid::createUuid().toString();
73 
74  // a surface not exported anymore
75  connect(exported, &XdgExportedV2Interface::destroyed, this, [this, handle]() {
76  m_exportedSurfaces.remove(handle);
77  });
78 
79  m_exportedSurfaces[handle] = exported;
80  exported->send_handle(handle);
81 }
82 
83 XdgImporterV2Interface::XdgImporterV2Interface(Display *display, XdgForeignV2Interface *foreign)
84  : QObject(foreign)
85  , QtWaylandServer::zxdg_importer_v2(*display, s_importerVersion)
86  , m_foreign(foreign)
87 {
88 }
89 
90 SurfaceInterface *XdgImporterV2Interface::transientFor(SurfaceInterface *surface)
91 {
92  auto it = m_parents.constFind(surface);
93  if (it == m_parents.constEnd()) {
94  return nullptr;
95  }
96  return (*it)->surface();
97 }
98 
99 void XdgImporterV2Interface::zxdg_importer_v2_destroy(Resource *resource)
100 {
101  wl_resource_destroy(resource->handle);
102 }
103 
104 void XdgImporterV2Interface::zxdg_importer_v2_import_toplevel(Resource *resource, uint32_t id, const QString &handle)
105 {
106  wl_resource *importedResource = wl_resource_create(resource->client(), &zxdg_imported_v2_interface, resource->version(), id);
107  if (!importedResource) {
108  wl_client_post_no_memory(resource->client());
109  return;
110  }
111 
112  // If there is no exported surface with the specified handle, we must still create an
113  // inert xdg_imported object and send the destroyed event right afterwards.
114  XdgExportedV2Interface *exported = m_foreign->d->exporter->exportedSurface(handle);
115  if (!exported) {
116  auto imported = new XdgDummyImportedV2Interface(importedResource);
117  imported->send_destroyed();
118  return;
119  }
120 
121  XdgImportedV2Interface *imported = new XdgImportedV2Interface(exported, importedResource);
122 
123  connect(imported, &XdgImportedV2Interface::childChanged, this, [this, imported](SurfaceInterface *child) {
124  link(imported, child);
125 
126  // child surface destroyed
127  connect(child, &QObject::destroyed, this, [this, child]() {
128  unlink(nullptr, child);
129  });
130  });
131 
132  // surface no longer imported
133  connect(imported, &XdgImportedV2Interface::destroyed, this, [this, imported]() {
134  unlink(imported, nullptr);
135  });
136 }
137 
138 void XdgImporterV2Interface::link(XdgImportedV2Interface *parent, SurfaceInterface *child)
139 {
140  // remove any previous association
141  auto it = m_children.find(parent);
142  if (it != m_children.end()) {
143  m_parents.remove(*it);
144  m_children.erase(it);
145  }
146 
147  m_parents[child] = parent;
148  m_children[parent] = child;
149 
150  Q_EMIT m_foreign->transientChanged(child, parent->surface());
151 }
152 
153 void XdgImporterV2Interface::unlink(XdgImportedV2Interface *parent, SurfaceInterface *child)
154 {
155  if (parent) {
156  // If the parent endpoint is unlinked, the transientChanged() signal will indicate
157  // the orphaned child.
158  auto it = m_children.find(parent);
159  if (it != m_children.end()) {
160  SurfaceInterface *child = *it;
161  m_parents.remove(*it);
162  m_children.erase(it);
163  Q_EMIT m_foreign->transientChanged(child, nullptr);
164  }
165  } else if (child) {
166  // If the child endpoint is unlinked, the transientChanged() signal will indicate
167  // what parent has lost a child.
168  auto it = m_parents.find(child);
169  if (it != m_parents.end()) {
170  XdgImportedV2Interface *parent = *it;
171  m_children.remove(*it);
172  m_parents.erase(it);
173  Q_EMIT m_foreign->transientChanged(nullptr, parent->surface());
174  }
175  }
176 }
177 
178 XdgExportedV2Interface::XdgExportedV2Interface(SurfaceInterface *surface, wl_resource *resource)
179  : QtWaylandServer::zxdg_exported_v2(resource)
180  , m_surface(surface)
181 {
182  connect(surface, &QObject::destroyed, this, &XdgExportedV2Interface::handleSurfaceDestroyed);
183 }
184 
185 SurfaceInterface *XdgExportedV2Interface::surface()
186 {
187  return m_surface;
188 }
189 
190 void XdgExportedV2Interface::zxdg_exported_v2_destroy(Resource *resource)
191 {
192  wl_resource_destroy(resource->handle);
193 }
194 
195 void XdgExportedV2Interface::zxdg_exported_v2_destroy_resource(Resource *resource)
196 {
197  Q_UNUSED(resource)
198  delete this;
199 }
200 
201 void XdgExportedV2Interface::handleSurfaceDestroyed()
202 {
203  delete this;
204 }
205 
206 XdgDummyImportedV2Interface::XdgDummyImportedV2Interface(wl_resource *resource)
207  : QtWaylandServer::zxdg_imported_v2(resource)
208 {
209 }
210 
211 void XdgDummyImportedV2Interface::zxdg_imported_v2_destroy(Resource *resource)
212 {
213  wl_resource_destroy(resource->handle);
214 }
215 
216 void XdgDummyImportedV2Interface::zxdg_imported_v2_destroy_resource(Resource *resource)
217 {
218  Q_UNUSED(resource)
219  delete this;
220 }
221 
222 XdgImportedV2Interface::XdgImportedV2Interface(XdgExportedV2Interface *exported, wl_resource *resource)
223  : QtWaylandServer::zxdg_imported_v2(resource)
224  , m_exported(exported)
225 {
226  connect(exported, &QObject::destroyed, this, &XdgImportedV2Interface::handleExportedDestroyed);
227 }
228 
229 SurfaceInterface *XdgImportedV2Interface::child() const
230 {
231  return m_child;
232 }
233 
234 SurfaceInterface *XdgImportedV2Interface::surface() const
235 {
236  return m_exported->surface();
237 }
238 
239 void XdgImportedV2Interface::zxdg_imported_v2_set_parent_of(Resource *resource, wl_resource *surface)
240 {
241  Q_UNUSED(resource)
242  SurfaceInterface *surf = SurfaceInterface::get(surface);
243 
244  if (!surf) {
245  return;
246  }
247 
248  m_child = surf;
249  Q_EMIT childChanged(surf);
250 }
251 
252 void XdgImportedV2Interface::zxdg_imported_v2_destroy(Resource *resource)
253 {
254  wl_resource_destroy(resource->handle);
255 }
256 
257 void XdgImportedV2Interface::zxdg_imported_v2_destroy_resource(Resource *resource)
258 {
259  Q_UNUSED(resource)
260  delete this;
261 }
262 
263 void XdgImportedV2Interface::handleExportedDestroyed()
264 {
265  send_destroyed();
266  delete this;
267 }
268 
269 }
SurfaceInterface * transientFor(SurfaceInterface *surface)
If a client did import a surface and set one of its own as child of the imported one, this returns the mapping.
Class holding the Wayland server display loop.
Definition: display.h:47
static SurfaceInterface * get(wl_resource *native)
This class encapsulates the server side logic of the XdgForeign protocol.
QObject(QObject *parent)
Resource representing a wl_surface.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QObject * parent() const const
QString toString() const const
void destroyed(QObject *obj)
QUuid createUuid()
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 23 2021 23:08:28 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.