diff options
author | Robert Griebl <robert.griebl@pelagicore.com> | 2018-03-28 16:12:54 +0200 |
---|---|---|
committer | Robert Griebl <robert.griebl@pelagicore.com> | 2018-04-04 13:33:52 +0000 |
commit | c0675368828969f3bfb5509f49a7c5368f0b8af3 (patch) | |
tree | 4eef821bbdbd9030c18c5263ee09963e8d89a6b7 | |
parent | b4b6adf4c0e915b399c02cb7b913f0bd3ff03ecc (diff) | |
download | qtapplicationmanager-c0675368828969f3bfb5509f49a7c5368f0b8af3.tar.gz |
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.exclude | 1 | ||||
-rw-r--r-- | src/common-lib/logging.cpp | 14 | ||||
-rw-r--r-- | src/common-lib/logging.h | 1 | ||||
-rw-r--r-- | src/launcher-lib/applicationmanagerwindow.cpp | 46 | ||||
-rw-r--r-- | src/launcher-lib/applicationmanagerwindow_p.h | 5 | ||||
-rw-r--r-- | src/launcher-lib/launcher-lib.pro | 12 | ||||
-rw-r--r-- | src/launcher-lib/launchermain.cpp | 35 | ||||
-rw-r--r-- | src/launcher-lib/launchermain.h | 13 | ||||
-rw-r--r-- | src/launcher-lib/waylandqtamclientextension.cpp | 148 | ||||
-rw-r--r-- | src/launcher-lib/waylandqtamclientextension_p.h | 94 | ||||
-rw-r--r-- | src/launchers/qml/main.cpp | 1 | ||||
-rw-r--r-- | src/wayland-extensions/qtam-extension.xml | 65 | ||||
-rw-r--r-- | src/window-lib/waylandcompositor.cpp | 42 | ||||
-rw-r--r-- | src/window-lib/waylandcompositor.h | 18 | ||||
-rw-r--r-- | src/window-lib/waylandqtamserverextension.cpp | 103 | ||||
-rw-r--r-- | src/window-lib/waylandqtamserverextension_p.h | 86 | ||||
-rw-r--r-- | src/window-lib/waylandwindow.cpp | 26 | ||||
-rw-r--r-- | src/window-lib/window-lib.pro | 12 |
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 += \ |