summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@pelagicore.com>2018-03-28 16:12:54 +0200
committerRobert Griebl <robert.griebl@pelagicore.com>2018-04-04 13:33:52 +0000
commitc0675368828969f3bfb5509f49a7c5368f0b8af3 (patch)
tree4eef821bbdbd9030c18c5263ee09963e8d89a6b7
parentb4b6adf4c0e915b399c02cb7b913f0bd3ff03ecc (diff)
Replace QtWayland's surface extension with a custom AM extension
Qt's qt_surface_extension was deprecated with Qt 5.11, so we need a new way to communicate window properties. The new extension does not use a per-surface extension interface anymore, since that makes the code on both sides a lot simpler. Change-Id: I4f908fa5f0fa356c02c132cd32fe44b63deaf15e Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
-rw-r--r--.qt-license-check.exclude1
-rw-r--r--src/common-lib/logging.cpp14
-rw-r--r--src/common-lib/logging.h1
-rw-r--r--src/launcher-lib/applicationmanagerwindow.cpp46
-rw-r--r--src/launcher-lib/applicationmanagerwindow_p.h5
-rw-r--r--src/launcher-lib/launcher-lib.pro12
-rw-r--r--src/launcher-lib/launchermain.cpp35
-rw-r--r--src/launcher-lib/launchermain.h13
-rw-r--r--src/launcher-lib/waylandqtamclientextension.cpp148
-rw-r--r--src/launcher-lib/waylandqtamclientextension_p.h94
-rw-r--r--src/launchers/qml/main.cpp1
-rw-r--r--src/wayland-extensions/qtam-extension.xml65
-rw-r--r--src/window-lib/waylandcompositor.cpp42
-rw-r--r--src/window-lib/waylandcompositor.h18
-rw-r--r--src/window-lib/waylandqtamserverextension.cpp103
-rw-r--r--src/window-lib/waylandqtamserverextension_p.h86
-rw-r--r--src/window-lib/waylandwindow.cpp26
-rw-r--r--src/window-lib/window-lib.pro12
18 files changed, 618 insertions, 104 deletions
diff --git a/.qt-license-check.exclude b/.qt-license-check.exclude
new file mode 100644
index 00000000..e80073a6
--- /dev/null
+++ b/.qt-license-check.exclude
@@ -0,0 +1 @@
+src/wayland-extensions/.*\.xml
diff --git a/src/common-lib/logging.cpp b/src/common-lib/logging.cpp
index b74cb3b1..3be5db62 100644
--- a/src/common-lib/logging.cpp
+++ b/src/common-lib/logging.cpp
@@ -75,13 +75,14 @@ QT_BEGIN_NAMESPACE_AM
//! [am-logging-categories]
\list
\li \c am.system - General system messages
-\li \c am.runtime.qml - QML runtime
-\li \c am.graphics - OpenGL/Wayland related messages
-\li \c am.deployment - Deployment hints"
\li \c am.installer - Installer sub-system
-\li \c am.notify - Notification sub-system
+\li \c am.graphics - OpenGL/UI related messages
+\li \c am.wayland.debug - Wayland protocol related messages
\li \c am.qml - QML messages
+\li \c am.runtime.qml - QML runtime
\li \c am.qml.ipc - QML IPC
+\li \c am.notify - Notification sub-system
+\li \c am.deployment - Deployment hints
\li \c general - General messages not part of any ApplicationManager sub-system
\endlist
//! [am-logging-categories]
@@ -90,11 +91,12 @@ QDLT_REGISTER_CONTEXT_ON_FIRST_USE(true)
QDLT_REGISTER_APPLICATION("PCAM", "Pelagicore Application-Manager")
QDLT_LOGGING_CATEGORY(LogSystem, "am.system", "SYS", "General system messages")
QDLT_LOGGING_CATEGORY(LogInstaller, "am.installer", "INST", "Installer sub-system")
-QDLT_LOGGING_CATEGORY(LogGraphics, "am.graphics", "GRPH", "OpenGL/Wayland related messages")
+QDLT_LOGGING_CATEGORY(LogGraphics, "am.graphics", "GRPH", "OpenGL/UI related messages")
+QDLT_LOGGING_CATEGORY(LogWaylandDebug, "am.wayland.debug", "WAYL", "Wayland protocol related messages")
QDLT_LOGGING_CATEGORY(LogQml, "am.qml", "QML", "QML messages")
-QDLT_LOGGING_CATEGORY(LogNotifications, "am.notify", "NTFY", "Notification sub-system")
QDLT_LOGGING_CATEGORY(LogQmlRuntime, "am.runtime.qml", "QMRT", "QML runtime")
QDLT_LOGGING_CATEGORY(LogQmlIpc, "am.qml.ipc", "QMIP", "QML IPC")
+QDLT_LOGGING_CATEGORY(LogNotifications, "am.notify", "NTFY", "Notification sub-system")
QDLT_LOGGING_CATEGORY(LogDeployment, "am.deployment", "DPLM", "Deployment hints")
QDLT_LOGGING_CATEGORY(LogGeneral, "general", "GEN", "General messages not part of any ApplicationManager sub-system")
QDLT_FALLBACK_CATEGORY(LogGeneral)
diff --git a/src/common-lib/logging.h b/src/common-lib/logging.h
index 77aff74f..fcf84ef1 100644
--- a/src/common-lib/logging.h
+++ b/src/common-lib/logging.h
@@ -49,6 +49,7 @@ QT_BEGIN_NAMESPACE_AM
Q_DECLARE_LOGGING_CATEGORY(LogSystem)
Q_DECLARE_LOGGING_CATEGORY(LogInstaller)
Q_DECLARE_LOGGING_CATEGORY(LogGraphics)
+Q_DECLARE_LOGGING_CATEGORY(LogWaylandDebug)
Q_DECLARE_LOGGING_CATEGORY(LogQml)
Q_DECLARE_LOGGING_CATEGORY(LogNotifications)
Q_DECLARE_LOGGING_CATEGORY(LogQmlRuntime)
diff --git a/src/launcher-lib/applicationmanagerwindow.cpp b/src/launcher-lib/applicationmanagerwindow.cpp
index 65384247..aca5e120 100644
--- a/src/launcher-lib/applicationmanagerwindow.cpp
+++ b/src/launcher-lib/applicationmanagerwindow.cpp
@@ -45,6 +45,7 @@
#include <qpa/qplatformwindow.h>
#include "logging.h"
+#include "launchermain.h"
#include "applicationmanagerwindow_p.h"
QT_BEGIN_NAMESPACE_AM
@@ -52,8 +53,7 @@ QT_BEGIN_NAMESPACE_AM
class ApplicationManagerWindowPrivate
{
public:
- QPlatformNativeInterface *platformNativeInterface = nullptr;
- QPlatformWindow *platformWindow = nullptr;
+ LauncherMain *launcherMain = nullptr;
};
@@ -125,18 +125,12 @@ ApplicationManagerWindow::ApplicationManagerWindow(QWindow *parent)
(void) winId(); // force allocation of platform resources
- d->platformNativeInterface = qApp->platformNativeInterface();
- d->platformWindow = handle();
- if (!d->platformNativeInterface) {
- qCCritical(LogQmlRuntime) << "ApplicationManagerWindow failed to get a valid QPlatformNativeInterface object";
- return;
- }
- if (!d->platformWindow) {
- qCCritical(LogQmlRuntime) << "ApplicationManagerWindow failed to get a QPlatformWindow handle for itself";
- return;
- }
- connect(d->platformNativeInterface, &QPlatformNativeInterface::windowPropertyChanged,
- this, &ApplicationManagerWindow::onWindowPropertyChangedInternal);
+ d->launcherMain = LauncherMain::instance();
+ connect(d->launcherMain, &LauncherMain::windowPropertyChanged,
+ this, [this](QWindow *window, const QString &name, const QVariant &value) {
+ if (window == this)
+ emit windowPropertyChanged(name, value);
+ });
}
ApplicationManagerWindow::~ApplicationManagerWindow()
@@ -144,16 +138,9 @@ ApplicationManagerWindow::~ApplicationManagerWindow()
delete d;
}
-void ApplicationManagerWindow::onWindowPropertyChangedInternal(QPlatformWindow *pw, const QString &name)
-{
- if (pw == d->platformWindow && d->platformWindow && d->platformNativeInterface) {
- emit windowPropertyChanged(name, d->platformNativeInterface->windowProperty(pw, name));
- }
-}
/*!
- \qmlmethod bool ApplicationManagerWindow::setWindowProperty(string name, var &value)
-
+ \qmlmethod void ApplicationManagerWindow::setWindowProperty(string name, var &value)
Sets this application window's shared property identified by \a name to the given \a value.
These properties are shared between the System-UI and the client applications: in single-process
@@ -168,12 +155,9 @@ void ApplicationManagerWindow::onWindowPropertyChangedInternal(QPlatformWindow *
\sa windowProperty, windowProperties, windowPropertyChanged
*/
-bool ApplicationManagerWindow::setWindowProperty(const QString &name, const QVariant &value)
+void ApplicationManagerWindow::setWindowProperty(const QString &name, const QVariant &value)
{
- if (!d->platformNativeInterface || !d->platformWindow)
- return false;
- d->platformNativeInterface->setWindowProperty(d->platformWindow, name, value);
- return true;
+ d->launcherMain->setWindowProperty(this, name, value);
}
/*!
@@ -185,9 +169,7 @@ bool ApplicationManagerWindow::setWindowProperty(const QString &name, const QVar
*/
QVariant ApplicationManagerWindow::windowProperty(const QString &name) const
{
- if (!d->platformNativeInterface || !d->platformWindow)
- return QVariant();
- return d->platformNativeInterface->windowProperty(d->platformWindow, name);
+ return windowProperties().value(name);
}
/*!
@@ -199,9 +181,7 @@ QVariant ApplicationManagerWindow::windowProperty(const QString &name) const
*/
QVariantMap ApplicationManagerWindow::windowProperties() const
{
- if (!d->platformNativeInterface || !d->platformWindow)
- return QVariantMap();
- return d->platformNativeInterface->windowProperties(d->platformWindow);
+ return d->launcherMain->windowProperties(const_cast<ApplicationManagerWindow *>(this));
}
/*!
diff --git a/src/launcher-lib/applicationmanagerwindow_p.h b/src/launcher-lib/applicationmanagerwindow_p.h
index c9d5fd40..1c773cd6 100644
--- a/src/launcher-lib/applicationmanagerwindow_p.h
+++ b/src/launcher-lib/applicationmanagerwindow_p.h
@@ -59,16 +59,13 @@ public:
explicit ApplicationManagerWindow(QWindow *parent = nullptr);
~ApplicationManagerWindow();
- Q_INVOKABLE bool setWindowProperty(const QString &name, const QVariant &value);
+ Q_INVOKABLE void setWindowProperty(const QString &name, const QVariant &value);
Q_INVOKABLE QVariant windowProperty(const QString &name) const;
Q_INVOKABLE QVariantMap windowProperties() const;
signals:
void windowPropertyChanged(const QString &name, const QVariant &value);
-private slots:
- void onWindowPropertyChangedInternal(QPlatformWindow *window, const QString &name);
-
private:
ApplicationManagerWindowPrivate *d;
};
diff --git a/src/launcher-lib/launcher-lib.pro b/src/launcher-lib/launcher-lib.pro
index c6d40678..587725b1 100644
--- a/src/launcher-lib/launcher-lib.pro
+++ b/src/launcher-lib/launcher-lib.pro
@@ -20,18 +20,26 @@ SOURCES += \
ipcwrapperobject.cpp \
qmlapplicationinterfaceextension.cpp \
qmlnotification.cpp \
- launchermain.cpp
+ launchermain.cpp \
!headless:SOURCES += \
applicationmanagerwindow.cpp \
+!headless:qtHaveModule(waylandclient) {
+ QT *= waylandclient waylandclient-private
+ CONFIG *= wayland-scanner
+ WAYLANDCLIENTSOURCES += ../wayland-extensions/qtam-extension.xml
+ HEADERS += waylandqtamclientextension_p.h
+ SOURCES += waylandqtamclientextension.cpp
+}
+
HEADERS += \
qmlapplicationinterface.h \
ipcwrapperobject.h \
ipcwrapperobject_p.h \
qmlapplicationinterfaceextension.h \
qmlnotification.h \
- launchermain.h
+ launchermain.h \
!headless:HEADERS += \
applicationmanagerwindow_p.h
diff --git a/src/launcher-lib/launchermain.cpp b/src/launcher-lib/launchermain.cpp
index 76142550..7de88eb2 100644
--- a/src/launcher-lib/launchermain.cpp
+++ b/src/launcher-lib/launchermain.cpp
@@ -49,6 +49,9 @@
#include <QtAppManCommon/qtyaml.h>
+#if !defined(AM_HEADLESS) && defined(QT_WAYLANDCLIENT_LIB)
+# include "waylandqtamclientextension_p.h"
+#endif
#include "launchermain.h"
QT_BEGIN_NAMESPACE_AM
@@ -61,6 +64,20 @@ LauncherMain::LauncherMain(int &argc, char **argv) Q_DECL_NOEXCEPT
LauncherMain::~LauncherMain()
{ }
+LauncherMain *LauncherMain::instance()
+{
+ return qobject_cast<LauncherMain *>(qApp);
+}
+
+void LauncherMain::registerWaylandExtensions() Q_DECL_NOEXCEPT
+{
+#if !defined(AM_HEADLESS) && defined(QT_WAYLANDCLIENT_LIB)
+ m_waylandExtension = new WaylandQtAMClientExtension();
+ connect(m_waylandExtension, &WaylandQtAMClientExtension::windowPropertyChanged,
+ this, &LauncherMain::windowPropertyChanged);
+#endif
+}
+
QString LauncherMain::baseDir() const
{
return m_baseDir;
@@ -106,6 +123,24 @@ QVariantMap LauncherMain::openGLConfiguration() const
return m_openGLConfiguration;
}
+
+QVariantMap LauncherMain::windowProperties(QWindow *window) const
+{
+#if !defined(AM_HEADLESS) && defined(QT_WAYLANDCLIENT_LIB)
+ if (m_waylandExtension && window)
+ return m_waylandExtension->windowProperties(window);
+#endif
+ return QVariantMap();
+}
+
+void LauncherMain::setWindowProperty(QWindow *window, const QString &name, const QVariant &value)
+{
+#if !defined(AM_HEADLESS) && defined(QT_WAYLANDCLIENT_LIB)
+ if (m_waylandExtension && window)
+ m_waylandExtension->setWindowProperty(window, name, value);
+#endif
+}
+
void LauncherMain::loadConfiguration(const QByteArray &configYaml) Q_DECL_NOEXCEPT_EXPR(false)
{
auto docs = QtYaml::variantDocumentsFromYaml(configYaml.isEmpty() ? qgetenv("AM_CONFIG")
diff --git a/src/launcher-lib/launchermain.h b/src/launcher-lib/launchermain.h
index 73a076cb..323a0d0d 100644
--- a/src/launcher-lib/launchermain.h
+++ b/src/launcher-lib/launchermain.h
@@ -47,6 +47,7 @@
#if defined(AM_HEADLESS)
# include <QCoreApplication>
typedef QCoreApplication LauncherMainBase;
+QT_FORWARD_DECLARE_CLASS(QWindow)
#elif defined(AM_ENABLE_WIDGETS)
# include <QApplication>
# include <QSurfaceFormat>
@@ -60,6 +61,8 @@ typedef QGuiApplication LauncherMainBase;
QT_BEGIN_NAMESPACE_AM
+class WaylandQtAMClientExtension;
+
class LauncherMain : public LauncherMainBase, public SharedMain
{
Q_OBJECT
@@ -67,9 +70,12 @@ public:
LauncherMain(int &argc, char **argv) Q_DECL_NOEXCEPT;
~LauncherMain();
+ static LauncherMain *instance();
+
public:
void loadConfiguration(const QByteArray &configYaml = QByteArray()) Q_DECL_NOEXCEPT_EXPR(false);
void setupDBusConnections() Q_DECL_NOEXCEPT_EXPR(false);
+ void registerWaylandExtensions() Q_DECL_NOEXCEPT;
QString baseDir() const;
QVariantMap runtimeConfiguration() const;
@@ -83,6 +89,12 @@ public:
QVariantMap openGLConfiguration() const;
+ QVariantMap windowProperties(QWindow *window) const;
+ void setWindowProperty(QWindow *window, const QString &name, const QVariant &value);
+
+signals:
+ void windowPropertyChanged(QWindow *window, const QString &name, const QVariant &value);
+
private:
QVariantMap m_configuration;
QString m_baseDir;
@@ -94,6 +106,7 @@ private:
QString m_dbusAddressP2P;
QString m_dbusAddressNotifications;
QVariantMap m_openGLConfiguration;
+ WaylandQtAMClientExtension *m_waylandExtension = nullptr;
};
QT_END_NAMESPACE_AM
diff --git a/src/launcher-lib/waylandqtamclientextension.cpp b/src/launcher-lib/waylandqtamclientextension.cpp
new file mode 100644
index 00000000..e047d3e4
--- /dev/null
+++ b/src/launcher-lib/waylandqtamclientextension.cpp
@@ -0,0 +1,148 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#include "waylandqtamclientextension_p.h"
+
+#include <QWindow>
+#include <QGuiApplication>
+#include <QPlatformSurfaceEvent>
+#include <qpa/qplatformnativeinterface.h>
+
+#include <QtAppManCommon/logging.h>
+
+QT_BEGIN_NAMESPACE_AM
+
+WaylandQtAMClientExtension::WaylandQtAMClientExtension()
+ : QWaylandClientExtensionTemplate(1)
+{
+ qApp->installEventFilter(this);
+}
+
+WaylandQtAMClientExtension::~WaylandQtAMClientExtension()
+{
+ qApp->removeEventFilter(this);
+}
+
+bool WaylandQtAMClientExtension::eventFilter(QObject *o, QEvent *e)
+{
+ if (e->type() == QEvent::PlatformSurface) {
+ QWindow *window = qobject_cast<QWindow *>(o);
+ if (!window)
+ return false;
+ if (!isActive()) {
+ qCWarning(LogGraphics) << "Tried to (un)register a Wayland qtam_extended_surface, but the extension itself is not active";
+ return false;
+ }
+
+ switch (static_cast<QPlatformSurfaceEvent *>(e)->surfaceEventType()) {
+ case QPlatformSurfaceEvent::SurfaceCreated: {
+ auto surface = static_cast<struct ::wl_surface *>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow("surface", window));
+ m_windows.insert(surface, window);
+ const QVariantMap wp = windowProperties(window);
+ for (auto it = wp.cbegin(); it != wp.cend(); ++it)
+ sendPropertyToServer(surface, it.key(), it.value());
+ break;
+ }
+ case QPlatformSurfaceEvent::SurfaceAboutToBeDestroyed:
+ m_windowProperties.remove(window);
+ break;
+
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+QVariantMap WaylandQtAMClientExtension::windowProperties(QWindow *window) const
+{
+ return m_windowProperties.value(window);
+}
+
+void WaylandQtAMClientExtension::sendPropertyToServer(struct ::wl_surface *surface, const QString &name, const QVariant &value)
+{
+ QByteArray byteValue;
+ QDataStream ds(&byteValue, QIODevice::WriteOnly);
+ ds << value;
+ qCDebug(LogWaylandDebug) << "CLIENT >>prop>>" << surface << name << value;
+ set_window_property(surface, name, byteValue);
+}
+
+void WaylandQtAMClientExtension::setWindowProperty(QWindow *window, const QString &name, const QVariant &value)
+{
+ if (setWindowPropertyHelper(window, name, value)) {
+ auto surface = static_cast<struct ::wl_surface *>(QGuiApplication::platformNativeInterface()->nativeResourceForWindow("surface", window));
+ if (surface)
+ sendPropertyToServer(surface, name, value);
+ }
+}
+
+bool WaylandQtAMClientExtension::setWindowPropertyHelper(QWindow *window, const QString &name, const QVariant &value)
+{
+ auto it = m_windowProperties.find(window);
+ if ((it == m_windowProperties.end()) || (it.value().value(name) != value)) {
+ if (it == m_windowProperties.end())
+ m_windowProperties[window].insert(name, value);
+ else
+ it.value().insert(name, value);
+
+ emit windowPropertyChanged(window, name, value);
+ return true;
+ }
+ return false;
+}
+
+void WaylandQtAMClientExtension::qtam_extension_window_property_changed(wl_surface *surface, const QString &name, wl_array *value)
+{
+ const QByteArray data = QByteArray::fromRawData(static_cast<char *>(value->data), value->size);
+ QDataStream ds(data);
+ QVariant variantValue;
+ ds >> variantValue;
+
+ QWindow *window = m_windows.value(surface);
+ qCDebug(LogWaylandDebug) << "CLIENT <<prop<<" << window << name << variantValue;
+ if (!window)
+ return;
+
+ setWindowPropertyHelper(window, name, variantValue);
+}
+
+QT_END_NAMESPACE_AM
diff --git a/src/launcher-lib/waylandqtamclientextension_p.h b/src/launcher-lib/waylandqtamclientextension_p.h
new file mode 100644
index 00000000..4cff387b
--- /dev/null
+++ b/src/launcher-lib/waylandqtamclientextension_p.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QVariantMap>
+#include <QtWaylandClient/QWaylandClientExtensionTemplate>
+#include "private/qwayland-qtam-extension.h"
+
+#include <QtAppManCommon/global.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_FORWARD_DECLARE_CLASS(QWaylandCompositor)
+QT_FORWARD_DECLARE_CLASS(QWaylandSurface)
+QT_FORWARD_DECLARE_CLASS(QWindow)
+
+QT_BEGIN_NAMESPACE_AM
+
+class WaylandQtAMClientExtension : public QWaylandClientExtensionTemplate<WaylandQtAMClientExtension>,
+ public ::QtWayland::qtam_extension
+{
+ Q_OBJECT
+
+public:
+ WaylandQtAMClientExtension();
+ ~WaylandQtAMClientExtension();
+
+ QVariantMap windowProperties(QWindow *window) const;
+ void setWindowProperty(QWindow *window, const QString &name, const QVariant &value);
+
+signals:
+ void windowPropertyChanged(QWindow *window, const QString &name, const QVariant &value);
+
+protected:
+ bool eventFilter(QObject *o, QEvent *e);
+
+private:
+ bool setWindowPropertyHelper(QWindow *window, const QString &name, const QVariant &value);
+ void sendPropertyToServer(::wl_surface *surface, const QString &name, const QVariant &value);
+ void qtam_extension_window_property_changed(wl_surface *surface, const QString &name, wl_array *value) override;
+
+ QMap<QWindow *, QVariantMap> m_windowProperties;
+ QMap<::wl_surface *, QWindow *> m_windows;
+};
+
+QT_END_NAMESPACE_AM
diff --git a/src/launchers/qml/main.cpp b/src/launchers/qml/main.cpp
index a8f8b343..41c9dea2 100644
--- a/src/launchers/qml/main.cpp
+++ b/src/launchers/qml/main.cpp
@@ -181,6 +181,7 @@ int main(int argc, char *argv[])
a.setupLoggingRules(false, a.loggingRules()); // the verbose flag has already been factored into the rules
a.setupQmlDebugging(clp.isSet(qSL("qml-debug")));
a.setupOpenGL(a.openGLConfiguration());
+ a.registerWaylandExtensions();
StartupTimer::instance()->checkpoint("after basic initialization");
diff --git a/src/wayland-extensions/qtam-extension.xml b/src/wayland-extensions/qtam-extension.xml
new file mode 100644
index 00000000..8bc41b58
--- /dev/null
+++ b/src/wayland-extensions/qtam-extension.xml
@@ -0,0 +1,65 @@
+<protocol name="qtam_extension">
+ <copyright>
+ Copyright (C) 2018 Pelagicore AG
+ Contact: https://www.qt.io/licensing/
+
+ This file is part of the Pelagicore Application Manager.
+
+ $QT_BEGIN_LICENSE:BSD-QTAS$
+ Commercial License Usage
+ Licensees holding valid commercial Qt Automotive Suite 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.
+
+ BSD License Usage
+ Alternatively, you may use this file under the terms of the BSD license
+ as follows:
+
+ "Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name of The Qt Company Ltd nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
+
+ $QT_END_LICENSE$
+
+ SPDX-License-Identifier: BSD-3-Clause
+ </copyright>
+
+ <interface name="qtam_extension" version="1">
+ <event name="window_property_changed">
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="name" type="string"/>
+ <arg name="value" type="array"/>
+ </event>
+
+ <request name="set_window_property">
+ <arg name="surface" type="object" interface="wl_surface"/>
+ <arg name="name" type="string"/>
+ <arg name="value" type="array"/>
+ </request>
+ </interface>
+</protocol>
diff --git a/src/window-lib/waylandcompositor.cpp b/src/window-lib/waylandcompositor.cpp
index 61cbefd2..ec896721 100644
--- a/src/window-lib/waylandcompositor.cpp
+++ b/src/window-lib/waylandcompositor.cpp
@@ -53,15 +53,16 @@
#include <QWaylandWlShell>
#include <QWaylandQuickOutput>
#include <QWaylandTextInputManager>
-#include <private/qwlextendedsurface_p.h>
#include <QWaylandQtWindowManager>
+#include "waylandqtamserverextension_p.h"
#include "waylandcompositor_p.h"
QT_BEGIN_NAMESPACE_AM
-WindowSurface::WindowSurface(QWaylandCompositor *comp, QWaylandClient *client, uint id, int version)
+WindowSurface::WindowSurface(WaylandCompositor *comp, QWaylandClient *client, uint id, int version)
: QWaylandQuickSurface(comp, client, id, version)
, m_surface(this)
+ , m_compositor(comp)
{ }
void WindowSurface::setShellSurface(QWaylandWlShellSurface *shellSurface)
@@ -72,20 +73,15 @@ void WindowSurface::setShellSurface(QWaylandWlShellSurface *shellSurface)
m_item = new WindowSurfaceQuickItem(this);
}
-void WindowSurface::setExtendedSurface(QtWayland::ExtendedSurface *extendedSurface)
-{
- m_extendedSurface = extendedSurface;
- if (m_extendedSurface) {
- connect(m_extendedSurface, &QtWayland::ExtendedSurface::windowPropertyChanged,
- this, &WindowSurface::windowPropertyChanged);
- }
-}
-
QWaylandWlShellSurface *WindowSurface::shellSurface() const
{
return m_shellSurface;
}
+WaylandCompositor *WindowSurface::compositor() const
+{
+ return m_compositor;
+}
QWaylandSurface *WindowSurface::surface() const
{
@@ -119,17 +115,6 @@ void WindowSurface::ping()
m_shellSurface->ping();
}
-QVariantMap WindowSurface::windowProperties() const
-{
- return m_extendedSurface ? m_extendedSurface->windowProperties() : QVariantMap();
-}
-
-void WindowSurface::setWindowProperty(const QString &name, const QVariant &value)
-{
- if (m_extendedSurface)
- m_extendedSurface->setWindowProperty(name, value);
-}
-
WindowSurfaceQuickItem::WindowSurfaceQuickItem(WindowSurface *windowSurface)
: QWaylandQuickItem()
@@ -159,7 +144,7 @@ void WindowSurfaceQuickItem::geometryChanged(const QRectF &newGeometry, const QR
WaylandCompositor::WaylandCompositor(QQuickWindow *window, const QString &waylandSocketName, WindowManager *manager)
: QWaylandQuickCompositor()
, m_shell(new QWaylandWlShell(this))
- , m_surfExt(new QtWayland::SurfaceExtensionGlobal(this))
+ , m_amExtension(new WaylandQtAMServerExtension(this))
, m_textInputManager(new QWaylandTextInputManager(this))
, m_manager(manager)
{
@@ -175,7 +160,6 @@ WaylandCompositor::WaylandCompositor(QQuickWindow *window, const QString &waylan
});
connect(m_shell, &QWaylandWlShell::wlShellSurfaceRequested, this, &WaylandCompositor::createShellSurface);
- connect(m_surfExt, &QtWayland::SurfaceExtensionGlobal::extendedSurfaceReady, this, &WaylandCompositor::extendedSurfaceReady);
auto wmext = new QWaylandQtWindowManager(this);
connect(wmext, &QWaylandQtWindowManager::openUrl, this, [](QWaylandClient *client, const QUrl &url) {
@@ -203,6 +187,10 @@ QWaylandSurface *WaylandCompositor::waylandSurfaceFromItem(QQuickItem *surfaceIt
return nullptr;
}
+WaylandQtAMServerExtension *WaylandCompositor::amExtension()
+{
+ return m_amExtension;
+}
void WaylandCompositor::doCreateSurface(QWaylandClient *client, uint id, int version)
{
@@ -223,10 +211,4 @@ void WaylandCompositor::createShellSurface(QWaylandSurface *surface, const QWayl
});
}
-void WaylandCompositor::extendedSurfaceReady(QtWayland::ExtendedSurface *ext, QWaylandSurface *surface)
-{
- WindowSurface *windowSurface = static_cast<WindowSurface *>(surface);
- windowSurface->setExtendedSurface(ext);
-}
-
QT_END_NAMESPACE_AM
diff --git a/src/window-lib/waylandcompositor.h b/src/window-lib/waylandcompositor.h
index bd864b8d..d8b3db09 100644
--- a/src/window-lib/waylandcompositor.h
+++ b/src/window-lib/waylandcompositor.h
@@ -56,15 +56,10 @@ QT_FORWARD_DECLARE_CLASS(QWaylandResource)
QT_FORWARD_DECLARE_CLASS(QWaylandWlShell)
QT_FORWARD_DECLARE_CLASS(QWaylandWlShellSurface)
QT_FORWARD_DECLARE_CLASS(QWaylandTextInputManager)
-QT_BEGIN_NAMESPACE
-namespace QtWayland {
-class ExtendedSurface;
-class SurfaceExtensionGlobal;
-}
-QT_END_NAMESPACE
QT_BEGIN_NAMESPACE_AM
+class WaylandQtAMServerExtension;
class WindowSurfaceQuickItem;
// A WindowSurface object exists for every Wayland surface created in the Wayland server.
@@ -75,17 +70,16 @@ class WindowSurface : public QWaylandQuickSurface
{
Q_OBJECT
public:
- WindowSurface(QWaylandCompositor *comp, QWaylandClient *client, uint id, int version);
+ WindowSurface(WaylandCompositor *comp, QWaylandClient *client, uint id, int version);
QWaylandWlShellSurface *shellSurface() const;
+ WaylandCompositor *compositor() const;
private:
void setShellSurface(QWaylandWlShellSurface *ss);
- void setExtendedSurface(QtWayland::ExtendedSurface *e);
private:
WindowSurfaceQuickItem *m_item = nullptr;
QWaylandWlShellSurface *m_shellSurface = nullptr;
- QtWayland::ExtendedSurface *m_extendedSurface = nullptr;
public:
QWaylandSurface *surface() const;
@@ -105,6 +99,7 @@ signals:
private:
QWaylandSurface *m_surface;
+ WaylandCompositor *m_compositor;
friend class WaylandCompositor;
};
@@ -116,14 +111,15 @@ public:
void registerOutputWindow(QQuickWindow *window);
QWaylandSurface *waylandSurfaceFromItem(QQuickItem *surfaceItem) const;
+ WaylandQtAMServerExtension *amExtension();
+
protected:
void doCreateSurface(QWaylandClient *client, uint id, int version);
void createShellSurface(QWaylandSurface *surface, const QWaylandResource &resource);
- void extendedSurfaceReady(QtWayland::ExtendedSurface *ext, QWaylandSurface *surface);
QWaylandWlShell *m_shell;
QVector<QWaylandOutput *> m_outputs;
- QtWayland::SurfaceExtensionGlobal *m_surfExt;
+ WaylandQtAMServerExtension *m_amExtension;
QWaylandTextInputManager *m_textInputManager;
private:
diff --git a/src/window-lib/waylandqtamserverextension.cpp b/src/window-lib/waylandqtamserverextension.cpp
new file mode 100644
index 00000000..1ab7e126
--- /dev/null
+++ b/src/window-lib/waylandqtamserverextension.cpp
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#include "waylandqtamserverextension_p.h"
+
+#include <QtWaylandCompositor/QWaylandCompositor>
+#include <QtWaylandCompositor/QWaylandResource>
+
+#include <QtAppManCommon/logging.h>
+
+QT_BEGIN_NAMESPACE_AM
+
+WaylandQtAMServerExtension::WaylandQtAMServerExtension(QWaylandCompositor *compositor)
+ : QWaylandCompositorExtensionTemplate(compositor)
+ , QtWaylandServer::qtam_extension(compositor->display(), 1)
+{ }
+
+QVariantMap WaylandQtAMServerExtension::windowProperties(const QWaylandSurface *surface) const
+{
+ return m_windowProperties.value(surface);
+}
+
+void WaylandQtAMServerExtension::setWindowProperty(QWaylandSurface *surface, const QString &name, const QVariant &value)
+{
+ if (setWindowPropertyHelper(surface, name, value)) {
+ QByteArray byteValue;
+ QDataStream ds(&byteValue, QIODevice::WriteOnly);
+ ds << value;
+
+ Resource *target = resourceMap().value(surface->waylandClient());
+ if (target) {
+ qDebug(LogWaylandDebug) << "SERVER >>prop>>" << surface << name << value;
+ send_window_property_changed(target->handle, surface->resource(), name, byteValue);
+ }
+ }
+}
+
+bool WaylandQtAMServerExtension::setWindowPropertyHelper(QWaylandSurface *surface, const QString &name, const QVariant &value)
+{
+ auto it = m_windowProperties.find(surface);
+ if ((it == m_windowProperties.end()) || (it.value().value(name) != value)) {
+ if (it == m_windowProperties.end())
+ m_windowProperties[surface].insert(name, value);
+ else
+ it.value().insert(name, value);
+ emit windowPropertyChanged(surface, name, value);
+ return true;
+ }
+ return false;
+}
+
+void WaylandQtAMServerExtension::qtam_extension_set_window_property(QtWaylandServer::qtam_extension::Resource *resource, wl_resource *surface_resource, const QString &name, wl_array *value)
+{
+ Q_UNUSED(resource);
+ QWaylandSurface *surface = QWaylandSurface::fromResource(surface_resource);
+ const QByteArray byteValue((const char *) value->data, value->size);
+ QDataStream ds(byteValue);
+ QVariant variantValue;
+ ds >> variantValue;
+
+ qCDebug(LogWaylandDebug) << "SERVER <<prop<<" << surface << name << variantValue;
+ setWindowPropertyHelper(surface, name, variantValue);
+}
+
+QT_END_NAMESPACE_AM
diff --git a/src/window-lib/waylandqtamserverextension_p.h b/src/window-lib/waylandqtamserverextension_p.h
new file mode 100644
index 00000000..28b3cfab
--- /dev/null
+++ b/src/window-lib/waylandqtamserverextension_p.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 Pelagicore AG
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Pelagicore Application Manager.
+**
+** $QT_BEGIN_LICENSE:LGPL-QTAS$
+** Commercial License Usage
+** Licensees holding valid commercial Qt Automotive Suite 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 Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+** SPDX-License-Identifier: LGPL-3.0
+**
+****************************************************************************/
+
+#pragma once
+
+#include <QtWaylandCompositor/QWaylandCompositorExtensionTemplate>
+#include "private/qwayland-server-qtam-extension.h"
+
+#include <QtAppManCommon/global.h>
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_FORWARD_DECLARE_CLASS(QWaylandCompositor)
+QT_FORWARD_DECLARE_CLASS(QWaylandSurface)
+
+QT_BEGIN_NAMESPACE_AM
+
+class WaylandQtAMServerExtension : public QWaylandCompositorExtensionTemplate<WaylandQtAMServerExtension>,
+ public ::QtWaylandServer::qtam_extension
+{
+ Q_OBJECT
+
+public:
+ WaylandQtAMServerExtension(QWaylandCompositor *compositor);
+
+ QVariantMap windowProperties(const QWaylandSurface *surface) const;
+ void setWindowProperty(QWaylandSurface *surface, const QString &name, const QVariant &value);
+
+signals:
+ void windowPropertyChanged(QWaylandSurface *surface, const QString &name, const QVariant &value);
+
+private:
+ bool setWindowPropertyHelper(QWaylandSurface *surface, const QString &name, const QVariant &value);
+ void qtam_extension_set_window_property(Resource *resource, wl_resource *surface_resource, const QString &name, wl_array *value) override;
+
+ QMap<const QWaylandSurface *, QVariantMap> m_windowProperties;
+};
+
+QT_END_NAMESPACE_AM
diff --git a/src/window-lib/waylandwindow.cpp b/src/window-lib/waylandwindow.cpp
index 9eba4ebc..a15c0323 100644
--- a/src/window-lib/waylandwindow.cpp
+++ b/src/window-lib/waylandwindow.cpp
@@ -48,6 +48,7 @@
#include "windowmanager.h"
#include "waylandwindow.h"
#include "waylandcompositor.h"
+#include "waylandqtamserverextension_p.h"
QT_BEGIN_NAMESPACE_AM
@@ -71,6 +72,12 @@ WaylandWindow::WaylandWindow(const Application *app, WindowSurface *surf)
m_pongTimer->setInterval(2000);
m_pongTimer->setSingleShot(true);
connect(m_pongTimer, &QTimer::timeout, this, &WaylandWindow::pongTimeout);
+
+ connect(surf->compositor()->amExtension(), &WaylandQtAMServerExtension::windowPropertyChanged,
+ this, [this](QWaylandSurface *surface, const QString &name, const QVariant &value) {
+ if (surface == m_surface)
+ emit windowPropertyChanged(name, value);
+ });
}
}
@@ -119,28 +126,19 @@ void WaylandWindow::pingTimeout()
bool WaylandWindow::setWindowProperty(const QString &name, const QVariant &value)
{
- if (m_surface) {
- QVariant oldValue = m_surface->windowProperties().value(name);
-
- if (oldValue != value)
- m_surface->setWindowProperty(name, value);
- return true;
- }
- return false;
+ if (m_surface)
+ m_surface->compositor()->amExtension()->setWindowProperty(m_surface, name, value);
+ return (m_surface);
}
QVariant WaylandWindow::windowProperty(const QString &name) const
{
- if (m_surface)
- return m_surface->windowProperties().value(name);
- return QVariant();
+ return windowProperties().value(name);
}
QVariantMap WaylandWindow::windowProperties() const
{
- if (m_surface)
- return m_surface->windowProperties();
- return QVariantMap();
+ return m_surface ? m_surface->compositor()->amExtension()->windowProperties(m_surface) : QVariantMap();
}
QT_END_NAMESPACE_AM
diff --git a/src/window-lib/window-lib.pro b/src/window-lib/window-lib.pro
index 6f5743e2..f11f1aa8 100644
--- a/src/window-lib/window-lib.pro
+++ b/src/window-lib/window-lib.pro
@@ -16,20 +16,24 @@ CONFIG *= static internal_module
multi-process:!headless {
HEADERS += \
waylandcompositor.h \
- waylandwindow.h
+ waylandwindow.h \
+ waylandqtamserverextension_p.h
SOURCES += \
waylandcompositor.cpp \
- waylandwindow.cpp
+ waylandwindow.cpp \
+ waylandqtamserverextension.cpp
qtHaveModule(waylandcompositor):qtHaveModule(waylandcompositor-private) {
QT *= waylandcompositor waylandcompositor-private
!osx:PKGCONFIG += wayland-server
HEADERS += waylandcompositor_p.h
- } else:qtHaveModule(compositor) {
- QT *= compositor
}
+ WAYLANDSERVERSOURCES += \
+ ../wayland-extensions/qtam-extension.xml
+
+ CONFIG *= wayland-scanner
}
!headless:HEADERS += \