You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
core/session/processmanager.cpp

175 lines
4.9 KiB
C++

#include "processmanager.h"
#include <QCoreApplication>
#include <QStandardPaths>
#include <QFileInfoList>
#include <QFileInfo>
#include <QSettings>
#include <QDebug>
#include <QTimer>
#include <QThread>
#include <QDir>
#include <QX11Info>
#include <KWindowSystem>
#include <KWindowSystem/NETWM>
ProcessManager::ProcessManager(QObject *parent)
: QObject(parent)
, m_wmStarted(false)
, m_waitLoop(nullptr)
{
qApp->installNativeEventFilter(this);
}
ProcessManager::~ProcessManager()
{
qApp->removeNativeEventFilter(this);
QMapIterator<QString, QProcess *> i(m_systemProcess);
while (i.hasNext()) {
i.next();
QProcess *p = i.value();
delete p;
m_systemProcess[i.key()] = nullptr;
}
}
void ProcessManager::start()
{
startWindowManager();
loadSystemProcess();
QTimer::singleShot(100, this, &ProcessManager::loadAutoStartProcess);
}
void ProcessManager::logout()
{
QMapIterator<QString, QProcess *> i(m_systemProcess);
while (i.hasNext()) {
i.next();
QProcess *p = i.value();
p->terminate();
}
i.toFront();
while (i.hasNext()) {
i.next();
QProcess *p = i.value();
if (p->state() != QProcess::NotRunning && !p->waitForFinished(2000)) {
p->kill();
}
}
QCoreApplication::exit(0);
}
void ProcessManager::startWindowManager()
{
QProcess *wmProcess = new QProcess;
wmProcess->start("kwin_x11", QStringList());
QEventLoop waitLoop;
m_waitLoop = &waitLoop;
// add a timeout to avoid infinite blocking if a WM fail to execute.
QTimer::singleShot(30 * 1000, &waitLoop, SLOT(quit()));
waitLoop.exec();
m_waitLoop = nullptr;
}
void ProcessManager::loadSystemProcess()
{
QList<QPair<QString, QStringList>> list;
list << qMakePair(QString("cutefish-settings-daemon"), QStringList());
list << qMakePair(QString("cutefish-xembedsniproxy"), QStringList());
// Desktop components
list << qMakePair(QString("cutefish-filemanager"), QStringList("--desktop"));
list << qMakePair(QString("cutefish-statusbar"), QStringList());
list << qMakePair(QString("cutefish-dock"), QStringList());
list << qMakePair(QString("cutefish-launcher"), QStringList());
for (QPair<QString, QStringList> pair : list) {
QProcess *process = new QProcess;
process->setProcessChannelMode(QProcess::ForwardedChannels);
process->setProgram(pair.first);
process->setArguments(pair.second);
process->start();
process->waitForStarted();
if (pair.first == "cutefish-settings-daemon") {
QThread::msleep(800);
}
qDebug() << "Load DE components: " << pair.first << pair.second;
// Add to map
if (process->exitCode() == 0) {
m_autoStartProcess.insert(pair.first, process);
} else {
process->deleteLater();
}
}
}
void ProcessManager::loadAutoStartProcess()
{
QStringList execList;
const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation,
QStringLiteral("autostart"),
QStandardPaths::LocateDirectory);
for (const QString &dir : dirs) {
const QDir d(dir);
const QStringList fileNames = d.entryList(QStringList() << QStringLiteral("*.desktop"));
for (const QString &file : fileNames) {
QSettings desktop(d.absoluteFilePath(file), QSettings::IniFormat);
desktop.setIniCodec("UTF-8");
desktop.beginGroup("Desktop Entry");
if (desktop.contains("OnlyShowIn"))
continue;
const QString execValue = desktop.value("Exec").toString();
if (!execValue.isEmpty()) {
execList << execValue;
}
}
}
for (const QString &exec : execList) {
QProcess *process = new QProcess;
process->setProgram(exec);
process->start();
process->waitForStarted();
if (process->exitCode() == 0) {
m_autoStartProcess.insert(exec, process);
} else {
process->deleteLater();
}
}
}
bool ProcessManager::nativeEventFilter(const QByteArray &eventType, void *message, long *result)
{
if (eventType != "xcb_generic_event_t") // We only want to handle XCB events
return false;
// ref: lxqt session
if (!m_wmStarted && m_waitLoop) {
// all window managers must set their name according to the spec
if (!QString::fromUtf8(NETRootInfo(QX11Info::connection(), NET::SupportingWMCheck).wmName()).isEmpty()) {
qDebug() << "Window manager started";
m_wmStarted = true;
if (m_waitLoop && m_waitLoop->isRunning())
m_waitLoop->exit();
qApp->removeNativeEventFilter(this);
}
}
return false;
}