diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt --- a/shell/CMakeLists.txt +++ b/shell/CMakeLists.txt @@ -33,7 +33,6 @@ panelconfigview.cpp panelshadows.cpp shellcorona.cpp - shellmanager.cpp standaloneappcorona osd.cpp coronatesthelper.cpp diff --git a/shell/main.cpp b/shell/main.cpp --- a/shell/main.cpp +++ b/shell/main.cpp @@ -38,7 +38,6 @@ #include "shellcorona.h" #include "standaloneappcorona.h" -#include "shellmanager.h" #include "coronatesthelper.h" #include "softwarerendernotifier.h" @@ -101,7 +100,7 @@ QCommandLineOption shellPluginOption(QStringList() << QStringLiteral("p") << QStringLiteral("shell-plugin"), i18n("Force loading the given shell plugin"), - QStringLiteral("plugin")); + QStringLiteral("plugin"), QStringLiteral("org.kde.plasma.desktop")); QCommandLineOption standaloneOption(QStringList() << QStringLiteral("a") << QStringLiteral("standalone"), i18n("Load plasmashell as a standalone application, needs the shell-plugin option to be specified")); @@ -131,7 +130,8 @@ QObject::connect(&app, &QGuiApplication::commitDataRequest, disableSessionManagement); QObject::connect(&app, &QGuiApplication::saveStateRequest, disableSessionManagement); - ShellManager::s_fixedShell = cliOptions.value(shellPluginOption); + ShellCorona* corona = new ShellCorona(&app); + corona->setShell(cliOptions.value(shellPluginOption)); if (!cliOptions.isSet(noRespawnOption) && !cliOptions.isSet(testOption)) { KCrash::setFlags(KCrash::AutoRestart); @@ -146,21 +146,15 @@ QStandardPaths::setTestModeEnabled(true); QDir(QStandardPaths::writableLocation(QStandardPaths::ConfigLocation)).removeRecursively(); - ShellManager::s_testModeLayout = layoutUrl.toLocalFile(); + corona->setTestModeLayout(layoutUrl.toLocalFile()); qApp->setProperty("org.kde.KActivities.core.disableAutostart", true); - QObject::connect(ShellManager::instance(), &ShellManager::shellChanged, - ShellManager::instance(), - [layoutUrl]() { - new CoronaTestHelper(ShellManager::instance()->corona()); - } - ); + new CoronaTestHelper(corona); } if (cliOptions.isSet(standaloneOption)) { if (cliOptions.isSet(shellPluginOption)) { - ShellManager::s_standaloneOption = true; app.setApplicationName(QStringLiteral("plasmashell_") + cliOptions.value(shellPluginOption)); app.setQuitOnLastWindowClosed(true); @@ -183,11 +177,7 @@ QStringLiteral("quit")); QDBusConnection::sessionBus().call(message); //deliberately block until it's done, so we register the name after the app quits } - } - - KDBusService service(KDBusService::Unique); - - QObject::connect(ShellManager::instance(), &ShellManager::glInitializationFailed, &app, [&app]() { + QObject::connect(corona, &ShellCorona::glInitializationFailed, &app, [&app]() { //scene graphs errors come from a thread //even though we process them in the main thread, app.exit could still process these events static bool s_multipleInvokations = false; @@ -209,8 +199,11 @@ } app.exit(-1); }); + } + + KDBusService service(KDBusService::Unique); + SoftwareRendererNotifier::notifyIfRelevant(); - QObject::connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, ShellManager::instance(), &QObject::deleteLater); return app.exec(); } diff --git a/shell/shellcorona.h b/shell/shellcorona.h --- a/shell/shellcorona.h +++ b/shell/shellcorona.h @@ -162,6 +162,8 @@ void previousActivity(); void stopCurrentActivity(); + void setTestModeLayout(const QString &layout) { m_testModeLayout = layout; } + protected Q_SLOTS: /** * Loads the layout and performs the needed checks @@ -251,6 +253,7 @@ KWayland::Client::PlasmaShell *m_waylandPlasmaShell; bool m_closingDown : 1; + QString m_testModeLayout; }; #endif // SHELLCORONA_H diff --git a/shell/shellcorona.cpp b/shell/shellcorona.cpp --- a/shell/shellcorona.cpp +++ b/shell/shellcorona.cpp @@ -63,7 +63,6 @@ #include "desktopview.h" #include "panelview.h" #include "scripting/scriptengine.h" -#include "shellmanager.h" #include "osd.h" #include "screenpool.h" @@ -910,7 +909,7 @@ addOutput(screen); } - script = ShellManager::s_testModeLayout; + script = m_testModeLayout; if (script.isEmpty()) { script = m_lookAndFeelPackage.filePath("layouts", QString(shell() + "-layout.js").toLatin1()); diff --git a/shell/shellmanager.h b/shell/shellmanager.h deleted file mode 100644 --- a/shell/shellmanager.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2013 Ivan Cukic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, - * or (at your option) any later version, as published by the Free - * Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#ifndef SHELLMANAGER_H -#define SHELLMANAGER_H - -#include - -namespace Plasma { - class Corona; -} - -/** - * ShellManager creates a ShellCorona instance and manages it. - * - * Shell manager loads "handlers" from QML files which suggests which shell - * corona should currently be active. - * For example switching between tablet and desktop shells on hardware changes. - * - * This class also provides crash handling. - */ - -class ShellManager: public QObject { - Q_OBJECT -public: - static ShellManager * instance(); - ~ShellManager() override; - - static bool s_standaloneOption; - static QString s_fixedShell; - static QString s_testModeLayout; - - Plasma::Corona* corona() const; - -protected Q_SLOTS: - void registerHandler(QObject * handler); - void deregisterHandler(QObject * handler); - -public Q_SLOTS: - void requestShellUpdate(); - void updateShell(); - -Q_SIGNALS: - void shellChanged(const QString & shell); - void glInitializationFailed(); - -private Q_SLOTS: - void loadHandlers(); - -private: - ShellManager(); - - class Private; - const QScopedPointer d; -}; - -#endif /* SHELLMANAGER_H */ - diff --git a/shell/shellmanager.cpp b/shell/shellmanager.cpp deleted file mode 100644 --- a/shell/shellmanager.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2013 Ivan Cukic - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2, - * or (at your option) any later version, as published by the Free - * Software Foundation - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details - * - * You should have received a copy of the GNU General Public - * License along with this program; if not, write to the - * Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ - -#include "shellmanager.h" - -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -//#include -#include "shellcorona.h" -#include "config-workspace.h" - -#include -#include - -#include - -static const QStringList s_shellsDirs(QStandardPaths::locateAll(QStandardPaths::QStandardPaths::GenericDataLocation, - PLASMA_RELATIVE_DATA_INSTALL_DIR "/shells/", - QStandardPaths::LocateDirectory)); -static const QString s_shellLoaderPath = QStringLiteral("/contents/loader.qml"); - -bool ShellManager::s_standaloneOption = false; -QString ShellManager::s_fixedShell; -QString ShellManager::s_testModeLayout; - -// -// ShellManager -// - -class ShellManager::Private { -public: - Private() - : currentHandler(nullptr), - corona(nullptr) - { - shellUpdateDelay.setInterval(100); - shellUpdateDelay.setSingleShot(true); - } - - QList handlers; - QObject * currentHandler; - QTimer shellUpdateDelay; - ShellCorona * corona; -}; - -ShellManager::ShellManager() - : d(new Private()) -{ - //we have to ensure this is executed after QCoreApplication::exec() - QMetaObject::invokeMethod(this, "loadHandlers", Qt::QueuedConnection); - connect(&d->shellUpdateDelay, &QTimer::timeout, - this, &ShellManager::updateShell); -} - -ShellManager::~ShellManager() -{ - // if (d->currentHandler) - // d->currentHandler->unload(); -} - -void ShellManager::loadHandlers() -{ - //this should be executed one single time in the app life cycle - Q_ASSERT(!d->corona); - - d->corona = new ShellCorona(this); - connect(d->corona, &ShellCorona::glInitializationFailed, - this, &ShellManager::glInitializationFailed); - - connect( - this, &ShellManager::shellChanged, - d->corona, &ShellCorona::setShell - ); - - for (const QString &shellsDir : qAsConst(s_shellsDirs)) { - const auto dirs = QDir(shellsDir).entryList(QDir::Dirs | QDir::NoDotAndDotDot); - for (const auto &dir : dirs) { - const QString qmlFile = shellsDir + dir + s_shellLoaderPath; - // qDebug() << "Making a new instance of " << qmlFile; - - //this shell is not valid, ignore it - if (!QFileInfo::exists(qmlFile)) { - continue; - } - - auto *handlerContainer = new KDeclarative::QmlObjectSharedEngine(this); - auto handler = handlerContainer->createObjectFromSource(QUrl::fromLocalFile(qmlFile), nullptr, { - { "pluginName", dir }, - - // This property is useful for shells to launch themselves in some specific sessions - // For example mediacenter shell can be launched when in plasma-mediacenter session - { "currentSession", QString::fromUtf8(qgetenv("DESKTOP_SESSION")) } - }); - - if (handler) { - registerHandler(handler); - } - } - } - - updateShell(); -} - -void ShellManager::registerHandler(QObject * handler) -{ - // qDebug() << "We got the handler: " << handler->property("shell").toString(); - - connect( - handler, &QObject::destroyed, - this, &ShellManager::deregisterHandler - ); - - connect( - handler, SIGNAL(willingChanged()), - this, SLOT(requestShellUpdate()) - ); - - connect( - handler, SIGNAL(priorityChanged()), - this, SLOT(requestShellUpdate()) - ); - - d->handlers.push_back(handler); -} - -void ShellManager::deregisterHandler(QObject * handler) -{ - const int removed = d->handlers.removeAll(handler); - if (removed > 0) { - handler->disconnect(this); - } - - if (d->currentHandler == handler) { - d->currentHandler = nullptr; - updateShell(); - } - handler->deleteLater(); -} - -void ShellManager::requestShellUpdate() -{ - d->shellUpdateDelay.start(); -} - -void ShellManager::updateShell() -{ - d->shellUpdateDelay.stop(); - - if (d->handlers.isEmpty()) { - KMessageBox::error(nullptr, //wID, but we don't have a window yet - i18nc("Fatal error message body","All shell packages missing.\nThis is an installation issue, please contact your distribution"), - i18nc("Fatal error message title", "Plasma Cannot Start")); - qCritical("We have no shell handlers installed"); - QCoreApplication::exit(-1); - } - - QObject *handler = nullptr; - - if (!s_fixedShell.isEmpty()) { - QList::const_iterator it = std::find_if (d->handlers.cbegin(), d->handlers.cend(), [=] (QObject *handler) { - return handler->property("pluginName").toString() == s_fixedShell; - }); - if (it != d->handlers.cend()) { - handler = *it; - } else { - KMessageBox::error(nullptr, - i18nc("Fatal error message body", "Shell package %1 cannot be found", s_fixedShell), - i18nc("Fatal error message title", "Plasma Cannot Start")); - qCritical("Unable to find the shell plugin '%s'", qPrintable(s_fixedShell)); - QCoreApplication::exit(-1); - } - } else { - // Finding the handler that has the priority closest to zero. - // We will return a handler even if there are no willing ones. - handler =* std::min_element(d->handlers.cbegin(), d->handlers.cend(), - [] (QObject * left, QObject * right) - { - auto willing = [] (QObject * handler) - { - return handler->property("willing").toBool(); - }; - - auto priority = [] (QObject * handler) - { - return handler->property("priority").toInt(); - }; - - return - // If one is willing and the other is not, - // return it - it has the priority - willing(left) && !willing(right) ? true : - !willing(left) && willing(right) ? false : - // otherwise just compare the priorities - priority(left) < priority(right); - } - ); - } - - if (handler == d->currentHandler) return; - - // Activating the new handler and killing the old one - if (d->currentHandler) { - d->currentHandler->setProperty("loaded", false); - } - - // handler will never be null, unless there is no shells - // available on the system, which is definitely not something - // we want to support :) - d->currentHandler = handler; - d->currentHandler->setProperty("loaded", true); - - emit shellChanged(d->currentHandler->property("shell").toString()); -} - -ShellManager * ShellManager::instance() -{ - static ShellManager* manager = nullptr; - if (!manager) { - manager = new ShellManager; - } - return manager; -} - -Plasma::Corona* ShellManager::corona() const -{ - return d->corona; -}