You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
181 lines
5.2 KiB
181 lines
5.2 KiB
/* |
|
SPDX-FileCopyrightText: 1999 Matthias Hoelzer-Kluepfel <hoelzer@kde.org> |
|
|
|
SPDX-License-Identifier: GPL-2.0-or-later |
|
*/ |
|
|
|
#include <config-workspace.h> |
|
|
|
#include "main.h" |
|
|
|
#include <unistd.h> |
|
|
|
#include <KFileUtils> |
|
#include <KPluginInfo> |
|
#include <QDBusConnection> |
|
#include <QDBusMessage> |
|
#include <QDBusPendingCall> |
|
#include <QDebug> |
|
#include <QFile> |
|
#include <QGuiApplication> |
|
#include <QLibrary> |
|
#include <QTimer> |
|
|
|
#include <KAboutData> |
|
#include <KConfig> |
|
#include <KConfigGroup> |
|
#include <KLocalizedString> |
|
#include <kworkspace.h> |
|
|
|
static int ready[2]; |
|
static bool startup = false; |
|
|
|
static void sendReady() |
|
{ |
|
if (ready[1] == -1) |
|
return; |
|
char c = 0; |
|
write(ready[1], &c, 1); |
|
close(ready[1]); |
|
ready[1] = -1; |
|
} |
|
|
|
static void waitForReady() |
|
{ |
|
char c = 1; |
|
close(ready[1]); |
|
read(ready[0], &c, 1); |
|
close(ready[0]); |
|
} |
|
|
|
bool KCMInit::runModule(const KPluginMetaData &data) |
|
{ |
|
QString path = QPluginLoader(data.fileName()).fileName(); |
|
|
|
// get the kcminit_ function |
|
QFunctionPointer init = QLibrary::resolve(path, "kcminit"); |
|
if (!init) { |
|
qWarning() << "Module" << data.fileName() << "does not actually have a kcminit function"; |
|
return false; |
|
} |
|
|
|
// initialize the module |
|
qDebug() << "Initializing " << data.fileName(); |
|
init(); |
|
return true; |
|
} |
|
|
|
void KCMInit::runModules(int phase) |
|
{ |
|
for (const KPluginMetaData &data : qAsConst(m_list)) { |
|
// see ksmserver's README for the description of the phases |
|
int libphase = data.value(QStringLiteral("X-KDE-Init-Phase"), 1); |
|
|
|
if (libphase > 1) { |
|
libphase = 1; |
|
} |
|
|
|
if (phase != -1 && libphase != phase) |
|
continue; |
|
|
|
// try to load the library |
|
if (!m_alreadyInitialized.contains(data.pluginId())) { |
|
runModule(data); |
|
m_alreadyInitialized.append(data.pluginId()); |
|
} |
|
} |
|
} |
|
|
|
KCMInit::KCMInit(const QCommandLineParser &args) |
|
{ |
|
QString arg; |
|
if (args.positionalArguments().size() == 1) { |
|
arg = args.positionalArguments().first(); |
|
} |
|
|
|
if (args.isSet(QStringLiteral("list"))) { |
|
m_list = KPluginMetaData::findPlugins(QStringLiteral("plasma/kcminit")); |
|
for (const KPluginMetaData &data : qAsConst(m_list)) { |
|
printf("%s\n", QFile::encodeName(data.fileName()).data()); |
|
} |
|
return; |
|
} |
|
|
|
if (!arg.isEmpty()) { |
|
if (KPluginMetaData data(arg); data.isValid()) { |
|
m_list << arg; |
|
} |
|
} else { |
|
m_list = KPluginMetaData::findPlugins(QStringLiteral("plasma/kcminit")); |
|
} |
|
|
|
if (startup) { |
|
runModules(0); |
|
// Tell KSplash that KCMInit has started |
|
QDBusMessage ksplashProgressMessage = QDBusMessage::createMethodCall(QStringLiteral("org.kde.KSplash"), |
|
QStringLiteral("/KSplash"), |
|
QStringLiteral("org.kde.KSplash"), |
|
QStringLiteral("setStage")); |
|
ksplashProgressMessage.setArguments(QList<QVariant>() << QStringLiteral("kcminit")); |
|
QDBusConnection::sessionBus().asyncCall(ksplashProgressMessage); |
|
|
|
sendReady(); |
|
QTimer::singleShot(300 * 1000, qApp, &QCoreApplication::quit); // just in case |
|
|
|
QDBusConnection::sessionBus().registerObject(QStringLiteral("/kcminit"), this, QDBusConnection::ExportScriptableContents); |
|
QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.kcminit")); |
|
|
|
qApp->exec(); // wait for runPhase1() |
|
} else |
|
runModules(-1); // all phases |
|
} |
|
|
|
KCMInit::~KCMInit() |
|
{ |
|
sendReady(); |
|
} |
|
|
|
void KCMInit::runPhase1() |
|
{ |
|
runModules(1); |
|
qApp->exit(0); |
|
} |
|
|
|
int main(int argc, char *argv[]) |
|
{ |
|
// plasma-session startup waits for kcminit to finish running phase 0 kcms |
|
// (theoretically that is only important kcms that need to be started very |
|
// early in the login process), the rest is delayed, so fork and make parent |
|
// return after the initial phase |
|
pipe(ready); |
|
if (fork() != 0) { |
|
waitForReady(); |
|
return 0; |
|
} |
|
close(ready[0]); |
|
|
|
const QString executableName = QString::fromUtf8(argv[0]); |
|
startup = executableName.endsWith(QLatin1String("kcminit_startup")); // started from startkde? |
|
|
|
KWorkSpace::detectPlatform(argc, argv); |
|
QGuiApplication::setDesktopSettingsAware(false); |
|
QGuiApplication app(argc, argv); // gui is needed for several modules |
|
KLocalizedString::setApplicationDomain("kcminit"); |
|
KAboutData about(QStringLiteral("kcminit"), |
|
i18n("KCMInit"), |
|
QString(), |
|
i18n("KCMInit - runs startup initialization for Control Modules."), |
|
KAboutLicense::GPL); |
|
KAboutData::setApplicationData(about); |
|
|
|
QCommandLineParser parser; |
|
about.setupCommandLine(&parser); |
|
parser.addOption(QCommandLineOption(QStringList() << QStringLiteral("list"), i18n("List modules that are run at startup"))); |
|
parser.addPositionalArgument(QStringLiteral("module"), i18n("Configuration module to run")); |
|
|
|
parser.process(app); |
|
about.processCommandLine(&parser); |
|
|
|
KCMInit kcminit(parser); |
|
return 0; |
|
}
|
|
|