Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwaylandcompositorextension.cpp
Go to the documentation of this file.
1// Copyright (C) 2021 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
7
8#include <QtCore/QCoreApplication>
9#include <QtCore/QDebug>
10
11#include <wayland-server-core.h>
12
13QT_BEGIN_NAMESPACE
14
15/*!
16 * \class QWaylandCompositorExtensionTemplate
17 * \inmodule QtWaylandCompositor
18 * \since 5.8
19 * \brief QWaylandCompositorExtensionTemplate is a convenience class for subclassing
20 * QWaylandCompositorExtension.
21 *
22 * QWaylandCompositorExtensionTemplate is a template class which inherits
23 * QWaylandCompositorExtension and is convenience for building custom Wayland extensions with Qt.
24 *
25 * It provides the connection between Qt Wayland Compositor and the class generated by
26 * \c qtwaylandscanner, based on the XML description of the extension protocol.
27 *
28 * It provides two specific pieces of convenience:
29 * \list
30 * \li A reimplementation of \l{QWaylandCompositorExtension::extensionInterface()} which returns
31 * the \c wl_interface pointer for the qtwaylandscanner-generated base class.
32 * \li A static \l{findIn()} function which searches for an instance of the extension in a
33 * provided container, and returns this if it is found.
34 * \endlist
35 *
36 * Typically, a new extension will dual-inherit QWaylandCompositorExtensionTemplate and the class
37 * generated by \c qtwaylandscanner.
38 *
39 * QWaylandCompositorExtensionTemplate should be parameterized with \a T being the subclass itself:
40 * \code
41 * class MyExtension
42 * : public QWaylandCompositorExtensionTemplate<MyExtension>
43 * , QtWaylandServer::my_extension
44 * \endcode
45 *
46 * In this example, \c MyExtension is an implementation of the generated interface \c my_extension.
47 *
48 * \sa {Custom Shell}
49 */
50
51/*!
52 * \fn template <typename T> T *QWaylandCompositorExtensionTemplate<T>::findIn(QWaylandObject *container)
53 *
54 * If any instance of the interface has been registered with \a container, this is returned.
55 * Otherwise null is returned. The look-up is based on the generated \c interfaceName() which
56 * matches the interface name in the protocol description.
57 */
58
59/*!
60 * \class QWaylandCompositorExtension
61 * \inmodule QtWaylandCompositor
62 * \since 5.8
63 * \brief QWaylandCompositorExtension is the base class for compositor extensions.
64 *
65 * QWaylandCompositorExtension is the base class for implementing Wayland extensions on the
66 * compositor-side of the connection. If no other extension container is explicitly set, it will
67 * automatically add itself to its parent object, granted that this inherits from QWaylandObject.
68 *
69 * For example, for registering global extensions, you can inherit from QWaylandCompositorExtension
70 * and pass the QWaylandCompositor object as extension container.
71 *
72 * \sa QWaylandCompositorExtensionTemplate, {Custom Shell}
73 */
74
75/*!
76 * Creates a QWaylandCompositorExtension with no container.
77 *
78 * \sa setExtensionContainer()
79 */
80QWaylandCompositorExtension::QWaylandCompositorExtension()
81 : QWaylandObject(*new QWaylandCompositorExtensionPrivate())
82{
83}
84
85/*!
86 * Creates a QWaylandCompositorExtension and adds it to the extension \a container. The \a container
87 * does not become the parent of the QWaylandCompositorExtension.
88 *
89 * The extension adds itself to \a container later, when \l{initialize()} is called. For this to
90 * happen automatically, an event loop must be running in the current thread.
91 *
92 * The QWaylandCompositorExtension will remove itself again when it is destroyed.
93 */
94QWaylandCompositorExtension::QWaylandCompositorExtension(QWaylandObject *container)
95 : QWaylandObject(*new QWaylandCompositorExtensionPrivate())
96{
97 d_func()->extension_container = container;
98 QCoreApplication::postEvent(this, new QEvent(QEvent::Polish));
99}
100
101QWaylandCompositorExtension::QWaylandCompositorExtension(QWaylandCompositorExtensionPrivate &dd)
102 : QWaylandObject(dd)
103{
104}
105
106QWaylandCompositorExtension::QWaylandCompositorExtension(QWaylandObject *container, QWaylandCompositorExtensionPrivate &dd)
107 : QWaylandObject(dd)
108{
109 d_func()->extension_container = container;
110 QCoreApplication::postEvent(this, new QEvent(QEvent::Polish));
111}
112
113QWaylandCompositorExtension::~QWaylandCompositorExtension()
114{
115 Q_D(QWaylandCompositorExtension);
116 if (d->extension_container)
117 d->extension_container->removeExtension(this);
118}
119
120/*!
121 * \fn const wl_interface *QWaylandCompositorExtension::extensionInterface() const
122 *
123 * A pure virtual function which should be reimplemented to return the \c wl_interface which
124 * corresponds to this QWaylandCompositorExtension.
125 */
126
127/*!
128 * \return the extension container for this QWaylandCompositorExtension or null if none has been
129 * set.
130 */
131QWaylandObject *QWaylandCompositorExtension::extensionContainer() const
132{
133 Q_D(const QWaylandCompositorExtension);
134 return d->extension_container;
135}
136
137/*!
138 * Sets the extension container for this QWaylandCompositorExtension to \a container. This must be
139 * called before \l{initialize()} and cannot be changed once the QWaylandCompositorExtension has
140 * been initialized.
141 */
142void QWaylandCompositorExtension::setExtensionContainer(QWaylandObject *container)
143{
144 Q_D(QWaylandCompositorExtension);
145 d->extension_container = container;
146}
147
148/*!
149 * Initializes the QWaylandCompositorExtension. The default implementation adopts the parent object
150 * as extension container if none has been set, and if the parent inherits from QWaylandObject. The
151 * default implementation also adds the QWaylandCompositorExtension to the list of extensions
152 * managed by the extension container.
153 *
154 * Override this function in subclasses to provide custom initialization code.
155 */
156void QWaylandCompositorExtension::initialize()
157{
158 Q_D(QWaylandCompositorExtension);
159 if (d->initialized) {
160 qWarning() << "QWaylandCompositorExtension:" << extensionInterface()->name << "is already initialized";
161 return;
162 }
163
164 if (!d->extension_container && parent()) {
165 QWaylandObject *parentObj = qobject_cast<QWaylandObject*>(parent());
166 if (parentObj)
167 setExtensionContainer(parentObj);
168 }
169
170 if (!d->extension_container) {
171 qWarning() << "QWaylandCompositorExtension:" << extensionInterface()->name << "requests to initialize with no extension container set";
172 return;
173 }
174
175 d->extension_container->addExtension(this);
176 d->initialized = true;
177}
178
179bool QWaylandCompositorExtension::isInitialized() const
180{
181 Q_D(const QWaylandCompositorExtension);
182 return d->initialized;
183}
184
185bool QWaylandCompositorExtension::event(QEvent *event)
186{
187 switch(event->type()) {
188 case QEvent::Polish:
189 if (!isInitialized())
190 initialize();
191 break;
192 default:
193 break;
194 }
195 return QWaylandObject::event(event);
196}
197
198/*!
199 * \class QWaylandObject
200 * \inmodule QtWaylandCompositor
201 * \since 5.8
202 * \brief QWaylandObject is the base class for objects that can contain Wayland extensions.
203 *
204 * The QWaylandObject encapsulate extension container functionality. Any QWaylandObject object
205 * will automatically be an extension container and QWaylandCompositorExtension object which is
206 * a child of this will automatically add itself to its extension list, and remove itself when
207 * the extension object is destroyed.
208 */
209
210/*!
211 * Creates a QWaylandObject as a child of \a parent.
212 */
213QWaylandObject::QWaylandObject(QObject *parent)
214 :QObject(parent)
215{
216}
217
218QWaylandObject::QWaylandObject(QObjectPrivate &d, QObject *parent)
219 :QObject(d, parent)
220{
221}
222
223
224QWaylandObject::~QWaylandObject()
225{
226 for (QWaylandCompositorExtension *extension : std::as_const(extension_vector))
227 QWaylandCompositorExtensionPrivate::get(extension)->extension_container = nullptr;
228}
229
230/*!
231 * Returns the compositor extension which matches \a name if one has been registered with the
232 * QWaylandObject. If no extension matching the name has been registered, this function returns
233 * null.
234 */
235QWaylandCompositorExtension *QWaylandObject::extension(const QByteArray &name)
236{
237 for (int i = 0; i < extension_vector.size(); i++) {
238 if (extension_vector.at(i)->extensionInterface()->name == name)
239 return extension_vector.at(i);
240 }
241 return nullptr;
242}
243
244/*!
245 * Returns the compositor extension which matches \a interface if one has been registered with the
246 * QWaylandObject. If no extension matching the interface has been registered, this function
247 * returns null.
248 */
249QWaylandCompositorExtension *QWaylandObject::extension(const wl_interface *interface)
250{
251 for (int i = 0; i < extension_vector.size(); i++) {
252 if (extension_vector.at(i)->extensionInterface() == interface)
253 return extension_vector.at(i);
254 }
255 return nullptr;
256}
257
258/*!
259 * Returns the list of compositor extensions that have been registered with this QWaylandObject.
260 */
261QList<QWaylandCompositorExtension *> QWaylandObject::extensions() const
262{
263 return extension_vector;
264}
265
266/*!
267 * Registers \a extension with this QWaylandObject.
268 */
269void QWaylandObject::addExtension(QWaylandCompositorExtension *extension)
270{
271 Q_ASSERT(!extension_vector.contains(extension));
272 extension_vector.append(extension);
273}
274
275/*!
276 * Removes \a extension from the list of registered extensions in this QWaylandObject, if it has
277 * previously been registered using \l{addExtension()}.
278 */
279void QWaylandObject::removeExtension(QWaylandCompositorExtension *extension)
280{
281 if (!extension->isInitialized())
282 return;
283 Q_ASSERT(extension_vector.contains(extension));
284 extension_vector.removeOne(extension);
285}
286
287QT_END_NAMESPACE
288
289#include "moc_qwaylandcompositorextension.cpp"