diff --git a/.gitignore b/.gitignore index 7f2661c..5c0361d 100755 --- a/.gitignore +++ b/.gitignore @@ -56,4 +56,7 @@ build/* debian/.debhelper debian/files debian/lingmo-core* -obj-x86_64* \ No newline at end of file +obj-x86_64* + +.cache/ +.idea/ diff --git a/session/CMakeLists.txt b/session/CMakeLists.txt index 58dfe4f..8917368 100755 --- a/session/CMakeLists.txt +++ b/session/CMakeLists.txt @@ -1,4 +1,8 @@ project(lingmo-session) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED 17) + set(TARGET lingmo-session) set(SOURCES diff --git a/session/application.cpp b/session/application.cpp index 21fab00..32786e9 100755 --- a/session/application.cpp +++ b/session/application.cpp @@ -130,6 +130,8 @@ Application::Application(int &argc, char **argv) m_networkProxyManager->update(); QTimer::singleShot(50, this, &Application::updateUserDirs); + + // Launch Lingmo and user defined processes ! QTimer::singleShot(100, m_processManager, &ProcessManager::start); } diff --git a/session/application.h b/session/application.h index 655cf62..0920420 100755 --- a/session/application.h +++ b/session/application.h @@ -21,6 +21,8 @@ #define APPLICATION_H #include +#include +#include #include "processmanager.h" #include "networkproxymanager.h" @@ -54,11 +56,12 @@ public slots: m_power.suspend(); } - void startDesktopProcess() { + [[maybe_unused]] void startDesktopProcess() { + // Start Lingmo Desktop Environment m_processManager->startDesktopProcess(); } - void updateNetworkProxy() { + [[maybe_unused]] void updateNetworkProxy() { m_networkProxyManager->update(); } diff --git a/session/daemon-helper.cpp b/session/daemon-helper.cpp index e1b132c..875a8b8 100644 --- a/session/daemon-helper.cpp +++ b/session/daemon-helper.cpp @@ -13,44 +13,45 @@ #include namespace LINGMO_SESSION { - Daemon::Daemon(const QList>& processList, QObject* parent) - : QObject(parent), m_processList(processList) { - for (const auto& processInfo : m_processList) { - startProcess(processInfo); +Daemon::Daemon(const QList> &processList, bool _enableAutoStart, QObject *parent) + : QObject(parent), m_processList(processList), m_enableAutoRestart(_enableAutoStart) { + for (const auto &processInfo : m_processList) { + startProcess(processInfo); } - } +} + +void Daemon::onProcessError(QProcess::ProcessError error) { + auto process = qobject_cast(sender()); - void Daemon::onProcessError(QProcess::ProcessError error) { - QProcess* process = qobject_cast(sender()); if (!process) - return; + return; QString program = process->program(); qDebug() << "Process error:" << program << "Error:" << error; - for (const auto& processInfo : m_processList) { - if (processInfo.first == program) { - qDebug() << "Restarting process due to error:" << program; - QTimer::singleShot(1, this, [this, processInfo]() { + for (const auto &processInfo : m_processList) { + if (processInfo.first == program) { + qDebug() << "Restarting process due to error:" << program; + QTimer::singleShot(1, this, [this, processInfo]() { startProcess(processInfo); - }); // Restart after 1 second - return; - } + }); // Restart after 1 second + return; + } } - } +} - void Daemon::startProcess(const QPair& processInfo) { - QProcess* process = new QProcess(this); +void Daemon::startProcess(const QPair &processInfo) { + auto process = new QProcess(this); - connect(process, &QProcess::errorOccurred, + if (this->m_enableAutoRestart) + connect(process, &QProcess::errorOccurred, this, &Daemon::onProcessError); process->start(processInfo.first, processInfo.second); if (process->waitForStarted()) { - qDebug() << "Process started:" << processInfo.first << "PID:" << process->processId(); - } - else { - qDebug() << "Failed to start process:" << processInfo.first << process->errorString(); + qDebug() << "Process started:" << processInfo.first << "PID:" << process->processId(); + } else { + qDebug() << "Failed to start process:" << processInfo.first << process->errorString(); } - } +} } // namespace LINGMO_SESSION diff --git a/session/daemon-helper.h b/session/daemon-helper.h index 3e712e4..3715569 100644 --- a/session/daemon-helper.h +++ b/session/daemon-helper.h @@ -20,7 +20,7 @@ namespace LINGMO_SESSION { * @param processList Process list to start * @param parent */ - Daemon(const QList>& processList, QObject* parent = nullptr); + explicit Daemon(const QList>& processList, bool _enableAutoStart = true, QObject* parent = nullptr); public slots: @@ -39,6 +39,11 @@ namespace LINGMO_SESSION { void startProcess(const QPair& processInfo); QList> m_processList; + + /** + * @brief Whether to enable auto reload when process exited. + */ + bool m_enableAutoRestart; }; } #endif diff --git a/session/processmanager.cpp b/session/processmanager.cpp index f2364b7..756395c 100755 --- a/session/processmanager.cpp +++ b/session/processmanager.cpp @@ -76,7 +76,7 @@ void ProcessManager::logout() void ProcessManager::startWindowManager() { - QProcess *wmProcess = new QProcess; + auto *wmProcess = new QProcess; wmProcess->start(m_app->wayland() ? "kwin_wayland" : "kwin_x11", QStringList()); @@ -127,7 +127,8 @@ void ProcessManager::startDaemonProcess() void ProcessManager::loadAutoStartProcess() { - QStringList execList; + QList> list; + const QStringList dirs = QStandardPaths::locateAll(QStandardPaths::GenericConfigLocation, QStringLiteral("autostart"), QStandardPaths::LocateDirectory); @@ -139,8 +140,17 @@ void ProcessManager::loadAutoStartProcess() desktop.setIniCodec("UTF-8"); desktop.beginGroup("Desktop Entry"); - if (desktop.contains("OnlyShowIn")) - continue; + // Ignore files the require a specific desktop environment + if (desktop.contains("NotShowIn")) { + const QStringList notShowIn = desktop.value("NotShowIn").toStringList(); + if (notShowIn.contains("Lingmo")) + continue; + } + if (desktop.contains("OnlyShowIn")) { + const QStringList onlyShowIn = desktop.value("OnlyShowIn").toStringList(); + if (!onlyShowIn.contains("Lingmo")) + continue; + } const QString execValue = desktop.value("Exec").toString(); @@ -148,24 +158,22 @@ void ProcessManager::loadAutoStartProcess() if (execValue.contains("gmenudbusmenuproxy")) continue; - if (!execValue.isEmpty()) { - execList << execValue; - } - } - } + // 使用 QProcess::splitCommand 来解析命令和参数 + QStringList args = QProcess::splitCommand(execValue); - for (const QString &exec : execList) { - QProcess *process = new QProcess; - process->setProgram(exec); - process->start(); - process->waitForStarted(); + // 检查是否至少有一个元素(即程序路径) + if (!args.isEmpty()) { + auto program = args.first(); + args.removeFirst(); // 移除程序路径,剩下的都是参数 - if (process->exitCode() == 0) { - m_autoStartProcess.insert(exec, process); - } else { - process->deleteLater(); + list << qMakePair(program, args); + } else { + qWarning() << "Invalid 'Exec' found in file!"; + } } } + + m_userAutoStartD = std::make_shared(list, false); } bool ProcessManager::nativeEventFilter(const QByteArray &eventType, void *message, long *result) diff --git a/session/processmanager.h b/session/processmanager.h index 1ad266b..f6a5562 100755 --- a/session/processmanager.h +++ b/session/processmanager.h @@ -20,6 +20,7 @@ #ifndef PROCESSMANAGER_H #define PROCESSMANAGER_H +#include #include #include #include @@ -47,6 +48,7 @@ class ProcessManager : public QObject, public QAbstractNativeEventFilter /** * @brief Start the user defined autostart process. + * Typically, they are in /.config/autostart/xxx.desktop */ void loadAutoStartProcess(); @@ -63,6 +65,9 @@ class ProcessManager : public QObject, public QAbstractNativeEventFilter // Daemon helper for other daemon components std::shared_ptr m_daemonAutoStartD; + // Daemon helper for User Auto Start Process + std::shared_ptr m_userAutoStartD; + bool m_wmStarted; QEventLoop *m_waitLoop; };