summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorRobert Griebl <robert.griebl@pelagicore.com>2017-12-06 12:43:08 +0100
committerDominik Holland <dominik.holland@pelagicore.com>2017-12-15 15:47:53 +0000
commit5fad90789b756ad8d6ec88db3ef71d354d0c7323 (patch)
treef894eb59441e35329a5985b88db584fa4f7f6d6c /src
parentc77ac0226c7f323bdb93fe214bc335a5d1e386cd (diff)
Refactor the interface between the AM and runtime launchers
* A lot of shared code was moved to the new shared-main library, making it easier to write custom runtime launchers * Simplified the qml runtime launcher * The new OpenGL versioning was extended to apps using the QML runtime * Settings are communicated to the apps as plain text YAML documents now, which makes it very easy to verify and extended this interface. Task-number: AUTOSUITE-162 Change-Id: I0c1be3ac2e38ab492e69182058098cf31d34484b Reviewed-by: Dominik Holland <dominik.holland@pelagicore.com>
Diffstat (limited to 'src')
-rw-r--r--src/application-lib/application.cpp8
-rw-r--r--src/application-lib/application.h4
-rw-r--r--src/application-lib/yamlapplicationscanner.cpp17
-rw-r--r--src/common-lib/logging.cpp12
-rw-r--r--src/common-lib/logging.h3
-rw-r--r--src/common-lib/qml-utilities.cpp28
-rw-r--r--src/common-lib/qml-utilities.h2
-rw-r--r--src/launcher-lib/launcher-lib.pro7
-rw-r--r--src/launcher-lib/launchermain.cpp174
-rw-r--r--src/launcher-lib/launchermain.h93
-rw-r--r--src/launchers/qml/main.cpp188
-rw-r--r--src/main-lib/defaultconfiguration.cpp16
-rw-r--r--src/main-lib/defaultconfiguration.h4
-rw-r--r--src/main-lib/main-lib.pro5
-rw-r--r--src/main-lib/main.cpp202
-rw-r--r--src/main-lib/main.h24
-rw-r--r--src/manager-lib/abstractruntime.cpp23
-rw-r--r--src/manager-lib/abstractruntime.h6
-rw-r--r--src/manager-lib/applicationmanager.cpp23
-rw-r--r--src/manager-lib/manager-lib.pro6
-rw-r--r--src/manager-lib/nativeruntime.cpp56
-rw-r--r--src/manager-lib/nativeruntime.h5
-rw-r--r--src/manager-lib/qmlinprocessruntime.cpp32
-rw-r--r--src/manager-lib/qmlinprocessruntime.h3
-rw-r--r--src/manager-lib/runtimefactory.cpp12
-rw-r--r--src/manager-lib/runtimefactory.h1
-rw-r--r--src/shared-main-lib/qmllogger.cpp (renamed from src/main-lib/qmllogger.cpp)0
-rw-r--r--src/shared-main-lib/qmllogger.h (renamed from src/main-lib/qmllogger.h)0
-rw-r--r--src/shared-main-lib/shared-main-lib.pro22
-rw-r--r--src/shared-main-lib/sharedmain.cpp246
-rw-r--r--src/shared-main-lib/sharedmain.h81
-rw-r--r--src/src.pro8
-rw-r--r--src/tools/appman/appman.pro4
33 files changed, 880 insertions, 435 deletions
diff --git a/src/application-lib/application.cpp b/src/application-lib/application.cpp
index 646f6cf5..8c5834d2 100644
--- a/src/application-lib/application.cpp
+++ b/src/application-lib/application.cpp
@@ -512,6 +512,11 @@ QString Application::version() const
return m_nonAliased ? m_nonAliased->m_version : m_version;
}
+QVariantMap Application::openGLConfiguration() const
+{
+ return m_nonAliased ? m_nonAliased->m_openGLConfiguration : m_openGLConfiguration;
+}
+
void Application::validate() const Q_DECL_NOEXCEPT_EXPR(false)
{
if (isAlias()) {
@@ -564,6 +569,7 @@ void Application::mergeInto(Application *app) const
app->m_mimeTypes = m_mimeTypes;
app->m_backgroundMode = m_backgroundMode;
app->m_version = m_version;
+ app->m_openGLConfiguration = m_openGLConfiguration;
emit app->bulkChange();
}
@@ -689,6 +695,7 @@ Application *Application::readFromDataStream(QDataStream &ds, const QVector<cons
>> app->m_mimeTypes
>> backgroundMode
>> app->m_version
+ >> app->m_openGLConfiguration
>> codeDir
>> manifestDir
>> app->m_uid
@@ -759,6 +766,7 @@ void Application::writeToDataStream(QDataStream &ds, const QVector<const Applica
<< m_mimeTypes
<< qint32(m_backgroundMode)
<< m_version
+ << m_openGLConfiguration
<< m_codeDir.absolutePath()
<< m_manifestDir.absolutePath()
<< m_uid
diff --git a/src/application-lib/application.h b/src/application-lib/application.h
index cfc09ac8..ff436952 100644
--- a/src/application-lib/application.h
+++ b/src/application-lib/application.h
@@ -131,6 +131,8 @@ public:
QString version() const;
+ QVariantMap openGLConfiguration() const;
+
void validate() const Q_DECL_NOEXCEPT_EXPR(false);
QVariantMap toVariantMap() const;
static Application *fromVariantMap(const QVariantMap &map, QString *error = 0);
@@ -208,6 +210,8 @@ private:
QString m_version;
+ QVariantMap m_openGLConfiguration;
+
// added by installer
QScopedPointer<InstallationReport> m_installationReport;
QDir m_manifestDir;
diff --git a/src/application-lib/yamlapplicationscanner.cpp b/src/application-lib/yamlapplicationscanner.cpp
index 11f26225..89d551d1 100644
--- a/src/application-lib/yamlapplicationscanner.cpp
+++ b/src/application-lib/yamlapplicationscanner.cpp
@@ -182,12 +182,12 @@ Application *YamlApplicationScanner::scanInternal(const QString &filePath, bool
{ "audio", Application::PlaysAudio },
{ "location", Application::TracksLocation },
{ "auto", Application::Auto },
- { 0, Application::Auto }
+ { nullptr, Application::Auto }
};
QByteArray enumValue = v.toString().toLatin1();
bool found = false;
- for (auto it = backgroundMap; backgroundMap->first; ++it) {
+ for (auto it = backgroundMap; it->first; ++it) {
if (enumValue == it->first) {
app->m_backgroundMode = it->second;
found = true;
@@ -196,6 +196,19 @@ Application *YamlApplicationScanner::scanInternal(const QString &filePath, bool
}
if (!found)
throw Exception(Error::Parse, "the 'backgroundMode' value '%1' is not valid").arg(enumValue);
+ } else if (field == "opengl") {
+ app->m_openGLConfiguration = v.toMap();
+
+ // sanity check
+ static QStringList validKeys = {
+ qSL("desktopProfile"),
+ qSL("esMajorVersion"),
+ qSL("esMinorVersion")
+ };
+ for (auto it = app->m_openGLConfiguration.cbegin(); it != app->m_openGLConfiguration.cend(); ++it) {
+ if (!validKeys.contains(it.key()))
+ throw Exception(Error::Parse, "the 'opengl' object contains the unsupported key '%1'").arg(it.key());
+ }
} else {
unknownField = true;
}
diff --git a/src/common-lib/logging.cpp b/src/common-lib/logging.cpp
index f4c7ecca..42af5482 100644
--- a/src/common-lib/logging.cpp
+++ b/src/common-lib/logging.cpp
@@ -105,6 +105,7 @@ bool Logging::s_dltEnabled =
false;
#endif
bool Logging::s_useDefaultQtHandler = false;
+QStringList Logging::s_rules;
QtMessageHandler Logging::s_defaultQtHandler = nullptr;
QByteArray Logging::s_applicationId = QByteArray();
@@ -303,6 +304,17 @@ void Logging::initialize()
s_defaultQtHandler = qInstallMessageHandler(messageHandler);
}
+QStringList Logging::filterRules()
+{
+ return s_rules;
+}
+
+void Logging::setFilterRules(const QStringList &rules)
+{
+ s_rules = rules;
+ QLoggingCategory::setFilterRules(rules.join(qL1C('\n')));
+}
+
QByteArray Logging::applicationId()
{
return s_applicationId;
diff --git a/src/common-lib/logging.h b/src/common-lib/logging.h
index 0f3b81a2..478cd234 100644
--- a/src/common-lib/logging.h
+++ b/src/common-lib/logging.h
@@ -58,6 +58,8 @@ class Logging
{
public:
static void initialize();
+ static QStringList filterRules();
+ static void setFilterRules(const QStringList &rules);
static QByteArray applicationId();
static void setApplicationId(const QByteArray &appId);
@@ -72,6 +74,7 @@ public:
private:
static bool s_dltEnabled;
static bool s_useDefaultQtHandler;
+ static QStringList s_rules;
static QtMessageHandler s_defaultQtHandler;
static QByteArray s_applicationId;
};
diff --git a/src/common-lib/qml-utilities.cpp b/src/common-lib/qml-utilities.cpp
index 5b5af432..53f3a069 100644
--- a/src/common-lib/qml-utilities.cpp
+++ b/src/common-lib/qml-utilities.cpp
@@ -40,9 +40,13 @@
****************************************************************************/
#include <QTimer>
+#include <QDir>
+#include <QQmlComponent>
+#include <QQmlContext>
#include <private/qqmlmetatype_p.h>
#include <private/qvariant_p.h>
+#include "logging.h"
#include "qml-utilities.h"
QT_BEGIN_NAMESPACE_AM
@@ -120,4 +124,28 @@ void retakeSingletonOwnershipFromQmlEngine(QQmlEngine *qmlEngine, QObject *singl
QTimer::singleShot(0, qmlEngine, retake);
}
+// copied straight from Qt 5.1.0 qmlscene/main.cpp for now - needs to be revised
+void loadQmlDummyDataFiles(QQmlEngine *engine, const QString &directory)
+{
+ QDir dir(directory + qSL("/dummydata"), qSL("*.qml"));
+ QStringList list = dir.entryList();
+ for (int i = 0; i < list.size(); ++i) {
+ QString qml = list.at(i);
+ QQmlComponent comp(engine, dir.filePath(qml));
+ QObject *dummyData = comp.create();
+
+ if (comp.isError()) {
+ const QList<QQmlError> errors = comp.errors();
+ for (const QQmlError &error : errors)
+ qCWarning(LogQml) << "Loading dummy data:" << error;
+ }
+
+ if (dummyData) {
+ qml.truncate(qml.length() - 4);
+ engine->rootContext()->setContextProperty(qml, dummyData);
+ dummyData->setParent(engine);
+ }
+ }
+}
+
QT_END_NAMESPACE_AM
diff --git a/src/common-lib/qml-utilities.h b/src/common-lib/qml-utilities.h
index 458a2da1..c657405e 100644
--- a/src/common-lib/qml-utilities.h
+++ b/src/common-lib/qml-utilities.h
@@ -53,4 +53,6 @@ void fixNullValuesForQml(QVariantMap &map);
void retakeSingletonOwnershipFromQmlEngine(QQmlEngine *qmlEngine, QObject *singleton, bool immediately = false);
+void loadQmlDummyDataFiles(QQmlEngine *engine, const QString &directory);
+
QT_END_NAMESPACE_AM
diff --git a/src/launcher-lib/launcher-lib.pro b/src/launcher-lib/launcher-lib.pro
index f5275cd6..fba6deac 100644
--- a/src/launcher-lib/launcher-lib.pro
+++ b/src/launcher-lib/launcher-lib.pro
@@ -8,6 +8,7 @@ QT = qml dbus core-private
!headless:QT += quick gui gui-private quick-private
QT_FOR_PRIVATE *= \
appman_common-private \
+ appman_shared_main-private \
appman_application-private \
appman_notification-private \
@@ -17,7 +18,8 @@ SOURCES += \
qmlapplicationinterface.cpp \
ipcwrapperobject.cpp \
qmlapplicationinterfaceextension.cpp \
- qmlnotification.cpp
+ qmlnotification.cpp \
+ launchermain.cpp
!headless:SOURCES += \
applicationmanagerwindow.cpp \
@@ -27,7 +29,8 @@ HEADERS += \
ipcwrapperobject.h \
ipcwrapperobject_p.h \
qmlapplicationinterfaceextension.h \
- qmlnotification.h
+ qmlnotification.h \
+ launchermain.h
!headless:HEADERS += \
applicationmanagerwindow_p.h
diff --git a/src/launcher-lib/launchermain.cpp b/src/launcher-lib/launchermain.cpp
new file mode 100644
index 00000000..8eb54002
--- /dev/null
+++ b/src/launcher-lib/launchermain.cpp
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 <QDBusConnection>
+
+#include <QtAppManCommon/exception.h>
+#include <QtAppManCommon/logging.h>
+#include <QtAppManCommon/utilities.h>
+#include <QtAppManCommon/crashhandler.h>
+#include <QtAppManCommon/exception.h>
+
+#include <QtAppManCommon/qtyaml.h>
+
+#include "launchermain.h"
+
+QT_BEGIN_NAMESPACE_AM
+
+LauncherMain::LauncherMain(int &argc, char **argv, const QByteArray &configYaml) Q_DECL_NOEXCEPT_EXPR(false)
+ : LauncherMainBase(SharedMain::preConstructor(argc), argv)
+ , SharedMain()
+{
+ auto docs = QtYaml::variantDocumentsFromYaml(configYaml.isEmpty() ? qgetenv("AM_CONFIG")
+ : configYaml);
+ if (docs.size() == 1)
+ m_configuration = docs.first().toMap();
+
+ m_baseDir = m_configuration.value(qSL("baseDir")).toString() + qL1C('/');
+ m_runtimeConfiguration = m_configuration.value(qSL("runtimeConfiguration")).toMap();
+ m_securityToken = QByteArray::fromHex(m_configuration.value(qSL("")).toString().toLatin1());
+ m_systemProperties = m_configuration.value(qSL("systemProperties")).toMap();
+
+ QVariantMap loggingConfig = m_configuration.value(qSL("logging")).toMap();
+ m_loggingRules = variantToStringList(loggingConfig.value(qSL("rules")));
+
+ QVariantMap dbusConfig = m_configuration.value(qSL("dbus")).toMap();
+ m_dbusAddressP2P = dbusConfig.value(qSL("p2p")).toString();
+ m_dbusAddressNotifications = dbusConfig.value(qSL("org.freedesktop.Notifications")).toString();
+
+ QVariantMap uiConfig = m_configuration.value(qSL("ui")).toMap();
+ m_slowAnimations = uiConfig.value(qSL("slowAnimations")).toBool();
+ m_openGLConfiguration = uiConfig.value(qSL("opengl")).toMap();
+
+ // un-comment this if things go south:
+ //qWarning() << "### LOG " << m_loggingRules;
+ //qWarning() << "### DBUS" << dbusConfig;
+ //qWarning() << "### UI " << uiConfig;
+ //qWarning() << "### RT " << m_runtimeConfiguration;
+ //qWarning() << "### SYSP" << m_systemProperties;
+ //qWarning() << "### GL " << m_openGLConfiguration;
+
+ // sanity checks
+ if (m_baseDir == qL1C('/'))
+ throw Exception("Runtime launcher received an empty baseDir");
+ if (loggingConfig.isEmpty())
+ throw Exception("Runtime launcher received no logging configuration");
+ if (dbusConfig.isEmpty())
+ throw Exception("Runtime launcher received no D-Bus configuration");
+}
+
+LauncherMain::~LauncherMain()
+{ }
+
+QString LauncherMain::baseDir() const
+{
+ return m_baseDir;
+}
+
+QVariantMap LauncherMain::runtimeConfiguration() const
+{
+ return m_runtimeConfiguration;
+}
+
+QByteArray LauncherMain::securityToken() const
+{
+ return m_securityToken;
+}
+
+bool LauncherMain::slowAnimations() const
+{
+ return m_slowAnimations;
+}
+
+QVariantMap LauncherMain::systemProperties() const
+{
+ return m_systemProperties;
+}
+
+QStringList LauncherMain::loggingRules() const
+{
+ return m_loggingRules;
+}
+
+QString LauncherMain::p2pDBusName() const
+{
+ return qSL("am");
+}
+
+QString LauncherMain::notificationDBusName() const
+{
+ return qSL("am_notification_bus");
+}
+
+QVariantMap LauncherMain::openGLConfiguration() const
+{
+ return m_openGLConfiguration;
+}
+
+void LauncherMain::setupDBusConnections() Q_DECL_NOEXCEPT_EXPR(false)
+{
+ if (m_dbusAddressP2P.isEmpty())
+ throw Exception("No address available to connect to the P2P D-Bus");
+
+ auto dbusConnection = QDBusConnection::connectToPeer(m_dbusAddressP2P, p2pDBusName());
+
+ if (!dbusConnection.isConnected())
+ throw Exception("could not connect to the P2P D-Bus via: %1").arg(m_dbusAddressP2P);
+
+ qCDebug(LogQmlRuntime) << "Connected to the P2P D-Bus via:" << m_dbusAddressP2P;
+
+ if (m_dbusAddressNotifications.isEmpty())
+ m_dbusAddressNotifications = qSL("session");
+
+ if (m_dbusAddressNotifications == qL1S("system"))
+ dbusConnection = QDBusConnection::connectToBus(QDBusConnection::SystemBus, notificationDBusName());
+ else if (m_dbusAddressNotifications == qL1S("session"))
+ dbusConnection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, notificationDBusName());
+ else
+ dbusConnection = QDBusConnection::connectToBus(m_dbusAddressNotifications, notificationDBusName());
+
+ if (!dbusConnection.isConnected())
+ throw Exception("could not connect to the Notification D-Bus via: %1").arg(m_dbusAddressNotifications);
+
+ qCDebug(LogQmlRuntime) << "Connected to the Notification D-Bus via:" << m_dbusAddressNotifications;
+}
+
+QT_END_NAMESPACE_AM
diff --git a/src/launcher-lib/launchermain.h b/src/launcher-lib/launchermain.h
new file mode 100644
index 00000000..69684dab
--- /dev/null
+++ b/src/launcher-lib/launchermain.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 <QtAppManCommon/global.h>
+#include <QtAppManSharedMain/sharedmain.h>
+
+#if defined(AM_HEADLESS)
+# include <QCoreApplication>
+typedef QCoreApplication LauncherMainBase;
+#else
+# include <QGuiApplication>
+typedef QGuiApplication LauncherMainBase;
+#endif
+
+
+QT_BEGIN_NAMESPACE_AM
+
+class LauncherMain : public LauncherMainBase, public SharedMain
+{
+ Q_OBJECT
+public:
+ LauncherMain(int &argc, char **argv, const QByteArray &configYaml = QByteArray()) Q_DECL_NOEXCEPT_EXPR(false);
+ ~LauncherMain();
+
+public:
+ void setupDBusConnections() Q_DECL_NOEXCEPT_EXPR(false);
+
+ QString baseDir() const;
+ QVariantMap runtimeConfiguration() const;
+ QByteArray securityToken() const;
+ bool slowAnimations() const;
+ QVariantMap systemProperties() const;
+ QStringList loggingRules() const;
+
+ QString p2pDBusName() const;
+ QString notificationDBusName() const;
+
+ QVariantMap openGLConfiguration() const;
+
+private:
+ QVariantMap m_configuration;
+ QString m_baseDir;
+ QVariantMap m_runtimeConfiguration;
+ QByteArray m_securityToken;
+ bool m_slowAnimations = false;
+ QVariantMap m_systemProperties;
+ QStringList m_loggingRules;
+ QString m_dbusAddressP2P;
+ QString m_dbusAddressNotifications;
+ QVariantMap m_openGLConfiguration;
+};
+
+QT_END_NAMESPACE_AM
diff --git a/src/launchers/qml/main.cpp b/src/launchers/qml/main.cpp
index c996436d..d168db8c 100644
--- a/src/launchers/qml/main.cpp
+++ b/src/launchers/qml/main.cpp
@@ -64,6 +64,8 @@
#include <private/qabstractanimation_p.h> // For QUnifiedTimer
#include <qplatformdefs.h>
+#include <QtAppManLauncher/launchermain.h>
+
#if !defined(AM_HEADLESS)
# include <QGuiApplication>
# include <QQuickItem>
@@ -91,6 +93,7 @@
#include "dbus-utilities.h"
#include "startuptimer.h"
#include "processtitle.h"
+#include "qml-utilities.h"
QT_BEGIN_NAMESPACE_AM
@@ -113,36 +116,12 @@ protected:
-// copied straight from Qt 5.1.0 qmlscene/main.cpp for now - needs to be revised
-static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory)
-{
- QDir dir(directory + qSL("/dummydata"), qSL("*.qml"));
- QStringList list = dir.entryList();
- for (int i = 0; i < list.size(); ++i) {
- QString qml = list.at(i);
- QQmlComponent comp(&engine, dir.filePath(qml));
- QObject *dummyData = comp.create();
-
- if (comp.isError()) {
- const QList<QQmlError> errors = comp.errors();
- for (const QQmlError &error : errors)
- qWarning() << error;
- }
-
- if (dummyData) {
- qml.truncate(qml.length()-4);
- engine.rootContext()->setContextProperty(qml, dummyData);
- dummyData->setParent(&engine);
- }
- }
-}
-
class Controller : public QObject
{
Q_OBJECT
public:
- Controller(QCoreApplication *a, bool quickLaunched, const QString &directLoad = QString());
+ Controller(LauncherMain *a, bool quickLaunched, const QString &directLoad = QString());
public slots:
void startApplication(const QString &baseDir, const QString &qmlFile, const QString &document,
@@ -161,13 +140,6 @@ private slots:
#endif
};
-static QString p2pBusName = qSL("am");
-static QString notificationBusName = qSL("am_notification_bus");
-static QCommandLineParser cp;
-static QCommandLineOption qmlDebugOption(qSL("qml-debug"), qSL("Enables QML debugging and profiling."));
-static QCommandLineOption quickLaunchOption(qSL("quicklaunch"), qSL("Starts the launcher in the quicklaunching mode."));
-static QCommandLineOption directLoadOption(qSL("directload") , qSL("The info.yaml to start."), qSL("info.yaml"));
-
QT_END_NAMESPACE_AM
@@ -178,6 +150,11 @@ int main(int argc, char *argv[])
{
StartupTimer::instance()->checkpoint("entered main");
+ QCoreApplication::setApplicationName(qSL("ApplicationManager QML Launcher"));
+ QCoreApplication::setOrganizationName(qSL("Pelagicore AG"));
+ QCoreApplication::setOrganizationDomain(qSL("pelagicore.com"));
+ QCoreApplication::setApplicationVersion(qSL(AM_VERSION));
+
if (qEnvironmentVariableIsSet("AM_NO_DLT_LOGGING"))
Logging::setDltEnabled(false);
@@ -191,114 +168,68 @@ int main(int argc, char *argv[])
Logging::setApplicationId("qml-launcher");
Logging::initialize();
- QLoggingCategory::setFilterRules(QString::fromUtf8(qgetenv("AM_LOGGING_RULES")));
+ try {
+ LauncherMain a(argc, argv);
-#if defined(AM_HEADLESS)
- QCoreApplication a(argc, argv);
-#else
- // this is needed for WebEngine
- QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
-
- QGuiApplication a(argc, argv);
- a.setApplicationDisplayName(qL1S("appman-launcher-qml"));
- cp.addHelpOption();
- cp.addOption(directLoadOption);
- cp.addOption(qmlDebugOption);
- cp.addOption(quickLaunchOption);
-
- cp.process(a);
-
- if (!static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(&a))->qmljsDebugArgumentsString().isEmpty()
- || cp.isSet(qmlDebugOption)) {
-#if !defined(QT_NO_QML_DEBUGGER)
- (void) new QQmlDebuggingEnabler(true);
- if (!QLoggingCategory::defaultCategory()->isDebugEnabled()) {
- qCCritical(LogQmlRuntime) << "The default 'debug' logging category was disabled. "
- "Re-enabling it for the QML Debugger interface to work correctly.";
- QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
- }
-#else
- qCWarning(LogQmlRuntime) << "The --qml-debug/-qmljsdebugger options are ignored, because Qt was built without support for QML Debugging!";
-#endif
- }
-
- qmlRegisterType<ApplicationManagerWindow>("QtApplicationManager", 1, 0, "ApplicationManagerWindow");
-#endif
-
- qmlRegisterType<QmlNotification>("QtApplicationManager", 1, 0, "Notification");
- qmlRegisterType<QmlApplicationInterfaceExtension>("QtApplicationManager", 1, 0, "ApplicationInterfaceExtension");
+ QCommandLineParser clp;
+ clp.addHelpOption();
+ clp.addOption({ qSL("qml-debug"), qSL("Enables QML debugging and profiling.") });
+ clp.addOption({ qSL("quicklaunch"), qSL("Starts the launcher in the quicklaunching mode.") });
+ clp.addOption({ qSL("directload") , qSL("The info.yaml to start."), qSL("info.yaml") });
+ clp.process(a);
- StartupTimer::instance()->checkpoint("after logging and qml register initialization");
+ CrashHandler::setCrashActionConfiguration(a.runtimeConfiguration().value(qSL("crashAction")).toMap());
+ a.setupLoggingRules(false, a.loggingRules()); // the verbose flag has already been factored into the rules
+ bool hasJSDebugArg = !static_cast<QCoreApplicationPrivate *>(QObjectPrivate::get(&a))->qmljsDebugArgumentsString().isEmpty();
+ a.setupQmlDebugging(hasJSDebugArg || clp.isSet(qSL("qml-debug")));
+ a.setupOpenGL(a.openGLConfiguration());
- if (cp.isSet(directLoadOption)) {
- QFileInfo fi = cp.value(directLoadOption);
+ StartupTimer::instance()->checkpoint("after basic initialization");
- if (!fi.exists() || fi.fileName() != qSL("info.yaml")) {
- qCCritical(LogQmlRuntime) << "ERROR: --directload needs a valid info.yaml file as parameter";
- return 2;
- }
-
- new Controller(&a, cp.isSet(quickLaunchOption), fi.absoluteFilePath());
- } else {
- QByteArray dbusAddress = qgetenv("AM_DBUS_PEER_ADDRESS");
- if (dbusAddress.isEmpty()) {
- qCCritical(LogQmlRuntime) << "ERROR: $AM_DBUS_PEER_ADDRESS is empty";
- return 2;
- }
- QDBusConnection dbusConnection = QDBusConnection::connectToPeer(QString::fromUtf8(dbusAddress), p2pBusName);
-
- if (!dbusConnection.isConnected()) {
- qCCritical(LogQmlRuntime) << "ERROR: could not connect to the P2P D-Bus via:" << dbusAddress;
- return 3;
- }
- qCDebug(LogQmlRuntime) << "Connected to the P2P D-Bus via:" << dbusAddress;
-
- dbusAddress = qgetenv("AM_DBUS_NOTIFICATION_BUS_ADDRESS");
- if (dbusAddress.isEmpty())
- dbusAddress = "session";
-
- if (dbusAddress == "system")
- dbusConnection = QDBusConnection::connectToBus(QDBusConnection::SystemBus, notificationBusName);
- else if (dbusAddress == "session")
- dbusConnection = QDBusConnection::connectToBus(QDBusConnection::SessionBus, notificationBusName);
- else
- dbusConnection = QDBusConnection::connectToBus(QString::fromUtf8(dbusAddress), notificationBusName);
-
- if (!dbusConnection.isConnected()) {
- qCCritical(LogQmlRuntime) << "ERROR: could not connect to the Notification D-Bus via:" << dbusAddress;
- return 3;
+ bool quicklaunched = clp.isSet(qSL("quicklaunch"));
+ QString directLoad = clp.value(qSL("directload"));
+ if (!directLoad.isEmpty()) {
+ QFileInfo fi(directLoad);
+ if (!fi.exists() || fi.fileName() != qSL("info.yaml")) {
+ throw Exception("--directload needs a valid info.yaml file as parameter");
+ return 2;
+ }
+ directLoad = fi.absoluteFilePath();
+ } else {
+ a.setupDBusConnections();
+ StartupTimer::instance()->checkpoint("after dbus initialization");
}
- qCDebug(LogQmlRuntime) << "Connected to the Notification D-Bus via:" << dbusAddress;
- StartupTimer::instance()->checkpoint("after dbus initialization");
+ new Controller(&a, quicklaunched, directLoad);
+ return a.exec();
- new Controller(&a, cp.isSet(quickLaunchOption));
+ } catch (const std::exception &e) {
+ qCCritical(LogQmlRuntime) << "ERROR:" << e.what();
+ return 2;
}
-
- return a.exec();
}
-Controller::Controller(QCoreApplication *a, bool quickLaunched, const QString &directLoad)
+Controller::Controller(LauncherMain *a, bool quickLaunched, const QString &directLoad)
: QObject(a)
, m_quickLaunched(quickLaunched)
{
- connect(&m_engine, &QObject::destroyed, &QCoreApplication::quit);
- connect(&m_engine, &QQmlEngine::quit, &QCoreApplication::quit);
+ connect(&m_engine, &QObject::destroyed, a, &QCoreApplication::quit);
+ connect(&m_engine, &QQmlEngine::quit, a, &QCoreApplication::quit);
- auto docs = QtYaml::variantDocumentsFromYaml(qgetenv("AM_RUNTIME_CONFIGURATION"));
- if (docs.size() == 1)
- m_configuration = docs.first().toMap();
-
- CrashHandler::setCrashActionConfiguration(m_configuration.value(qSL("crashAction")).toMap());
+#if !defined(AM_HEADLESS)
+ qmlRegisterType<ApplicationManagerWindow>("QtApplicationManager", 1, 0, "ApplicationManagerWindow");
+#endif
+ qmlRegisterType<QmlNotification>("QtApplicationManager", 1, 0, "Notification");
+ qmlRegisterType<QmlApplicationInterfaceExtension>("QtApplicationManager", 1, 0, "ApplicationInterfaceExtension");
- const QString baseDir = QString::fromLocal8Bit(qgetenv("AM_BASE_DIR") + "/");
+ m_configuration = a->runtimeConfiguration();
QStringList importPaths = variantToStringList(m_configuration.value(qSL("importPaths")));
for (QString &path : importPaths) {
if (QFileInfo(path).isRelative()) {
- path.prepend(baseDir);
+ path.prepend(a->baseDir());
} else {
- qCWarning(LogQmlRuntime) << "Absolute import path in config file can lead to problems inside containers:"
+ qCWarning(LogQmlRuntime) << "Absolute import paths in the runtime configuration can lead to problems inside containers:"
<< path;
}
m_engine.addImportPath(path);
@@ -321,9 +252,9 @@ Controller::Controller(QCoreApplication *a, bool quickLaunched, const QString &d
StartupTimer::instance()->checkpoint("after window registration");
QString quicklaunchQml = m_configuration.value((qSL("quicklaunchQml"))).toString();
- if (!quicklaunchQml.isEmpty() && cp.isSet(quickLaunchOption)) {
+ if (!quicklaunchQml.isEmpty() && quickLaunched) {
if (QFileInfo(quicklaunchQml).isRelative())
- quicklaunchQml.prepend(baseDir);
+ quicklaunchQml.prepend(a->baseDir());
QQmlComponent quicklaunchComp(&m_engine, quicklaunchQml);
if (!quicklaunchComp.isError()) {
@@ -337,13 +268,11 @@ Controller::Controller(QCoreApplication *a, bool quickLaunched, const QString &d
}
if (directLoad.isEmpty()) {
- m_applicationInterface = new QmlApplicationInterface(p2pBusName, notificationBusName, this);
+ m_applicationInterface = new QmlApplicationInterface(a->p2pDBusName(), a->notificationDBusName(), this);
connect(m_applicationInterface, &QmlApplicationInterface::startApplication,
this, &Controller::startApplication);
- if (!m_applicationInterface->initialize()) {
- qCritical("ERROR: could not connect to the application manager's interface on the peer D-Bus");
- qApp->exit(4);
- }
+ if (!m_applicationInterface->initialize())
+ throw Exception("Could not connect to the application manager's interface on the peer D-Bus");
} else {
QTimer::singleShot(0, [this, directLoad]() {
QFileInfo fi(directLoad);
@@ -352,8 +281,7 @@ Controller::Controller(QCoreApplication *a, bool quickLaunched, const QString &d
const Application *a = yas.scan(directLoad);
startApplication(fi.absolutePath(), a->codeFilePath(), QString(), QString(), a->toVariantMap(), QVariantMap());
} catch (const Exception &e) {
- qCritical("ERROR: could not parse info.yaml file: %s", e.what());
- qApp->exit(5);
+ throw Exception("Could not parse info.yaml file: %1").arg(e.what());
}
});
}
@@ -456,7 +384,7 @@ void Controller::startApplication(const QString &baseDir, const QString &qmlFile
if (loadDummyData) {
qCDebug(LogQmlRuntime) << "loading dummy-data";
- loadDummyDataFiles(m_engine, QFileInfo(qmlFile).path());
+ loadQmlDummyDataFiles(&m_engine, QFileInfo(qmlFile).path());
}
QVariant imports = runtimeParameters.value(qSL("importPaths"));
diff --git a/src/main-lib/defaultconfiguration.cpp b/src/main-lib/defaultconfiguration.cpp
index 8384c095..91a5278d 100644
--- a/src/main-lib/defaultconfiguration.cpp
+++ b/src/main-lib/defaultconfiguration.cpp
@@ -258,21 +258,9 @@ bool DefaultConfiguration::enableTouchEmulation() const
return value<bool>("enable-touch-emulation", { "ui", "enableTouchEmulation" });
}
-QString DefaultConfiguration::openGLESProfile() const
+QVariantMap DefaultConfiguration::openGLConfiguration() const
{
- return value<QString>(nullptr, { "ui", "opengl", "desktopProfile" });
-}
-
-int DefaultConfiguration::openGLESVersionMajor() const
-{
- auto v = value<QVariant>(nullptr, { "ui", "opengl", "esMajorVersion" });
- return v.isValid() ? v.toInt() : -1;
-}
-
-int DefaultConfiguration::openGLESVersionMinor() const
-{
- auto v = value<QVariant>(nullptr, { "ui", "opengl", "esMinorVersion" });
- return v.isValid() ? v.toInt() : -1;
+ return value<QVariant>(nullptr, { "ui", "opengl" }).toMap();
}
QVariantList DefaultConfiguration::installationLocations() const
diff --git a/src/main-lib/defaultconfiguration.h b/src/main-lib/defaultconfiguration.h
index 405204c0..d7c4b1e7 100644
--- a/src/main-lib/defaultconfiguration.h
+++ b/src/main-lib/defaultconfiguration.h
@@ -85,9 +85,7 @@ public:
QString style() const;
bool enableTouchEmulation() const;
- QString openGLESProfile() const;
- int openGLESVersionMajor() const;
- int openGLESVersionMinor() const;
+ QVariantMap openGLConfiguration() const;
QVariantList installationLocations() const;
diff --git a/src/main-lib/main-lib.pro b/src/main-lib/main-lib.pro
index 9006e6ed..0211e242 100644
--- a/src/main-lib/main-lib.pro
+++ b/src/main-lib/main-lib.pro
@@ -6,7 +6,7 @@ load(am-config)
QT = core network qml core-private
enable-widgets:QT *= widgets
-!headless:QT *= gui gui-private quick
+!headless:QT *= gui quick
qtHaveModule(pssdp):QT *= pssdp
qtHaveModule(pshellserver):QT *= pshellserver
QT *= \
@@ -17,6 +17,7 @@ QT *= \
appman_installer-private \
appman_notification-private \
appman_monitor-private \
+ appman_shared_main-private \
!headless:QT *= appman_window-private
!disable-external-dbus-interfaces:qtHaveModule(dbus):QT *= dbus appman_dbus-private
@@ -28,14 +29,12 @@ win32:LIBS += -luser32
DEFINES += AM_BUILD_DIR=\\\"$$BUILD_DIR\\\"
HEADERS += \
- $$PWD/qmllogger.h \
$$PWD/configuration.h \
$$PWD/main.h \
$$PWD/defaultconfiguration.h
SOURCES += \
$$PWD/main.cpp \
- $$PWD/qmllogger.cpp \
$$PWD/configuration.cpp \
$$PWD/defaultconfiguration.cpp
diff --git a/src/main-lib/main.cpp b/src/main-lib/main.cpp
index 998ec8ad..22cbf951 100644
--- a/src/main-lib/main.cpp
+++ b/src/main-lib/main.cpp
@@ -138,44 +138,11 @@
QT_BEGIN_NAMESPACE_AM
-#if !defined(AM_HEADLESS)
-static QMap<int, QString> openGLProfileNames = {
- { QSurfaceFormat::NoProfile, qSL("default") },
- { QSurfaceFormat::CoreProfile, qSL("core") },
- { QSurfaceFormat::CompatibilityProfile, qSL("compatibility") }
-};
-#endif
-
-// We need to do some things BEFORE the Q*Application constructor runs, so we're using this
-// old trick to do this hooking transparently for the user of the class.
-int &Main::preConstructor(int &argc)
-{
-#if !defined(AM_HEADLESS)
-# if !defined(QT_NO_SESSIONMANAGER)
- QGuiApplication::setFallbackSessionManagementEnabled(false);
-# endif
-
- // this is needed for both WebEngine and Wayland Multi-screen rendering
- QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
-
- // Calling this semi-private function before the QGuiApplication constructor is the only way to
- // set a custom global shared GL context. We are NOT creating it right now, since we still need
- // to parse the requested format from the config files - the creation is completed later
- // in setupOpenGL().
- qt_gl_set_global_share_context(new QOpenGLContext());
-
-# if defined(Q_OS_UNIX) && defined(AM_MULTI_PROCESS)
- // set a reasonable default for OSes/distros that do not set this by default
- setenv("XDG_RUNTIME_DIR", "/tmp", 0);
-# endif
-#endif
- return argc;
-}
-
// The QGuiApplication constructor
Main::Main(int &argc, char **argv)
- : MainBase(preConstructor(argc), argv)
+ : MainBase(SharedMain::preConstructor(argc), argv)
+ , SharedMain()
{
// this might be needed later on by the native runtime to find a suitable qml runtime launcher
setProperty("_am_build_dir", qSL(AM_BUILD_DIR));
@@ -221,7 +188,6 @@ Main::~Main()
delete m_quickLauncher;
delete m_systemMonitor;
delete m_applicationIPCManager;
- delete m_debuggingEnabler;
}
/*! \internal
@@ -239,7 +205,7 @@ void Main::setup(const DefaultConfiguration *cfg) Q_DECL_NOEXCEPT_EXPR(false)
setupLoggingRules(cfg->verbose(), cfg->loggingRules());
setupQmlDebugging(cfg->qmlDebugging());
Logging::registerUnregisteredDltContexts();
- setupOpenGL(cfg->openGLESProfile(), cfg->openGLESVersionMajor(), cfg->openGLESVersionMinor());
+ setupOpenGL(cfg->openGLConfiguration());
loadStartupPlugins(cfg->pluginFilePaths("startup"));
parseSystemProperties(cfg->rawSystemProperties());
@@ -252,8 +218,8 @@ void Main::setup(const DefaultConfiguration *cfg) Q_DECL_NOEXCEPT_EXPR(false)
setMainQmlFile(cfg->mainQmlFile());
setupSingleOrMultiProcess(cfg->forceSingleProcess(), cfg->forceMultiProcess());
- setupRuntimesAndContainers(cfg->runtimeConfigurations(), cfg->containerConfigurations(),
- cfg->pluginFilePaths("container"));
+ setupRuntimesAndContainers(cfg->runtimeConfigurations(), cfg->openGLConfiguration(),
+ cfg->containerConfigurations(), cfg->pluginFilePaths("container"));
setupInstallationLocations(cfg->installationLocations());
loadApplicationDatabase(cfg->database(), cfg->recreateDatabase(), cfg->singleApp());
setupSingletons(cfg->containerSelectionConfiguration(), cfg->quickLaunchRuntimesPerContainer(),
@@ -318,133 +284,6 @@ QQmlApplicationEngine *Main::qmlEngine() const
return m_engine;
}
-void Main::setupQmlDebugging(bool qmlDebugging)
-{
- if (qmlDebugging) {
-#if !defined(QT_NO_QML_DEBUGGER)
- m_debuggingEnabler = new QQmlDebuggingEnabler(true);
- if (!QLoggingCategory::defaultCategory()->isDebugEnabled()) {
- qCCritical(LogQmlRuntime) << "The default 'debug' logging category was disabled. "
- "Re-enabling it for the QML Debugger interface to work correctly.";
- QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
- }
-#else
- qCWarning(LogSystem) << "The --qml-debug option is ignored, because Qt was built without support for QML Debugging!";
-#endif
- }
-}
-
-void Main::setupLoggingRules(bool verbose, const QStringList &loggingRules)
-{
- const QString rules = verbose ? qSL("*=true\nqt.*.debug=false")
- : loggingRules.isEmpty() ? qSL("*.debug=false")
- : loggingRules.join(qL1C('\n'));
-
- QLoggingCategory::setFilterRules(rules);
-
- // setting this for child processes //TODO: use a more generic IPC approach
- qputenv("AM_LOGGING_RULES", rules.toUtf8());
- StartupTimer::instance()->checkpoint("after logging setup");
-}
-
-void Main::setupOpenGL(const QString &profileName, int majorVersion, int minorVersion)
-{
-#if !defined(AM_HEADLESS)
- QOpenGLContext *globalContext = qt_gl_global_share_context();
- QSurfaceFormat format = QSurfaceFormat::defaultFormat();
- bool isES = (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES);
-
- // either both are set or none is set
- if ((majorVersion > -1) != (minorVersion > -1)) {
- qCWarning(LogGraphics) << "Requesting only the major or minor OpenGL version number is not "
- "supported - always specify both or none.";
- } else if (majorVersion > -1) {
- bool valid = isES;
-
- if (!isES) {
- // we need to map the ES version to the corresponding desktop versions:
- static int mapping[] = {
- 2, 0, 2, 1,
- 3, 0, 4, 3,
- 3, 1, 4, 5,
- 3, 2, 4, 6,
- -1
- };
- for (int i = 0; mapping[i] != -1; i += 4) {
- if ((majorVersion == mapping[i]) && (minorVersion == mapping[i + 1])) {
- majorVersion = mapping[i + 2];
- minorVersion = mapping[i + 3];
- valid = true;
- break;
- }
- }
- if (!valid) {
- qCWarning(LogGraphics).nospace() << "Requested OpenGLES version " << majorVersion
- << "." << minorVersion
- << ", but there is no mapping available to a corresponding desktop GL version.";
- }
- }
-
- if (valid) {
- format.setMajorVersion(majorVersion);
- format.setMinorVersion(minorVersion);
- m_requestedOpenGLMajorVersion = majorVersion;
- m_requestedOpenGLMinorVersion = minorVersion;
- qCDebug(LogGraphics).nospace() << "Requested OpenGL" << (isES ? "ES" : "") << " version "
- << majorVersion << "." << minorVersion;
- }
- }
- if (!profileName.isEmpty()) {
- int profile = openGLProfileNames.key(profileName, -1);
-
- if (profile == -1) {
- qCWarning(LogGraphics) << "Requested an invalid OpenGL profile:" << profileName;
- } else if (profile != QSurfaceFormat::NoProfile) {
- m_requestedOpenGLProfile = (QSurfaceFormat::OpenGLContextProfile) profile;
- format.setProfile(m_requestedOpenGLProfile);
- qCDebug(LogGraphics) << "Requested OpenGL profile" << profileName;
- }
- }
- if ((m_requestedOpenGLProfile != QSurfaceFormat::NoProfile) || (m_requestedOpenGLMajorVersion > -1))
- QSurfaceFormat::setDefaultFormat(format);
-
- // Setting the screen is normally done by the QOpenGLContext constructor, but our constructor
- // ran before the QGuiApplication constructor, so the screen was not initialized yet. So we have
- // to tell the context about the screen again now:
- globalContext->setScreen(QGuiApplication::primaryScreen());
-
- if (!globalContext->create())
- throw Exception("Failed to create the global shared OpenGL context.");
-
- // check if we got what we requested on the OpenGL side
- checkOpenGLFormat("global shared context", globalContext->format());
-#endif
-}
-
-#if !defined(AM_HEADLESS)
-void Main::checkOpenGLFormat(const char *what, const QSurfaceFormat &format) const
-{
- if ((m_requestedOpenGLProfile != QSurfaceFormat::NoProfile)
- && (format.profile() != m_requestedOpenGLProfile)) {
- qCWarning(LogGraphics) << "Failed to get the requested OpenGL profile"
- << openGLProfileNames.value(m_requestedOpenGLProfile) << "for the"
- << what << "- got"
- << openGLProfileNames.value(format.profile()) << "instead.";
- }
- if (m_requestedOpenGLMajorVersion > -1) {
- if ((format.majorVersion() != m_requestedOpenGLMajorVersion )
- || (format.minorVersion() != m_requestedOpenGLMinorVersion)) {
- qCWarning(LogGraphics).nospace() << "Failed to get the requested OpenGL version "
- << m_requestedOpenGLMajorVersion << "."
- << m_requestedOpenGLMinorVersion << " for "
- << what << " - got "
- << format.majorVersion() << "."
- << format.minorVersion() << " instead";
- }
- }
-}
-#endif
-
void Main::loadStartupPlugins(const QStringList &startupPluginPaths) Q_DECL_NOEXCEPT_EXPR(false)
{
m_startupPlugins = loadPlugins<StartupInterface>("startup", startupPluginPaths);
@@ -515,7 +354,8 @@ void Main::setupSingleOrMultiProcess(bool forceSingleProcess, bool forceMultiPro
#endif
}
-void Main::setupRuntimesAndContainers(const QVariantMap &runtimeConfigurations, const QVariantMap &containerConfigurations, const QStringList &containerPluginPaths)
+void Main::setupRuntimesAndContainers(const QVariantMap &runtimeConfigurations, const QVariantMap &openGLConfiguration,
+ const QVariantMap &containerConfigurations, const QStringList &containerPluginPaths)
{
if (m_isSingleProcessMode) {
RuntimeFactory::instance()->registerRuntime(new QmlInProcessRuntimeManager());
@@ -539,7 +379,7 @@ void Main::setupRuntimesAndContainers(const QVariantMap &runtimeConfigurations,
ContainerFactory::instance()->setConfiguration(containerConfigurations);
RuntimeFactory::instance()->setConfiguration(runtimeConfigurations);
-
+ RuntimeFactory::instance()->setSystemOpenGLConfiguration(openGLConfiguration);
RuntimeFactory::instance()->setSystemProperties(m_systemProperties.at(SP_ThirdParty),
m_systemProperties.at(SP_BuiltIn));
@@ -782,7 +622,7 @@ void Main::loadQml(bool loadDummyData) Q_DECL_NOEXCEPT_EXPR(false)
if (m_mainQmlLocalFile.isEmpty()) {
qCDebug(LogQml) << "Not loading QML dummy data on non-local URL" << m_mainQml;
} else {
- loadDummyDataFiles(QFileInfo(m_mainQmlLocalFile).path());
+ loadQmlDummyDataFiles(m_engine, QFileInfo(m_mainQmlLocalFile).path());
StartupTimer::instance()->checkpoint("after loading dummy-data");
}
}
@@ -1057,30 +897,6 @@ void Main::registerDBusInterfaces(const std::function<QString(const char *)> &bu
#endif // defined(QT_DBUS_LIB) && !defined(AM_DISABLE_EXTERNAL_DBUS_INTERFACES)
}
-// copied straight from Qt 5.1.0 qmlscene/main.cpp for now - needs to be revised
-void Main::loadDummyDataFiles(const QString &directory)
-{
- QDir dir(directory + qSL("/dummydata"), qSL("*.qml"));
- QStringList list = dir.entryList();
- for (int i = 0; i < list.size(); ++i) {
- QString qml = list.at(i);
- QQmlComponent comp(m_engine, dir.filePath(qml));
- QObject *dummyData = comp.create();
-
- if (comp.isError()) {
- const QList<QQmlError> errors = comp.errors();
- for (const QQmlError &error : errors)
- qWarning() << error;
- }
-
- if (dummyData) {
- qWarning() << "Loaded dummy data:" << dir.filePath(qml);
- qml.truncate(qml.length()-4);
- m_engine->rootContext()->setContextProperty(qml, dummyData);
- dummyData->setParent(m_engine);
- }
- }
-}
QVector<const Application *> Main::scanForApplication(const QString &singleAppInfoYaml, const QStringList &builtinAppsDirs) Q_DECL_NOEXCEPT_EXPR(false)
{
diff --git a/src/main-lib/main.h b/src/main-lib/main.h
index a2c13269..8e433370 100644
--- a/src/main-lib/main.h
+++ b/src/main-lib/main.h
@@ -58,10 +58,10 @@ typedef QGuiApplication MainBase;
#endif
#include <QtAppManInstaller/installationlocation.h>
+#include <QtAppManSharedMain/sharedmain.h>
#include <QVector>
QT_FORWARD_DECLARE_CLASS(QQmlApplicationEngine)
-QT_FORWARD_DECLARE_STRUCT(QQmlDebuggingEnabler)
QT_FORWARD_DECLARE_CLASS(QQuickView)
QT_FORWARD_DECLARE_CLASS(QDBusAbstractAdaptor)
@@ -81,7 +81,8 @@ class QuickLauncher;
class SystemMonitor;
class DefaultConfiguration;
-class Main : public MainBase
+
+class Main : public MainBase, protected SharedMain
{
Q_OBJECT
Q_PROPERTY(bool singleProcessMode READ isSingleProcessMode)
@@ -101,8 +102,6 @@ public:
QQmlApplicationEngine *qmlEngine() const;
protected:
- void setupQmlDebugging(bool qmlDebugging);
- void setupLoggingRules(bool verbose, const QStringList &loggingRules);
void loadStartupPlugins(const QStringList &startupPluginPaths) Q_DECL_NOEXCEPT_EXPR(false);
void parseSystemProperties(const QVariantMap &rawSystemProperties);
void setupDBus(bool startSessionBus) Q_DECL_NOEXCEPT_EXPR(false);
@@ -110,8 +109,8 @@ protected:
const std::function<QVariantMap(const char *)> &policyForInterface);
void setMainQmlFile(const QString &mainQml) Q_DECL_NOEXCEPT_EXPR(false);
void setupSingleOrMultiProcess(bool forceSingleProcess, bool forceMultiProcess) Q_DECL_NOEXCEPT_EXPR(false);
- void setupRuntimesAndContainers(const QVariantMap &runtimeConfigurations, const QVariantMap &containerConfigurations,
- const QStringList &containerPluginPaths);
+ void setupRuntimesAndContainers(const QVariantMap &runtimeConfigurations, const QVariantMap &openGLConfiguration,
+ const QVariantMap &containerConfigurations, const QStringList &containerPluginPaths);
void setupInstallationLocations(const QVariantList &installationLocations);
void loadApplicationDatabase(const QString &databasePath, bool recreateDatabase,
const QString &singleApp) Q_DECL_NOEXCEPT_EXPR(false);
@@ -124,7 +123,6 @@ protected:
void setupWindowTitle(const QString &title, const QString &iconPath);
void setupWindowManager(const QString &waylandSocketName, bool slowAnimations, bool uiWatchdog);
void setupTouchEmulation(bool enableTouchEmulation);
- void setupOpenGL(const QString &profileName, int majorVersion, int minorVersion);
void setupShellServer(const QString &telnetAddress, quint16 telnetPort) Q_DECL_NOEXCEPT_EXPR(false);
void setupSSDPService() Q_DECL_NOEXCEPT_EXPR(false);
@@ -138,9 +136,6 @@ protected:
QString hardwareId() const;
private:
- static int &preConstructor(int &argc);
- void loadDummyDataFiles(const QString &directory);
-
#if defined(QT_DBUS_LIB) && !defined(AM_DISABLE_EXTERNAL_DBUS_INTERFACES)
const char *dbusInterfaceName(QObject *o) const Q_DECL_NOEXCEPT_EXPR(false);
void registerDBusObject(QDBusAbstractAdaptor *adaptor, const QString &dbusName, const char *serviceName,
@@ -158,7 +153,6 @@ private:
QUrl m_mainQml;
QString m_mainQmlLocalFile;
- QQmlDebuggingEnabler *m_debuggingEnabler = nullptr;
QQmlApplicationEngine *m_engine = nullptr;
QQuickView *m_view = nullptr; // only set if we allocate the window ourselves
@@ -176,14 +170,6 @@ private:
bool m_noSecurity = false;
QStringList m_builtinAppsManifestDirs;
QString m_installedAppsManifestDir;
-
-#if !defined(AM_HEADLESS)
- QSurfaceFormat::OpenGLContextProfile m_requestedOpenGLProfile = QSurfaceFormat::NoProfile;
- int m_requestedOpenGLMajorVersion = -1;
- int m_requestedOpenGLMinorVersion = -1;
-
- void checkOpenGLFormat(const char *what, const QSurfaceFormat &format) const;
-#endif
};
QT_END_NAMESPACE_AM
diff --git a/src/manager-lib/abstractruntime.cpp b/src/manager-lib/abstractruntime.cpp
index c9f63987..0eff5209 100644
--- a/src/manager-lib/abstractruntime.cpp
+++ b/src/manager-lib/abstractruntime.cpp
@@ -105,12 +105,25 @@ QByteArray AbstractRuntime::securityToken() const
return m_securityToken;
}
+
+void setOpenGLConfiguration(const QVariantMap &openGLConfiguration)
+{
+ // not every runtime needs this information
+ Q_UNUSED(openGLConfiguration)
+}
+
void AbstractRuntime::openDocument(const QString &document, const QString &mimeType)
{
Q_UNUSED(document)
Q_UNUSED(mimeType)
}
+void AbstractRuntime::setSlowAnimations(bool slow)
+{
+ // not every runtime needs this information
+ Q_UNUSED(slow)
+}
+
const Application *AbstractRuntime::application() const
{
return m_app.data();
@@ -223,4 +236,14 @@ void AbstractRuntimeManager::setSystemProperties(const QVariantMap &thirdParty,
m_systemPropertiesBuiltIn = builtIn;
}
+QVariantMap AbstractRuntimeManager::systemOpenGLConfiguration() const
+{
+ return m_systemOpenGLConfiguration;
+}
+
+void AbstractRuntimeManager::setSystemOpenGLConfiguration(const QVariantMap &openGLConfiguration)
+{
+ m_systemOpenGLConfiguration = openGLConfiguration;
+}
+
QT_END_NAMESPACE_AM
diff --git a/src/manager-lib/abstractruntime.h b/src/manager-lib/abstractruntime.h
index a6cad10b..77212a2f 100644
--- a/src/manager-lib/abstractruntime.h
+++ b/src/manager-lib/abstractruntime.h
@@ -81,11 +81,15 @@ public:
QVariantMap systemProperties3rdParty() const;
void setSystemProperties(const QVariantMap &thirdParty, const QVariantMap &builtIn);
+ QVariantMap systemOpenGLConfiguration() const;
+ void setSystemOpenGLConfiguration(const QVariantMap &openGLConfiguration);
+
private:
QString m_id;
QVariantMap m_configuration;
QVariantMap m_systemPropertiesBuiltIn;
QVariantMap m_systemProperties3rdParty;
+ QVariantMap m_systemOpenGLConfiguration;
};
@@ -121,7 +125,7 @@ public:
virtual void openDocument(const QString &document, const QString &mimeType);
- virtual void setSlowAnimations(bool value) = 0;
+ virtual void setSlowAnimations(bool slow);
void setInProcessQmlEngine(QQmlEngine *view);
QQmlEngine* inProcessQmlEngine() const;
diff --git a/src/manager-lib/applicationmanager.cpp b/src/manager-lib/applicationmanager.cpp
index c15e2862..e431f1b4 100644
--- a/src/manager-lib/applicationmanager.cpp
+++ b/src/manager-lib/applicationmanager.cpp
@@ -720,12 +720,23 @@ bool ApplicationManager::startApplication(const Application *app, const QString
// we cannot use the quicklaunch pool, if
// (a) a debug-wrapper is being used,
// (b) stdio is redirected or
- // (c) the app requests special environment variables
- bool cannotUseQuickLaunch = !debugWrapperCommand.isEmpty()
- || hasStdioRedirections
- || !app->environmentVariables().isEmpty();
-
- if (!cannotUseQuickLaunch) {
+ // (c) the app requests special environment variables or
+ // (d) the app requests a different OpenGL config from the AM
+ const char *cannotUseQuickLaunch = nullptr;
+
+ if (!debugWrapperCommand.isEmpty())
+ cannotUseQuickLaunch = "the app is started using a debug-wrapper";
+ else if (hasStdioRedirections)
+ cannotUseQuickLaunch = "standard I/O is redirected";
+ else if (!app->environmentVariables().isEmpty())
+ cannotUseQuickLaunch = "the app requests customs environment variables";
+ else if (app->openGLConfiguration() != runtimeManager->systemOpenGLConfiguration())
+ cannotUseQuickLaunch = "the app requests a custom OpenGL configuration";
+
+ if (cannotUseQuickLaunch) {
+ qCDebug(LogSystem) << "Cannot use quick-launch for application" << app->id()
+ << "because" << cannotUseQuickLaunch;
+ } else {
// check quicklaunch pool
QPair<AbstractContainer *, AbstractRuntime *> quickLaunch =
QuickLauncher::instance()->take(containerId, app->m_runtimeName);
diff --git a/src/manager-lib/manager-lib.pro b/src/manager-lib/manager-lib.pro
index 93f728f8..8f57ee85 100644
--- a/src/manager-lib/manager-lib.pro
+++ b/src/manager-lib/manager-lib.pro
@@ -5,7 +5,7 @@ MODULE = appman_manager
load(am-config)
QT = core network qml
-!headless:QT *= gui quick qml-private
+!headless:QT *= gui gui-private quick qml-private
qtHaveModule(dbus):QT *= dbus
QT_FOR_PRIVATE *= \
appman_common-private \
@@ -36,7 +36,7 @@ HEADERS += \
applicationipcinterface_p.h \
applicationmanager_p.h \
systemreader.h \
- debugwrapper.h
+ debugwrapper.h \
linux:HEADERS += \
sysfsreader.h \
@@ -68,7 +68,7 @@ SOURCES += \
applicationipcmanager.cpp \
applicationipcinterface.cpp \
systemreader.cpp \
- debugwrapper.cpp
+ debugwrapper.cpp \
linux:SOURCES += \
sysfsreader.cpp \
diff --git a/src/manager-lib/nativeruntime.cpp b/src/manager-lib/nativeruntime.cpp
index f10a20fa..c0fcf45e 100644
--- a/src/manager-lib/nativeruntime.cpp
+++ b/src/manager-lib/nativeruntime.cpp
@@ -264,23 +264,49 @@ bool NativeRuntime::start()
break;
}
- QMap<QString, QString> env = {
- { qSL("QT_QPA_PLATFORM"), qSL("wayland") },
- { qSL("QT_IM_MODULE"), QString() }, // Applications should use wayland text input
- { qSL("AM_SECURITY_TOKEN"), qL1S(securityToken().toHex()) },
- { qSL("AM_DBUS_PEER_ADDRESS"), applicationInterfaceServer()->address() },
- { qSL("AM_DBUS_NOTIFICATION_BUS_ADDRESS"), NotificationManager::instance()->property("_am_dbus_name").toString() },
- { qSL("AM_RUNTIME_CONFIGURATION"), QString::fromUtf8(QtYaml::yamlFromVariantDocuments({ configuration() })) },
- { qSL("AM_BASE_DIR"), QDir::currentPath() }
+ QVariantMap dbusConfig = {
+ { qSL("p2p"), applicationInterfaceServer()->address() },
+ { qSL("org.freedesktop.Notifications"), NotificationManager::instance()->property("_am_dbus_name").toString()}
};
+ QVariantMap loggingConfig = {
+ { qSL("dlt"), Logging::isDltEnabled() },
+ { qSL("rules"), Logging::filterRules() }
+ };
+
+ QVariantMap uiConfig;
if (m_slowAnimations)
- env.insert(qSL("AM_SLOW_ANIMATIONS"), qSL("1"));
+ uiConfig.insert(qSL("slowAnimations"), true);
+ QVariantMap openGLConfig = m_app->openGLConfiguration();
+ if (openGLConfig.isEmpty())
+ openGLConfig = manager()->systemOpenGLConfiguration();
+ if (!openGLConfig.isEmpty())
+ uiConfig.insert(qSL("opengl"), openGLConfig);
+
+ QVariantMap config = {
+ { qSL("logging"), loggingConfig },
+ { qSL("baseDir"), QDir::currentPath() },
+ { qSL("runtimeConfiguration"), configuration() },
+ { qSL("securityToken"), qL1S(securityToken().toHex()) },
+ { qSL("dbus"), dbusConfig }
+ };
if (!m_needsLauncher && !m_isQuickLauncher)
- env.insert(qSL("AM_RUNTIME_SYSTEM_PROPERTIES"), QString::fromUtf8(QtYaml::yamlFromVariantDocuments({ systemProperties() })));
- if (!Logging::isDltEnabled())
+ config.insert(qSL("systemProperties"), systemProperties());
+ if (!uiConfig.isEmpty())
+ config.insert(qSL("ui"), uiConfig);
+
+ QMap<QString, QString> env = {
+ { qSL("QT_QPA_PLATFORM"), qSL("wayland") },
+ { qSL("QT_IM_MODULE"), QString() }, // Applications should use wayland text input
+ { qSL("QT_SCALE_FACTOR"), QString() }, // do not scale wayland clients
+ { qSL("AM_CONFIG"), QString::fromUtf8(QtYaml::yamlFromVariantDocuments({ config })) },
+ };
+
+ if (Logging::isDltEnabled()) {
+ // sadly we still need this, since we need to disable DLT as soon as possible
env.insert(qSL("AM_NO_DLT_LOGGING"), qSL("1"));
+ }
for (QMapIterator<QString, QVariant> it(configuration().value(qSL("environmentVariables")).toMap()); it.hasNext(); ) {
it.next();
@@ -472,12 +498,12 @@ void NativeRuntime::openDocument(const QString &document, const QString &mimeTyp
emit m_applicationInterface->openDocument(document, mimeType);
}
-void NativeRuntime::setSlowAnimations(bool value)
+void NativeRuntime::setSlowAnimations(bool slow)
{
- if (m_slowAnimations != value) {
- m_slowAnimations = value;
+ if (m_slowAnimations != slow) {
+ m_slowAnimations = slow;
if (m_applicationInterface)
- emit m_applicationInterface->slowAnimationsChanged(value);
+ emit m_applicationInterface->slowAnimationsChanged(slow);
}
}
diff --git a/src/manager-lib/nativeruntime.h b/src/manager-lib/nativeruntime.h
index b840ec60..8521fb5d 100644
--- a/src/manager-lib/nativeruntime.h
+++ b/src/manager-lib/nativeruntime.h
@@ -89,8 +89,8 @@ public:
bool attachApplicationToQuickLauncher(const Application *app) override;
qint64 applicationProcessId() const override;
- virtual void openDocument(const QString &document, const QString &mimeType) override;
- virtual void setSlowAnimations(bool value) override;
+ void openDocument(const QString &document, const QString &mimeType) override;
+ void setSlowAnimations(bool slow) override;
bool sendNotificationUpdate(Notification *n);
@@ -134,6 +134,7 @@ private:
AbstractContainerProcess *m_process = nullptr;
QDBusServer *m_applicationInterfaceServer;
bool m_slowAnimations = false;
+ QVariantMap m_openGLConfiguration;
friend class NativeRuntimeManager;
};
diff --git a/src/manager-lib/qmlinprocessruntime.cpp b/src/manager-lib/qmlinprocessruntime.cpp
index 51e7d0da..821f900a 100644
--- a/src/manager-lib/qmlinprocessruntime.cpp
+++ b/src/manager-lib/qmlinprocessruntime.cpp
@@ -60,6 +60,7 @@
#include "global.h"
#include "utilities.h"
#include "runtimefactory.h"
+#include "qml-utilities.h"
#if defined(Q_OS_UNIX)
# include <signal.h>
@@ -67,35 +68,6 @@
QT_BEGIN_NAMESPACE_AM
-// copied straight from Qt 5.1.0 qmlscene/main.cpp for now - needs to be revised
-static void loadDummyDataFiles(QQmlEngine &engine, const QString& directory)
-{
- QDir dir(directory + qSL("/dummydata"), qSL("*.qml"));
- QStringList list = dir.entryList();
- for (int i = 0; i < list.size(); ++i) {
- QString qml = list.at(i);
- QFile f(dir.filePath(qml));
- f.open(QIODevice::ReadOnly);
- QByteArray data = f.readAll();
- QQmlComponent comp(&engine);
- comp.setData(data, QUrl());
- QObject *dummyData = comp.create();
-
- if (comp.isError()) {
- const QList<QQmlError> errors = comp.errors();
- for (const QQmlError &error : errors)
- qWarning() << error;
- }
-
- if (dummyData) {
- qWarning() << "Loaded dummy data:" << dir.filePath(qml);
- qml.truncate(qml.length()-4);
- engine.rootContext()->setContextProperty(qml, dummyData);
- dummyData->setParent(&engine);
- }
- }
-}
-
const char *QmlInProcessRuntime::s_runtimeKey = "_am_runtime";
@@ -131,7 +103,7 @@ bool QmlInProcessRuntime::start()
if (m_app->runtimeParameters().value(qSL("loadDummyData")).toBool()) {
qCDebug(LogSystem) << "Loading dummy-data";
- loadDummyDataFiles(*m_inProcessQmlEngine, QFileInfo(m_app->absoluteCodeFilePath()).path());
+ loadQmlDummyDataFiles(m_inProcessQmlEngine, QFileInfo(m_app->absoluteCodeFilePath()).path());
}
const QStringList importPaths = variantToStringList(configuration().value(qSL("importPaths")))
diff --git a/src/manager-lib/qmlinprocessruntime.h b/src/manager-lib/qmlinprocessruntime.h
index 6e8208c2..9685243f 100644
--- a/src/manager-lib/qmlinprocessruntime.h
+++ b/src/manager-lib/qmlinprocessruntime.h
@@ -73,9 +73,6 @@ public:
void openDocument(const QString &document, const QString &mimeType) override;
qint64 applicationProcessId() const override;
- // No need to do anything as, being inprocess, it will use QUnified timers from appman itself
- void setSlowAnimations(bool) override {}
-
public slots:
bool start() override;
void stop(bool forceKill = false) override;
diff --git a/src/manager-lib/runtimefactory.cpp b/src/manager-lib/runtimefactory.cpp
index 16176f71..bceb60ba 100644
--- a/src/manager-lib/runtimefactory.cpp
+++ b/src/manager-lib/runtimefactory.cpp
@@ -117,16 +117,14 @@ AbstractRuntime *RuntimeFactory::createQuickLauncher(AbstractContainer *containe
void RuntimeFactory::setConfiguration(const QVariantMap &configuration)
{
- for (auto it = m_runtimes.cbegin(); it != m_runtimes.cend(); ++it) {
+ for (auto it = m_runtimes.cbegin(); it != m_runtimes.cend(); ++it)
it.value()->setConfiguration(configuration.value(it.key()).toMap());
- }
}
void RuntimeFactory::setSystemProperties(const QVariantMap &thirdParty, const QVariantMap &builtIn)
{
- for (auto it = m_runtimes.cbegin(); it != m_runtimes.cend(); ++it) {
+ for (auto it = m_runtimes.cbegin(); it != m_runtimes.cend(); ++it)
it.value()->setSystemProperties(thirdParty, builtIn);
- }
}
void RuntimeFactory::setSlowAnimations(bool value)
@@ -134,6 +132,12 @@ void RuntimeFactory::setSlowAnimations(bool value)
m_slowAnimations = value;
}
+void RuntimeFactory::setSystemOpenGLConfiguration(const QVariantMap &openGLConfiguration)
+{
+ for (auto it = m_runtimes.cbegin(); it != m_runtimes.cend(); ++it)
+ it.value()->setSystemOpenGLConfiguration(openGLConfiguration);
+}
+
bool RuntimeFactory::registerRuntime(AbstractRuntimeManager *manager)
{
return registerRuntime(manager, manager->identifier());
diff --git a/src/manager-lib/runtimefactory.h b/src/manager-lib/runtimefactory.h
index 18ce504f..4ba41aca 100644
--- a/src/manager-lib/runtimefactory.h
+++ b/src/manager-lib/runtimefactory.h
@@ -70,6 +70,7 @@ public:
void setConfiguration(const QVariantMap &configuration);
void setSystemProperties(const QVariantMap &thirdParty, const QVariantMap &builtIn);
void setSlowAnimations(bool isSlow);
+ void setSystemOpenGLConfiguration(const QVariantMap &openGLConfiguration);
bool registerRuntime(AbstractRuntimeManager *manager);
bool registerRuntime(AbstractRuntimeManager *manager, const QString &identifier);
diff --git a/src/main-lib/qmllogger.cpp b/src/shared-main-lib/qmllogger.cpp
index 21889251..21889251 100644
--- a/src/main-lib/qmllogger.cpp
+++ b/src/shared-main-lib/qmllogger.cpp
diff --git a/src/main-lib/qmllogger.h b/src/shared-main-lib/qmllogger.h
index 7ea18cb5..7ea18cb5 100644
--- a/src/main-lib/qmllogger.h
+++ b/src/shared-main-lib/qmllogger.h
diff --git a/src/shared-main-lib/shared-main-lib.pro b/src/shared-main-lib/shared-main-lib.pro
new file mode 100644
index 00000000..bbbb52c6
--- /dev/null
+++ b/src/shared-main-lib/shared-main-lib.pro
@@ -0,0 +1,22 @@
+TEMPLATE = lib
+TARGET = QtAppManSharedMain
+MODULE = appman_shared_main
+
+load(am-config)
+
+QT = core network qml
+!headless:QT *= gui gui-private
+QT *= \
+ appman_common-private \
+
+CONFIG *= static internal_module
+
+HEADERS += \
+ $$PWD/sharedmain.h \
+ $$PWD/qmllogger.h \
+
+SOURCES += \
+ $$PWD/sharedmain.cpp \
+ $$PWD/qmllogger.cpp \
+
+load(qt_module)
diff --git a/src/shared-main-lib/sharedmain.cpp b/src/shared-main-lib/sharedmain.cpp
new file mode 100644
index 00000000..862025de
--- /dev/null
+++ b/src/shared-main-lib/sharedmain.cpp
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 <memory>
+#include <qglobal.h>
+
+#include <QFile>
+#include <QDir>
+#include <QStringList>
+#include <QVariant>
+#include <QFileInfo>
+#include <QLibrary>
+#include <QQmlDebuggingEnabler>
+#include <QQmlComponent>
+#include <QQmlContext>
+#include <QQmlEngine>
+
+#if !defined(AM_HEADLESS)
+# include <QGuiApplication>
+# include <private/qopenglcontext_p.h>
+#endif
+
+#include "global.h"
+#include "logging.h"
+#include "sharedmain.h"
+
+#include "utilities.h"
+#include "exception.h"
+#include "crashhandler.h"
+#include "qmllogger.h"
+#include "startuptimer.h"
+#include "unixsignalhandler.h"
+
+#include "../plugin-interfaces/startupinterface.h"
+
+
+QT_BEGIN_NAMESPACE_AM
+
+#if !defined(AM_HEADLESS)
+static QMap<int, QString> openGLProfileNames = {
+ { QSurfaceFormat::NoProfile, qSL("default") },
+ { QSurfaceFormat::CoreProfile, qSL("core") },
+ { QSurfaceFormat::CompatibilityProfile, qSL("compatibility") }
+};
+#endif
+
+SharedMain::SharedMain()
+{ }
+
+SharedMain::~SharedMain()
+{
+ delete m_debuggingEnabler;
+}
+
+// We need to do some things BEFORE the Q*Application constructor runs, so we're using this
+// old trick to do this hooking transparently for the user of the class.
+int &SharedMain::preConstructor(int &argc)
+{
+#if !defined(AM_HEADLESS)
+# if !defined(QT_NO_SESSIONMANAGER)
+ QGuiApplication::setFallbackSessionManagementEnabled(false);
+# endif
+
+ // this is needed for both WebEngine and Wayland Multi-screen rendering
+ QCoreApplication::setAttribute(Qt::AA_ShareOpenGLContexts);
+
+ // Calling this semi-private function before the QGuiApplication constructor is the only way to
+ // set a custom global shared GL context. We are NOT creating it right now, since we still need
+ // to parse the requested format from the config files - the creation is completed later
+ // in setupOpenGL().
+ qt_gl_set_global_share_context(new QOpenGLContext());
+
+# if defined(Q_OS_UNIX) && defined(AM_MULTI_PROCESS)
+ // set a reasonable default for OSes/distros that do not set this by default
+ setenv("XDG_RUNTIME_DIR", QDir::tempPath().toLocal8Bit(), 0);
+# endif
+#endif
+ return argc;
+}
+
+void SharedMain::setupQmlDebugging(bool qmlDebugging)
+{
+ if (qmlDebugging) {
+#if !defined(QT_NO_QML_DEBUGGER)
+ m_debuggingEnabler = new QQmlDebuggingEnabler(true);
+ if (!QLoggingCategory::defaultCategory()->isDebugEnabled()) {
+ qCCritical(LogQmlRuntime) << "The default 'debug' logging category was disabled. "
+ "Re-enabling it for the QML Debugger interface to work correctly.";
+ QLoggingCategory::defaultCategory()->setEnabled(QtDebugMsg, true);
+ }
+#else
+ qCWarning(LogSystem) << "The --qml-debug option is ignored, because Qt was built without support for QML Debugging!";
+#endif
+ }
+}
+
+void SharedMain::setupLoggingRules(bool verbose, const QStringList &loggingRules)
+{
+ const QStringList rules = verbose ? QStringList() << qSL("*=true") << qSL("qt.*.debug=false")
+ : loggingRules.isEmpty() ? QStringList(qSL("*.debug=false"))
+ : loggingRules;
+ Logging::setFilterRules(rules);
+ StartupTimer::instance()->checkpoint("after logging setup");
+}
+
+void SharedMain::setupOpenGL(const QVariantMap &openGLConfiguration)
+{
+#if !defined(AM_HEADLESS)
+ QString profileName = openGLConfiguration.value(qSL("desktopProfile")).toString();
+ int majorVersion = openGLConfiguration.value(qSL("esMajorVersion"), -1).toInt();
+ int minorVersion = openGLConfiguration.value(qSL("esMinorVersion"), -1).toInt();
+
+ QOpenGLContext *globalContext = qt_gl_global_share_context();
+ QSurfaceFormat format = QSurfaceFormat::defaultFormat();
+ bool isES = (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES);
+
+ // either both are set or none is set
+ if ((majorVersion > -1) != (minorVersion > -1)) {
+ qCWarning(LogGraphics) << "Requesting only the major or minor OpenGL version number is not "
+ "supported - always specify both or none.";
+ } else if (majorVersion > -1) {
+ bool valid = isES;
+
+ if (!isES) {
+ // we need to map the ES version to the corresponding desktop versions:
+ static int mapping[] = {
+ 2, 0, 2, 1,
+ 3, 0, 4, 3,
+ 3, 1, 4, 5,
+ 3, 2, 4, 6,
+ -1
+ };
+ for (int i = 0; mapping[i] != -1; i += 4) {
+ if ((majorVersion == mapping[i]) && (minorVersion == mapping[i + 1])) {
+ majorVersion = mapping[i + 2];
+ minorVersion = mapping[i + 3];
+ valid = true;
+ break;
+ }
+ }
+ if (!valid) {
+ qCWarning(LogGraphics).nospace() << "Requested OpenGLES version " << majorVersion
+ << "." << minorVersion
+ << ", but there is no mapping available to a corresponding desktop GL version.";
+ }
+ }
+
+ if (valid) {
+ format.setMajorVersion(majorVersion);
+ format.setMinorVersion(minorVersion);
+ m_requestedOpenGLMajorVersion = majorVersion;
+ m_requestedOpenGLMinorVersion = minorVersion;
+ qCDebug(LogGraphics).nospace() << "Requested OpenGL" << (isES ? "ES" : "") << " version "
+ << majorVersion << "." << minorVersion;
+ }
+ }
+ if (!profileName.isEmpty()) {
+ int profile = openGLProfileNames.key(profileName, -1);
+
+ if (profile == -1) {
+ qCWarning(LogGraphics) << "Requested an invalid OpenGL profile:" << profileName;
+ } else if (profile != QSurfaceFormat::NoProfile) {
+ m_requestedOpenGLProfile = (QSurfaceFormat::OpenGLContextProfile) profile;
+ format.setProfile(m_requestedOpenGLProfile);
+ qCDebug(LogGraphics) << "Requested OpenGL profile" << profileName;
+ }
+ }
+ if ((m_requestedOpenGLProfile != QSurfaceFormat::NoProfile) || (m_requestedOpenGLMajorVersion > -1))
+ QSurfaceFormat::setDefaultFormat(format);
+
+ // Setting the screen is normally done by the QOpenGLContext constructor, but our constructor
+ // ran before the QGuiApplication constructor, so the screen was not initialized yet. So we have
+ // to tell the context about the screen again now:
+ globalContext->setScreen(QGuiApplication::primaryScreen());
+
+ if (!globalContext->create())
+ throw Exception("Failed to create the global shared OpenGL context.");
+
+ // check if we got what we requested on the OpenGL side
+ checkOpenGLFormat("global shared context", globalContext->format());
+#endif
+}
+
+#if !defined(AM_HEADLESS)
+void SharedMain::checkOpenGLFormat(const char *what, const QSurfaceFormat &format) const
+{
+ if ((m_requestedOpenGLProfile != QSurfaceFormat::NoProfile)
+ && (format.profile() != m_requestedOpenGLProfile)) {
+ qCWarning(LogGraphics) << "Failed to get the requested OpenGL profile"
+ << openGLProfileNames.value(m_requestedOpenGLProfile) << "for the"
+ << what << "- got"
+ << openGLProfileNames.value(format.profile()) << "instead.";
+ }
+ if (m_requestedOpenGLMajorVersion > -1) {
+ if ((format.majorVersion() != m_requestedOpenGLMajorVersion )
+ || (format.minorVersion() != m_requestedOpenGLMinorVersion)) {
+ qCWarning(LogGraphics).nospace() << "Failed to get the requested OpenGL version "
+ << m_requestedOpenGLMajorVersion << "."
+ << m_requestedOpenGLMinorVersion << " for "
+ << what << " - got "
+ << format.majorVersion() << "."
+ << format.minorVersion() << " instead";
+ }
+ }
+}
+#endif
+
+QT_END_NAMESPACE_AM
diff --git a/src/shared-main-lib/sharedmain.h b/src/shared-main-lib/sharedmain.h
new file mode 100644
index 00000000..8c9da1ba
--- /dev/null
+++ b/src/shared-main-lib/sharedmain.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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 <QtAppManCommon/global.h>
+#include <QVariantMap>
+#include <QStringList>
+#if !defined(AM_HEADLESS)
+# include <QSurfaceFormat>
+#endif
+
+QT_FORWARD_DECLARE_STRUCT(QQmlDebuggingEnabler)
+QT_FORWARD_DECLARE_STRUCT(QQmlEngine)
+
+QT_BEGIN_NAMESPACE_AM
+
+class SharedMain
+{
+public:
+ SharedMain();
+ ~SharedMain();
+
+ static int &preConstructor(int &argc);
+ void setupQmlDebugging(bool qmlDebugging);
+ void setupLoggingRules(bool verbose, const QStringList &loggingRules);
+ void setupOpenGL(const QVariantMap &openGLConfiguration);
+
+#if !defined(AM_HEADLESS)
+ void checkOpenGLFormat(const char *what, const QSurfaceFormat &format) const;
+#endif
+
+private:
+ QQmlDebuggingEnabler *m_debuggingEnabler = nullptr;
+
+#if !defined(AM_HEADLESS)
+ QSurfaceFormat::OpenGLContextProfile m_requestedOpenGLProfile = QSurfaceFormat::NoProfile;
+ int m_requestedOpenGLMajorVersion = -1;
+ int m_requestedOpenGLMinorVersion = -1;
+#endif
+};
+
+QT_END_NAMESPACE_AM
diff --git a/src/src.pro b/src/src.pro
index 8a6ab09f..00543693 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -34,8 +34,11 @@ monitor_lib.depends = manager_lib window_lib
launcher_lib.subdir = launcher-lib
launcher_lib.depends = application_lib notification_lib
+shared_main_lib.subdir = shared-main-lib
+shared_main_lib.depends = common_lib
+
main_lib.subdir = main-lib
-main_lib.depends = manager_lib installer_lib window_lib monitor_lib
+main_lib.depends = shared_main_lib manager_lib installer_lib window_lib monitor_lib
!disable-external-dbus-interfaces:qtHaveModule(dbus) {
dbus_lib.subdir = dbus-lib
@@ -45,7 +48,7 @@ main_lib.depends = manager_lib installer_lib window_lib monitor_lib
}
launchers_qml.subdir = launchers/qml
-launchers_qml.depends = launcher_lib plugin_interfaces
+launchers_qml.depends = shared_main_lib launcher_lib plugin_interfaces
tools_appman.subdir = tools/appman
tools_appman.depends = main_lib
@@ -81,6 +84,7 @@ SUBDIRS = \
installer_lib \
window_lib \
monitor_lib \
+ shared_main_lib \
main_lib \
tools_appman \
# Although the testrunner is in tools we don't want to build it with tools-only
diff --git a/src/tools/appman/appman.pro b/src/tools/appman/appman.pro
index 0b9e3e46..385860b0 100644
--- a/src/tools/appman/appman.pro
+++ b/src/tools/appman/appman.pro
@@ -1,5 +1,5 @@
TEMPLATE = app
-TARGET = appman
+TARGET = appman
load(am-config)
@@ -7,8 +7,6 @@ QT = appman_main-private
CONFIG *= console
-#win32:LIBS += -luser32
-
SOURCES += \
$$PWD/appman.cpp