#include "processmanager.h" #include #include #include #include #include #include #include #include #include #include #include #include ProcessManager::ProcessManager(QObject *parent) : QObject(parent) , m_wmStarted(false) , m_waitLoop(nullptr) { qApp->installNativeEventFilter(this); } ProcessManager::~ProcessManager() { qApp->removeNativeEventFilter(this); QMapIterator 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 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> 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 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; }