Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions panels/dock/taskmanager/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ add_library(dock-taskmanager SHARED ${DBUS_INTERFACES}
waylandwindowmonitor.h
taskmanagersettings.cpp
taskmanagersettings.h
processinfo.cpp
processinfo.h
)

qt_generate_wayland_protocol_client_sources(dock-taskmanager
Expand Down
72 changes: 72 additions & 0 deletions panels/dock/taskmanager/desktopfileamparser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "abstractwindow.h"
#include "desktopfileamparser.h"
#include "desktopfileabstractparser.h"
#include "processinfo.h"

#include <unistd.h>
#include <sys/syscall.h>
Expand All @@ -31,6 +32,11 @@ namespace dock {
static QDBusServiceWatcher dbusWatcher(AM_DBUS_PATH, QDBusConnection::sessionBus(),
QDBusServiceWatcher::WatchForOwnerChange);

QList<QPair<QString, IdentifyFunc>> DesktopFileAMParser::m_identifyWindowFuns = {
{"PidEnv", &DesktopFileAMParser::identifyWindowPidEnv},
{"AM", &DesktopFileAMParser::identifyWindowAM},
};

DesktopFileAMParser::DesktopFileAMParser(QString id, QObject* parent)
: DesktopfileAbstractParser(id, parent)
{
Expand Down Expand Up @@ -134,6 +140,44 @@ QString DesktopFileAMParser::id2dbusPath(const QString& id)
}

QString DesktopFileAMParser::identifyWindow(QPointer<AbstractWindow> window)
{
for (auto iter = m_identifyWindowFuns.begin(); iter != m_identifyWindowFuns.end(); iter++) {
QString name = iter->first;
IdentifyFunc func = iter->second;
qInfo() << "identifyWindow: try " << name;
QString appId = func(window);
if (!appId.isEmpty()) {
return appId;
}
}

return "";
}

QString DesktopFileAMParser::identifyWindowPidEnv(QPointer<AbstractWindow> window)
{
ProcessInfo process(window->pid());
QString launchedDesktopFile = process.getEnv("GIO_LAUNCHED_DESKTOP_FILE");
QString launchedDesktopFilePidStr = process.getEnv("GIO_LAUNCHED_DESKTOP_FILE_PID");
if (launchedDesktopFile.isEmpty()) {
return "";
}

int launchedDesktopFilePid = launchedDesktopFilePidStr.toInt();
int ppid = process.getPpid();
if (launchedDesktopFilePid != ppid && !isLinglongApp(process)) {
return "";
}

if (!isApplicationDesktop(launchedDesktopFile)) {
return "";
}

QFileInfo fileinfo(launchedDesktopFile);
return fileinfo.completeBaseName();
}

QString DesktopFileAMParser::identifyWindowAM(QPointer<AbstractWindow> window)
{
if (!m_amIsAvaliable) m_amIsAvaliable = QDBusConnection::sessionBus().
interface()->isServiceRegistered(AM_DBUS_PATH);
Expand All @@ -160,6 +204,34 @@ QString DesktopFileAMParser::identifyWindow(QPointer<AbstractWindow> window)
return QString();
}

bool DesktopFileAMParser::isApplicationDesktop(const QString &path) {
for (auto dir : QStandardPaths::standardLocations(QStandardPaths::ApplicationsLocation)) {
if (path.startsWith(dir + QDir::separator())) {
return true;
}
}

return false;
}

bool DesktopFileAMParser::isLinglongApp(ProcessInfo &process)
{
for (ProcessInfo p(process.getPpid()); p.getPid() != 0; p = ProcessInfo(p.getPpid())) {
auto cmdline = p.getCmdLine();
if (cmdline.isEmpty()){
qWarning() << "Failed to get command line of" << p.getPid() << " SKIP it.";
continue;
}
if (p.getCmdLine()[0].indexOf("ll-box") != -1) {
qDebug() << "process ID" << process.getPid() << "is in linglong container,"
<< "ll-box PID" << p.getPid();
return true;
}
}

return false;
}

QString DesktopFileAMParser::identifyType()
{
return QStringLiteral("amAPP");
Expand Down
8 changes: 8 additions & 0 deletions panels/dock/taskmanager/desktopfileamparser.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

namespace dock {
class AbstractWindow;
class ProcessInfo;

typedef std::function<QString (QPointer<AbstractWindow>)> IdentifyFunc;

class DesktopFileAMParser : public DesktopfileAbstractParser
{
Expand Down Expand Up @@ -42,6 +45,10 @@ class DesktopFileAMParser : public DesktopfileAbstractParser
DesktopFileAMParser(QString id, QObject *parent = nullptr);

static QString identifyWindow(QPointer<AbstractWindow> window);
static QString identifyWindowPidEnv(QPointer<AbstractWindow> window);
static QString identifyWindowAM(QPointer<AbstractWindow> window);
static bool isApplicationDesktop(const QString &path);
static bool isLinglongApp(ProcessInfo &process);

private:
QString id2dbusPath(const QString& id);
Expand All @@ -58,6 +65,7 @@ private Q_SLOTS:

private:
inline static bool m_amIsAvaliable;
static QList<QPair<QString, IdentifyFunc>> m_identifyWindowFuns;

QString m_name;
QString m_icon;
Expand Down
220 changes: 220 additions & 0 deletions panels/dock/taskmanager/processinfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
// SPDX-FileCopyrightText: 2018 - 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#include "processinfo.h"

#include <string>
#include <fstream>
#include <unistd.h>

#include <QDir>
#include <QDebug>
#include <QFileInfo>


DS_BEGIN_NAMESPACE
namespace dock {
ProcessInfo::ProcessInfo(int pid)
: m_pid(pid)
, m_ppid(0)

{
if (pid == 0)
return;
m_exe = getExe();
m_cwd = getCwd();
m_cmdLine = getCmdLine();
getStatus();
// 部分root进程在/proc文件系统查找不到exe、cwd、cmdline信息
if (m_exe.isEmpty() || m_cwd.isEmpty() || m_cmdLine.size() == 0) {
m_isValid = false;
return;
}

// args
qInfo() << "ProcessInfo: exe=" << m_exe << " cwd=" << m_cwd << " cmdLine=" << (m_cmdLine[0].isEmpty() ? " " : m_cmdLine[0]);
auto verifyExe = [](QString exe, QString cwd, QString firstArg){
if (firstArg.size() == 0) return false;

QFileInfo info(firstArg);
if (info.completeBaseName() == firstArg) return true;

if (!QDir::isAbsolutePath(firstArg))
firstArg = cwd + firstArg;

return exe == firstArg;
};

if (!m_cmdLine[0].isEmpty()) {
if (!verifyExe(m_exe, m_cwd, m_cmdLine[0])) {
auto parts = m_cmdLine[0].split(' ');
// try again
if (verifyExe(m_exe, m_cwd, parts[0])) {
m_args.append(parts.mid(1, parts.size() - 1));
m_args.append(m_cmdLine.mid(1, m_cmdLine.size() - 1));
}
} else {
m_args.append(m_cmdLine.mid(1, m_cmdLine.size() - 1));
}
}
}

ProcessInfo::ProcessInfo(QStringList cmd)
: m_hasPid(false)
, m_isValid(true)
{
if (cmd.size() == 0) {
m_isValid = false;
return;
}

m_cmdLine = cmd;
m_exe = cmd[0];
m_args.append(cmd.mid(1, cmd.size() - 1));
}

ProcessInfo::~ProcessInfo()
{
}

QString ProcessInfo::getEnv(const QString &key)
{
if (m_environ.size() == 0) getEnviron();
return m_environ[key];
}

Status ProcessInfo::getStatus()
{
if (!m_status.empty()){
return m_status;
}

QString statusFile = getFile("status");

std::ifstream fs(statusFile.toStdString());
if (!fs.is_open()) {
return m_status;
}

std::string tmp = "";
while (std::getline(fs, tmp)) {
auto pos = tmp.find_first_of(':');
if (pos == std::string::npos) {
continue;
}

QString value;
if (pos + 1 < tmp.length()) {
value = QString::fromStdString(tmp.substr(pos + 1));
}

m_status[QString::fromStdString(tmp.substr(0, pos))] = value;
}

return m_status;
}

QStringList ProcessInfo::getCmdLine()
{
if (m_cmdLine.size() == 0) {
QString cmdlineFile = getFile("cmdline");
m_cmdLine = readFile(cmdlineFile);
}

return m_cmdLine;
}

QStringList ProcessInfo::getArgs()
{
return m_args;
}

int ProcessInfo::getPid()
{

return m_pid;
}

int ProcessInfo::getPpid()
{
if (m_ppid == 0) {
if (m_status.find("PPid") != m_status.end()) {
m_ppid = std::stoi(m_status["PPid"].toStdString());
}
}
return m_ppid;
}

bool ProcessInfo::initWithPid()
{
return m_hasPid;
}

bool ProcessInfo::isValid()
{
return m_isValid;
}

QString ProcessInfo::getExe()
{
if (m_exe.isEmpty()) {
QString cmdLineFile = getFile("exe");
QFileInfo path(cmdLineFile);
m_exe = path.canonicalFilePath();
}

return m_exe;
}

bool ProcessInfo::isExist()
{
QString procDir = "/proc/" + QString::number(m_pid);
return QFile::exists(procDir);
}

QStringList ProcessInfo::readFile(const QString &filePath)
{
QStringList ret;
std::ifstream fs(filePath.toStdString());
if (!fs.is_open()) {
return ret;
}

std::string tmp;
while (std::getline(fs, tmp, '\0')) {
ret.append(QString::fromStdString(tmp));
}
return ret;
}

QString ProcessInfo::getFile(const QString &file)
{
return QString("/proc/").append(QString::number(m_pid).append('/').append(file));
}

QString ProcessInfo::getCwd()
{
if (m_cwd.isEmpty()) {
QString cwdFile = getFile("cwd");
QFileInfo path(cwdFile);
m_cwd = path.canonicalFilePath();
}
return m_cwd;
}

QMap<QString, QString> ProcessInfo::getEnviron()
{
if (m_environ.size() == 0) {
QString envFile = getFile("environ");
QStringList contents = readFile(envFile);
for (auto line : contents){
int index = line.indexOf('=');
m_environ.insert(line.left(index), line.right(line.size() - index - 1));
}
}
return m_environ;
}

}
DS_END_NAMESPACE
Loading