summaryrefslogtreecommitdiff
path: root/src/compositor
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@qt.io>2021-10-18 16:41:12 +0200
committerPaul Olav Tvete <paul.tvete@qt.io>2021-12-02 09:08:40 +0100
commitd89c8920f3b82dd2098971b5a66c4b9c75da5af0 (patch)
treeb7f35e03485f1aa8725e30870f3066b34d24ea94 /src/compositor
parent0204df32ee7417db3156ef3c70bcf762d7e9fb0a (diff)
downloadqtwayland-d89c8920f3b82dd2098971b5a66c4b9c75da5af0.tar.gz
Introduce new qt-shell and an API for custom shells
Adds a new API for writing custom shell extensions. This API is supported, but semi-public. Binary compatibility is not guaranteed. Also adds qt-shell, a new shell that maps directly to the QWindow API, and provides functionality that Qt provides on other window systems, such as absolute window positions and window activation. This shell is not intended for use on the desktop. This is a squashed commit of a development branch consisting of approximately 60 changes. Contributors: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Paul Olav Tvete <paul.tvete@qt.io> Task-number: QTBUG-94330 Task-number: QTBUG-91542 Change-Id: I419b6bd8179fe03e4da47d328c7ff4b4795b8a91 Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io> Reviewed-by: David Edmundson <davidedmundson@kde.org> Reviewed-by: Paul Olav Tvete <paul.tvete@qt.io>
Diffstat (limited to 'src/compositor')
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem.cpp30
-rw-r--r--src/compositor/compositor_api/qwaylandquickitem_p.h3
-rw-r--r--src/compositor/compositor_api/qwaylandresource.cpp25
-rw-r--r--src/compositor/compositor_api/qwaylandsurface.cpp63
-rw-r--r--src/compositor/doc/qtwaylandcompositor.qdocconf8
-rw-r--r--src/compositor/doc/src/qtwaylandcompositor-shellextensions.qdoc4
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp123
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem.h9
-rw-r--r--src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h5
-rw-r--r--src/compositor/extensions/qwaylandshellsurface.cpp41
-rw-r--r--src/compositor/extensions/qwaylandshellsurface.h2
-rw-r--r--src/compositor/global/qwaylandcompositorextension.cpp136
-rw-r--r--src/compositor/global/qwaylandquickextension.qdoc81
13 files changed, 510 insertions, 20 deletions
diff --git a/src/compositor/compositor_api/qwaylandquickitem.cpp b/src/compositor/compositor_api/qwaylandquickitem.cpp
index 9796b72a..095c6e3b 100644
--- a/src/compositor/compositor_api/qwaylandquickitem.cpp
+++ b/src/compositor/compositor_api/qwaylandquickitem.cpp
@@ -1606,20 +1606,34 @@ void QWaylandQuickItem::setInputEventsEnabled(bool enabled)
void QWaylandQuickItem::lower()
{
- QQuickItem *parent = parentItem();
+ Q_D(QWaylandQuickItem);
+ d->lower();
+}
+
+void QWaylandQuickItemPrivate::lower()
+{
+ Q_Q(QWaylandQuickItem);
+ QQuickItem *parent = q->parentItem();
Q_ASSERT(parent);
- QQuickItem *bottom = parent->childItems().first();
- if (this != bottom)
- stackBefore(bottom);
+ QQuickItem *bottom = parent->childItems().constFirst();
+ if (q != bottom)
+ q->stackBefore(bottom);
}
void QWaylandQuickItem::raise()
{
- QQuickItem *parent = parentItem();
+ Q_D(QWaylandQuickItem);
+ d->raise();
+}
+
+void QWaylandQuickItemPrivate::raise()
+{
+ Q_Q(QWaylandQuickItem);
+ QQuickItem *parent = q->parentItem();
Q_ASSERT(parent);
- QQuickItem *top = parent->childItems().last();
- if (this != top)
- stackAfter(top);
+ QQuickItem *top = parent->childItems().constLast();
+ if (q != top)
+ q->stackAfter(top);
}
void QWaylandQuickItem::sendMouseMoveEvent(const QPointF &position, QWaylandSeat *seat)
diff --git a/src/compositor/compositor_api/qwaylandquickitem_p.h b/src/compositor/compositor_api/qwaylandquickitem_p.h
index 09b9f678..13892204 100644
--- a/src/compositor/compositor_api/qwaylandquickitem_p.h
+++ b/src/compositor/compositor_api/qwaylandquickitem_p.h
@@ -153,6 +153,9 @@ public:
void placeAboveParent();
void placeBelowParent();
+ virtual void raise();
+ virtual void lower();
+
static QMutex *mutex;
QScopedPointer<QWaylandView> view;
diff --git a/src/compositor/compositor_api/qwaylandresource.cpp b/src/compositor/compositor_api/qwaylandresource.cpp
index 585b238c..612589eb 100644
--- a/src/compositor/compositor_api/qwaylandresource.cpp
+++ b/src/compositor/compositor_api/qwaylandresource.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2017 Klarälvdalens Datakonsult AB (KDAB).
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
@@ -31,13 +32,37 @@
QT_BEGIN_NAMESPACE
+/*!
+ * \class QWaylandResource
+ * \inmodule QtWaylandCompositor
+ * \since 5.8
+ * \brief QWaylandResource is a container for a \c wl_resource.
+ *
+ * The QWaylandResource is a simple wrapper around the Wayland type \c wl_resource, and makes it
+ * possible to use wl_resource pointers in Qt Quick APIs.
+ *
+ * \sa {Qt Wayland Compositor Examples - Custom Shell}
+ */
+
+/*!
+ * Constructs an invalid QWaylandResource. The \l{resource()} accessor will return null.
+ */
QWaylandResource::QWaylandResource()
{
}
+/*!
+ * Constructs a QWaylandResource which contains \a resource.
+ */
QWaylandResource::QWaylandResource(wl_resource *resource)
: m_resource(resource)
{
}
+/*!
+ * \fn wl_resource *QWaylandResource::resource() const
+ *
+ * \return the wl_resource pointer held by this QWaylandResource.
+ */
+
QT_END_NAMESPACE
diff --git a/src/compositor/compositor_api/qwaylandsurface.cpp b/src/compositor/compositor_api/qwaylandsurface.cpp
index fc10be11..b07a93e9 100644
--- a/src/compositor/compositor_api/qwaylandsurface.cpp
+++ b/src/compositor/compositor_api/qwaylandsurface.cpp
@@ -362,6 +362,52 @@ QtWayland::ClientBuffer *QWaylandSurfacePrivate::getBuffer(struct ::wl_resource
}
/*!
+ * \class QWaylandSurfaceRole
+ * \inmodule QtWaylandCompositor
+ * \since 5.8
+ * \brief The QWaylandSurfaceRole class represents the role of the surface in context of wl_surface.
+ *
+ * QWaylandSurfaceRole is used to represent the role of a QWaylandSurface. According to the protocol
+ * specification, the role of a surface is permanent once set, and if the same surface is later
+ * reused for a different role, this constitutes a protocol error. Setting the surface to the same
+ * role multiple times is not an error.
+ *
+ * As an example, the QWaylandXdgShell can assign either "popup" or "toplevel" roles to surfaces.
+ * If \c get_toplevel is requested on a surface which has previously received a \c get_popup
+ * request, then the compositor will issue a protocol error.
+ *
+ * Roles are compared by pointer value, so any two objects of QWaylandSurfaceRole will be considered
+ * different roles, regardless of what their \l{name()}{names} are. A typical way of assigning a
+ * role is to have a static QWaylandSurfaceRole object to represent it.
+ *
+ * \code
+ * class MyShellSurfaceSubType
+ * {
+ * static QWaylandSurfaceRole s_role;
+ * // ...
+ * };
+ *
+ * // ...
+ *
+ * surface->setRole(&MyShellSurfaceSubType::s_role, resource->handle, MY_ERROR_CODE);
+ * \endcode
+ */
+
+/*!
+ * \fn QWaylandSurfaceRole::QWaylandSurfaceRole(const QByteArray &name)
+ *
+ * Creates a QWaylandSurfaceRole and assigns it \a name. The name is used in error messages
+ * involving this QWaylandSurfaceRole.
+ */
+
+/*!
+ * \fn const QByteArray QWaylandSurfaceRole::name()
+ *
+ * Returns the name of the QWaylandSurfaceRole. The name is used in error messages involving this
+ * QWaylandSurfaceRole, for example if an attempt is made to change the role of a surface.
+ */
+
+/*!
* \qmltype WaylandSurface
* \instantiates QWaylandSurface
* \inqmlmodule QtWayland.Compositor
@@ -912,10 +958,19 @@ struct wl_resource *QWaylandSurface::resource() const
}
/*!
- * Sets a \a role on the surface. A role defines how a surface will be mapped on screen; without a role
- * a surface is supposed to be hidden. Only one role can be set on a surface, at all times. Although
- * setting the same role many times is allowed, attempting to change the role of a surface will trigger
- * a protocol error to the \a errorResource and send an \a errorCode to the client.
+ * Sets a \a role on the surface. A role defines how a surface will be mapped on screen; without a
+ * role a surface is supposed to be hidden. Once a role is assigned to a surface, this becomes its
+ * permanent role. Any subsequent call to \c setRole() with a different role will trigger a
+ * protocol error to the \a errorResource and send an \a errorCode to the client. Enforcing this
+ * requirement is the main purpose of the surface role.
+ *
+ * The \a role is compared by pointer value. Any two objects of QWaylandSurfaceRole will be
+ * considered different roles, regardless of their names.
+ *
+ * The surface role is set internally by protocol implementations when a surface is adopted for a
+ * specific purpose, for example in a \l{Shell Extensions - Qt Wayland Compositor}{shell extension}.
+ * Unless you are developing extensions which use surfaces in this way, you should not call this
+ * function.
*
* Returns true if a role can be assigned; false otherwise.
*/
diff --git a/src/compositor/doc/qtwaylandcompositor.qdocconf b/src/compositor/doc/qtwaylandcompositor.qdocconf
index 9e49887e..817846d3 100644
--- a/src/compositor/doc/qtwaylandcompositor.qdocconf
+++ b/src/compositor/doc/qtwaylandcompositor.qdocconf
@@ -31,8 +31,12 @@ qhp.QtWaylandCompositor.subprojects.examples.sortPages = true
depends += qtcore qtqml qtquick qtdoc qtquickcontrols qmake qtgui qtqmlmodels qtwidgets qtvirtualkeyboard
exampledirs += ../../../examples/wayland
-headerdirs += ..
-sourcedirs += ..
+headerdirs += \
+ ../ \
+ ../../imports/
+sourcedirs += \
+ ../ \
+ ../../imports/
imagedirs += images
examplesinstallpath = wayland
diff --git a/src/compositor/doc/src/qtwaylandcompositor-shellextensions.qdoc b/src/compositor/doc/src/qtwaylandcompositor-shellextensions.qdoc
index 418df9f9..5feee55d 100644
--- a/src/compositor/doc/src/qtwaylandcompositor-shellextensions.qdoc
+++ b/src/compositor/doc/src/qtwaylandcompositor-shellextensions.qdoc
@@ -57,6 +57,10 @@
applications can run, often with pre-assigned screen real estate. For some more details
on this protocol, see the
\l{Qt Wayland Compositor Examples - IVI Compositor}{IVI Compositor example}.
+ \li \l QtShell is a specialized shell for Qt applications which supports the window management
+ features available in Qt. It may be suitable on a platform where both the compositor and
+ client applications are written with Qt, and where applications are trusted not to abuse
+ features such as manual window positioning and "bring-to-front".
\li \l WlShell is mostly useful for compatibility with third-party applications. This is also
a desktop-style shell, but it has been deprecated and replaced by \l XdgShell.
\endlist
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
index 8928d803..4b481d0d 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.cpp
@@ -313,4 +313,127 @@ void QWaylandQuickShellEventFilter::timerEvent(QTimerEvent *event)
}
}
+static QWaylandQuickShellSurfaceItem *findSurfaceItemFromMoveItem(QQuickItem *moveItem)
+{
+ if (Q_UNLIKELY(!moveItem))
+ return nullptr;
+ if (auto *surf = qobject_cast<QWaylandQuickShellSurfaceItem *>(moveItem))
+ return surf;
+ for (auto *item : moveItem->childItems()) {
+ if (auto *surf = findSurfaceItemFromMoveItem(item))
+ return surf;
+ }
+ return nullptr;
+}
+
+/*
+ To raise a surface, find the topmost suitable surface and place above that.
+ We start from the top and:
+ If we don't have staysOnTop, skip all surfaces with staysOnTop
+ If we have staysOnBottom, skip all surfaces that don't have staysOnBottom
+ */
+void QWaylandQuickShellSurfaceItemPrivate::raise()
+{
+ Q_Q(QWaylandQuickShellSurfaceItem);
+ auto *moveItem = q->moveItem();
+ QQuickItem *parent = moveItem->parentItem();
+ if (!parent)
+ return;
+ auto it = parent->childItems().crbegin();
+ auto skip = [this](QQuickItem *item) {
+ if (auto *surf = findSurfaceItemFromMoveItem(item))
+ return (!staysOnTop && surf->staysOnTop()) || (staysOnBottom && !surf->staysOnBottom());
+ return true; // ignore any other Quick items that may be there
+ };
+ while (skip(*it))
+ ++it;
+ QQuickItem *top = *it;
+ if (moveItem != top)
+ moveItem->stackAfter(top);
+}
+
+/*
+ To lower a surface, find the lowest suitable surface and place below that.
+ We start from the bottom and:
+ If we don't have staysOnBottom, skip all surfaces with staysOnBottom
+ If we have staysOnTop, skip all surfaces that don't have staysOnTop
+ */
+void QWaylandQuickShellSurfaceItemPrivate::lower()
+{
+ Q_Q(QWaylandQuickShellSurfaceItem);
+ auto *moveItem = q->moveItem();
+ QQuickItem *parent = moveItem->parentItem();
+ if (!parent)
+ return;
+ auto it = parent->childItems().cbegin();
+
+ auto skip = [this](QQuickItem *item) {
+ if (auto *surf = findSurfaceItemFromMoveItem(item))
+ return (!staysOnBottom && surf->staysOnBottom()) || (staysOnTop && !surf->staysOnTop());
+ return true; // ignore any other Quick items that may be there
+ };
+ while (skip(*it))
+ ++it;
+
+ QQuickItem *bottom = *it;
+ if (moveItem != bottom)
+ moveItem->stackBefore(bottom);
+}
+
+/*!
+ * \property QWaylandQuickShellSurfaceItem::staysOnTop
+ *
+ * Keep this item above other Wayland surfaces
+ */
+bool QWaylandQuickShellSurfaceItem::staysOnTop() const
+{
+ Q_D(const QWaylandQuickShellSurfaceItem);
+ return d->staysOnTop;
+}
+
+void QWaylandQuickShellSurfaceItem::setStaysOnTop(bool onTop)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (d->staysOnTop == onTop)
+ return;
+ d->staysOnTop = onTop;
+ if (d->staysOnBottom) {
+ d->staysOnBottom = false;
+ emit staysOnBottomChanged();
+ }
+ // We need to call raise() even if onTop is false, since we need to stack under any other
+ // staysOnTop surfaces in that case
+ raise();
+ emit staysOnTopChanged();
+ Q_ASSERT(!(d->staysOnTop && d->staysOnBottom));
+}
+
+/*!
+ * \property QWaylandQuickShellSurfaceItem::staysOnBottom
+ *
+ * Keep this item above other Wayland surfaces
+ */
+bool QWaylandQuickShellSurfaceItem::staysOnBottom() const
+{
+ Q_D(const QWaylandQuickShellSurfaceItem);
+ return d->staysOnBottom;
+}
+
+void QWaylandQuickShellSurfaceItem::setStaysOnBottom(bool onBottom)
+{
+ Q_D(QWaylandQuickShellSurfaceItem);
+ if (d->staysOnBottom == onBottom)
+ return;
+ d->staysOnBottom = onBottom;
+ if (d->staysOnTop) {
+ d->staysOnTop = false;
+ emit staysOnTopChanged();
+ }
+ // We need to call lower() even if onBottom is false, since we need to stack over any other
+ // staysOnBottom surfaces in that case
+ lower();
+ emit staysOnBottomChanged();
+ Q_ASSERT(!(d->staysOnTop && d->staysOnBottom));
+}
+
QT_END_NAMESPACE
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
index 9307909e..d2cc311a 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem.h
@@ -45,6 +45,8 @@ class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellSurfaceItem : public QWaylan
Q_PROPERTY(QWaylandShellSurface *shellSurface READ shellSurface WRITE setShellSurface NOTIFY shellSurfaceChanged)
Q_PROPERTY(QQuickItem *moveItem READ moveItem WRITE setMoveItem NOTIFY moveItemChanged)
Q_PROPERTY(bool autoCreatePopupItems READ autoCreatePopupItems WRITE setAutoCreatePopupItems NOTIFY autoCreatePopupItemsChanged)
+ Q_PROPERTY(bool staysOnTop READ staysOnTop WRITE setStaysOnTop NOTIFY staysOnTopChanged)
+ Q_PROPERTY(bool staysOnBottom READ staysOnBottom WRITE setStaysOnBottom NOTIFY staysOnBottomChanged)
Q_MOC_INCLUDE("qwaylandshellsurface.h")
QML_NAMED_ELEMENT(ShellSurfaceItem)
QML_ADDED_IN_VERSION(1, 0)
@@ -61,10 +63,17 @@ public:
bool autoCreatePopupItems();
void setAutoCreatePopupItems(bool enabled);
+ bool staysOnTop() const;
+ void setStaysOnTop(bool on);
+ bool staysOnBottom() const;
+ void setStaysOnBottom(bool on);
+
Q_SIGNALS:
void shellSurfaceChanged();
void moveItemChanged();
void autoCreatePopupItemsChanged();
+ void staysOnTopChanged();
+ void staysOnBottomChanged();
protected:
QWaylandQuickShellSurfaceItem(QWaylandQuickShellSurfaceItemPrivate &dd, QQuickItem *parent);
diff --git a/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h b/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h
index 24f38160..6fd96d16 100644
--- a/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h
+++ b/src/compositor/extensions/qwaylandquickshellsurfaceitem_p.h
@@ -61,10 +61,15 @@ public:
QWaylandQuickShellSurfaceItem *maybeCreateAutoPopup(QWaylandShellSurface* shellSurface);
static QWaylandQuickShellSurfaceItemPrivate *get(QWaylandQuickShellSurfaceItem *item) { return item->d_func(); }
+ void raise() override;
+ void lower() override;
+
QWaylandQuickShellIntegration *m_shellIntegration = nullptr;
QWaylandShellSurface *m_shellSurface = nullptr;
QQuickItem *m_moveItem = nullptr;
bool m_autoCreatePopupItems = true;
+ bool staysOnTop = false;
+ bool staysOnBottom = false;
};
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandQuickShellEventFilter : public QObject
diff --git a/src/compositor/extensions/qwaylandshellsurface.cpp b/src/compositor/extensions/qwaylandshellsurface.cpp
index d7f0c401..067e2f80 100644
--- a/src/compositor/extensions/qwaylandshellsurface.cpp
+++ b/src/compositor/extensions/qwaylandshellsurface.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the config.tests of the Qt Toolkit.
@@ -30,6 +30,41 @@
#include <QtWaylandCompositor/QWaylandShellSurface>
/*!
+ * \class QWaylandShellSurfaceTemplate
+ * \inmodule QtWaylandCompositor
+ * \since 5.8
+ * \brief QWaylandShellSurfaceTemplate is a convenience class for creating custom shell surface
+ * classes.
+ *
+ * QWaylandShellSurfaceTemplate is a template class which inherits from QWaylandShellSurface and
+ * is convenience for building custom shell extensions.
+ *
+ * It provides the connection between Qt Wayland Compositor and the class generated by
+ * \c qtwaylandscanner, based on the XML description of the extension protocol.
+ *
+ * It provides two specific pieces of convenience:
+ * \list
+ * \li A reimplementation of \l{QWaylandCompositorExtension::extensionInterface()} which returns
+ * the \c wl_interface pointer for the qtwaylandscanner-generated base class.
+ * \li A static \l{findIn()} function which searches for an instance of the extension in a
+ * provided container, and returns this if it is found.
+ * \endlist
+ *
+ * The same usage pattern applies as for QWaylandCompositorExtensionTemplate.
+ *
+ * \sa {Qt Wayland Compositor Examples - Custom Shell}
+ */
+
+/*!
+ * \fn template <typename T> T *QWaylandShellSurfaceTemplate<T>::findIn(QWaylandObject *container)
+ *
+ * If any instance of the interface has been registered with \a container, this is returned.
+ * Otherwise null is returned. The look-up is based on the generated \c interfaceName() which
+ * matches the interface name in the protocol description.
+ */
+
+
+/*!
* \qmltype ShellSurface
* \instantiates QWaylandShellSurface
* \inqmlmodule QtWayland.Compositor
@@ -39,7 +74,7 @@
* This interface represents a Wayland surface role given by a Wayland protocol extension that
* defines how the WaylandSurface should map onto the screen.
*
- * Note: Even though this type contains a very limited API, the properties and signals of the
+ * \note Even though this type contains a very limited API, the properties and signals of the
* implementations are named consistently. For example, if you're only using desktop shell
* extensions in your compositor, it's safe to access properties such as title, maximized, etc.
* directly on the ShellSurface. See the various implementations for additional properties and
@@ -57,7 +92,7 @@
* This interface represents a Wayland surface role given by a Wayland protocol extension that
* defines how the QWaylandSurface should map onto the screen.
*
- * \sa QWaylandSurface, QWaylandWlShellSurface, QWaylandIviSurface
+ * \sa QWaylandSurface, QWaylandWlShellSurface, QWaylandIviSurface, QWaylandShellSurfaceTemplate
*/
#if QT_CONFIG(wayland_compositor_quick)
diff --git a/src/compositor/extensions/qwaylandshellsurface.h b/src/compositor/extensions/qwaylandshellsurface.h
index 8dd7da9c..f1814df3 100644
--- a/src/compositor/extensions/qwaylandshellsurface.h
+++ b/src/compositor/extensions/qwaylandshellsurface.h
@@ -64,7 +64,7 @@ template <typename T>
class Q_WAYLAND_COMPOSITOR_EXPORT QWaylandShellSurfaceTemplate : public QWaylandShellSurface
{
public:
- QWaylandShellSurfaceTemplate(QWaylandObject *container)
+ QWaylandShellSurfaceTemplate(QWaylandObject *container = nullptr)
: QWaylandShellSurface(container)
{ }
diff --git a/src/compositor/global/qwaylandcompositorextension.cpp b/src/compositor/global/qwaylandcompositorextension.cpp
index 6fc66513..5092cdfa 100644
--- a/src/compositor/global/qwaylandcompositorextension.cpp
+++ b/src/compositor/global/qwaylandcompositorextension.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2017 The Qt Company Ltd.
+** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWaylandCompositor module of the Qt Toolkit.
@@ -27,7 +27,6 @@
**
****************************************************************************/
-
#include "qwaylandcompositorextension.h"
#include "qwaylandcompositorextension_p.h"
@@ -38,11 +37,85 @@
QT_BEGIN_NAMESPACE
+/*!
+ * \class QWaylandCompositorExtensionTemplate
+ * \inmodule QtWaylandCompositor
+ * \since 5.8
+ * \brief QWaylandCompositorExtensionTemplate is a convenience class for subclassing
+ * QWaylandCompositorExtension.
+ *
+ * QWaylandCompositorExtensionTemplate is a template class which inherits
+ * QWaylandCompositorExtension and is convenience for building custom Wayland extensions with Qt.
+ *
+ * It provides the connection between Qt Wayland Compositor and the class generated by
+ * \c qtwaylandscanner, based on the XML description of the extension protocol.
+ *
+ * It provides two specific pieces of convenience:
+ * \list
+ * \li A reimplementation of \l{QWaylandCompositorExtension::extensionInterface()} which returns
+ * the \c wl_interface pointer for the qtwaylandscanner-generated base class.
+ * \li A static \l{findIn()} function which searches for an instance of the extension in a
+ * provided container, and returns this if it is found.
+ * \endlist
+ *
+ * Typically, a new extension will dual-inherit QWaylandCompositorExtensionTemplate and the class
+ * generated by \c qtwaylandscanner.
+ *
+ * QWaylandCompositorExtensionTemplate should be parameterized with the subclass itself:
+ * \code
+ * class MyExtension
+ * : public QWaylandCompositorExtensionTemplate<MyExtension>
+ * , QtWaylandServer::my_extension
+ * \endcode
+ *
+ * In this example, \c MyExtension is an implementation of the generated interface \c my_extension.
+ *
+ * \sa {Qt Wayland Compositor Examples - Custom Shell}
+ */
+
+/*!
+ * \fn template <typename T> T *QWaylandCompositorExtensionTemplate<T>::findIn(QWaylandObject *container)
+ *
+ * If any instance of the interface has been registered with \a container, this is returned.
+ * Otherwise null is returned. The look-up is based on the generated \c interfaceName() which
+ * matches the interface name in the protocol description.
+ */
+
+/*!
+ * \class QWaylandCompositorExtension
+ * \inmodule QtWaylandCompositor
+ * \since 5.8
+ * \brief QWaylandCompositorExtension is the base class for compositor extensions.
+ *
+ * QWaylandCompositorExtension is the base class for implementing Wayland extensions on the
+ * compositor-side of the connection. If no other extension container is explicitly set, it will
+ * automatically add itself to its parent object, granted that this inherits from QWaylandObject.
+ *
+ * For example, for registering global extensions, you can inherit from QWaylandCompositorExtension
+ * and pass the QWaylandCompositor object as extension container.
+ *
+ * \sa QWaylandCompositorExtensionTemplate, {Qt Wayland Compositor Examples - Custom Shell}
+ */
+
+/*!
+ * Creates a QWaylandCompositorExtension with no container.
+ *
+ * \sa setExtensionContainer()
+ */
QWaylandCompositorExtension::QWaylandCompositorExtension()
: QWaylandObject(*new QWaylandCompositorExtensionPrivate())
{
}
+/*!
+ * Creates a QWaylandCompositorExtension and adds it to the extension \a container. The \a container
+ * does not become the parent of the QWaylandCompositorExtension.
+ *
+ * The extension adds itself to \a container later, when \l{initialize()} is called. For this to
+ * happen automatically, an event loop must be running in the current thread.
+ *
+ * The QWaylandCompositorExtension will remove itself again when it is destroyed.
+ */
QWaylandCompositorExtension::QWaylandCompositorExtension(QWaylandObject *container)
: QWaylandObject(*new QWaylandCompositorExtensionPrivate())
{
@@ -69,18 +142,42 @@ QWaylandCompositorExtension::~QWaylandCompositorExtension()
d->extension_container->removeExtension(this);
}
+/*!
+ * \fn const wl_interface *QWaylandCompositorExtension::extensionInterface() const
+ *
+ * A pure virtual function which should be reimplemented to return the \c wl_interface which
+ * corresponds to this QWaylandCompositorExtension.
+ */
+
+/*!
+ * \return the extension container for this QWaylandCompositorExtension or null if none has been
+ * set.
+ */
QWaylandObject *QWaylandCompositorExtension::extensionContainer() const
{
Q_D(const QWaylandCompositorExtension);
return d->extension_container;
}
+/*!
+ * Sets the extension container for this QWaylandCompositorExtension to \a container. This must be
+ * called before \l{initialize()} and cannot be changed once the QWaylandCompositorExtension has
+ * been initialized.
+ */
void QWaylandCompositorExtension::setExtensionContainer(QWaylandObject *container)
{
Q_D(QWaylandCompositorExtension);
d->extension_container = container;
}
+/*!
+ * Initializes the QWaylandCompositorExtension. The default implementation adopts the parent object
+ * as extension container if none has been set, and if the parent inherits from QWaylandObject. The
+ * default implementation also adds the QWaylandCompositorExtension to the list of extensions
+ * managed by the extension container.
+ *
+ * Override this function in subclasses to provide custom initialization code.
+ */
void QWaylandCompositorExtension::initialize()
{
Q_D(QWaylandCompositorExtension);
@@ -123,6 +220,21 @@ bool QWaylandCompositorExtension::event(QEvent *event)
return QWaylandObject::event(event);
}
+/*!
+ * \class QWaylandObject
+ * \inmodule QtWaylandCompositor
+ * \since 5.8
+ * \brief QWaylandObject is the base class for objects that can contain Wayland extensions.
+ *
+ * The QWaylandObject encapsulate extension container functionality. Any QWaylandObject object
+ * will automatically be an extension container and QWaylandCompositorExtension object which is
+ * a child of this will automatically add itself to its extension list, and remove itself when
+ * the extension object is destroyed.
+ */
+
+/*!
+ * Creates a QWaylandObject as a child of \a parent.
+ */
QWaylandObject::QWaylandObject(QObject *parent)
:QObject(parent)
{
@@ -140,6 +252,11 @@ QWaylandObject::~QWaylandObject()
QWaylandCompositorExtensionPrivate::get(extension)->extension_container = nullptr;
}
+/*!
+ * Returns the compositor extension which matches \a name if one has been registered with the
+ * QWaylandObject. If no extension matching the name has been registered, this function returns
+ * null.
+ */
QWaylandCompositorExtension *QWaylandObject::extension(const QByteArray &name)
{
for (int i = 0; i < extension_vector.size(); i++) {
@@ -149,6 +266,11 @@ QWaylandCompositorExtension *QWaylandObject::extension(const QByteArray &name)
return nullptr;
}
+/*!
+ * Returns the compositor extension which matches \a interface if one has been registered with the
+ * QWaylandObject. If no extension matching the interface has been registered, this function
+ * returns null.
+ */
QWaylandCompositorExtension *QWaylandObject::extension(const wl_interface *interface)
{
for (int i = 0; i < extension_vector.size(); i++) {
@@ -158,17 +280,27 @@ QWaylandCompositorExtension *QWaylandObject::extension(const wl_interface *inter
return nullptr;
}
+/*!
+ * Returns the list of compositor extensions that have been registered with this QWaylandObject.
+ */
QList<QWaylandCompositorExtension *> QWaylandObject::extensions() const
{
return extension_vector;
}
+/*!
+ * Registers \a extension with this QWaylandObject.
+ */
void QWaylandObject::addExtension(QWaylandCompositorExtension *extension)
{
Q_ASSERT(!extension_vector.contains(extension));
extension_vector.append(extension);
}
+/*!
+ * Removes \a extension from the list of registered extensions in this QWaylandObject, if it has
+ * previously been registered using \l{addExtension()}.
+ */
void QWaylandObject::removeExtension(QWaylandCompositorExtension *extension)
{
Q_ASSERT(extension_vector.contains(extension));
diff --git a/src/compositor/global/qwaylandquickextension.qdoc b/src/compositor/global/qwaylandquickextension.qdoc
new file mode 100644
index 00000000..925baef2
--- /dev/null
+++ b/src/compositor/global/qwaylandquickextension.qdoc
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2021 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the documentation of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:FDL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Free Documentation License Usage
+** Alternatively, this file may be used under the terms of the GNU Free
+** Documentation License version 1.3 as published by the Free Software
+** Foundation and appearing in the file included in the packaging of
+** this file. Please review the following information to ensure
+** the GNU Free Documentation License version 1.3 requirements
+** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ * \headerfile <QWaylandQuickExtension>
+ * \title Qt Wayland Compositor Qt Quick Extension Macro Declarations
+ * \inmodule QtWaylandCompositor
+ * \ingroup funclists
+ *
+ * \brief The <QWaylandQuickExtension> header file includes \l{macros} for creating Qt Quick types
+ * that correspond to subclasses of QWaylandCompositorExtension and QWaylandObject.
+ *
+ * If you are creating extensions to Qt Wayland Compositor, the macros in the QWaylandQuickExtension
+ * header may be a useful alternative to manually implementing the required parts for each class.
+ *
+ * \sa {Qt Wayland Compositor Examples - Custom Shell}
+ */
+
+/*!
+ * \macro Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS(className)
+ * \relates <QWaylandQuickExtension>
+ *
+ * This macro can be used to define a Qt Quick class based on a Wayland extension. It defines
+ * a new class which inherits from \a className and which suffixes the name with "QuickExtension".
+ *
+ * The class should be a subclass of QWaylandCompositorExtension, and
+ * \l{QWaylandCompositorExtension::initialize()} will be called automatically. The type must be
+ * manually registered in Qt Quick using \l{qmlRegisterType()}.
+ *
+ * \sa Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_NAMED_CLASS
+ */
+
+/*!
+ * \macro Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CONTAINER_CLASS(className)
+ * \relates <QWaylandQuickExtension>
+ *
+ * This macro can be used to define a Qt Quick class intended to contain Wayland extensions. It
+ *
+ * It defines a new class which inherits from \a className and which suffixes the name with
+ * "QuickExtensionContainer". The class given by \a className should inherit from QWaylandObject,
+ * and the new class will have an \c extensions property which manages the extensions by calling
+ * \l{QWaylandObject::addExtension()}{addExtension()} and
+ * \l{QWaylandObject::removeExtension()}{removeExtension()} in the base class.
+ *
+ * The type must be manually registered in Qt Quick using \l{qmlRegisterType()}.
+ */
+
+/*!
+ * \macro Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_NAMED_CLASS(className, QmlType)
+ * \relates <QWaylandQuickExtension>
+ *
+ * This macro can be used to define a Qt Quick class based on a Wayland extension. It defines
+ * a new class which inherits from \a className and which suffixes the name with "QuickExtension".
+ *
+ * The macro works the same as \l{Q_COMPOSITOR_DECLARE_QUICK_EXTENSION_CLASS}, but will also
+ * automatically register the new type as \a QmlType in Qt Quick.
+ */