From 62a5b07ce330c5ad51ffe593ea6950b08b77c6e3 Mon Sep 17 00:00:00 2001 From: Ivy233 Date: Wed, 14 Jan 2026 18:22:09 +0800 Subject: [PATCH] feat: add category-based skip list for cgroups grouping MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 新增 DConfig 配置项 cgroupsBasedGroupingSkipCategories 2. 默认跳过 TerminalEmulator 类别的应用,避免终端中启动的程序被错误识别 3. 在 dde-apps 的 AppItem 中添加 categories 属性 4. 在 AppItemModel 中添加 CategoriesRole 5. 在 AMAppItem 构造函数中保存从 AM 获取的 categories 6. 实现 shouldSkipCgroupsByCategories() 函数,从 dde-apps 缓存读取 categories 7. 提取 tryMatchByApplicationManager() 函数,优化代码结构 8. 使用 TaskManager::CategoriesRole 枚举常量替代运行时查找 9. 优化迭代逻辑,迭代 skipCategories 而非 categories,提升性能 10. 在窗口匹配流程中集成类别检查逻辑 Log: 新增基于应用类别的 cgroups 分组跳过列表,解决终端中启动的图形程序被错误归类的问题 Influence: 1. 测试在 Alacritty 等终端模拟器中启动图形应用 2. 验证新启动的应用在任务栏显示独立图标 3. 验证 categories 从 dde-apps 缓存读取,无额外 DBus 调用 4. 检查 DConfig 配置项可正常读取和修改 5. 确认不影响非终端类应用的正常分组行为 6. 验证深度终端等原有白名单应用仍正常工作 7. 确认代码结构优化不影响功能正确性 PMS: TASK-384865 --- applets/dde-apps/amappitem.cpp | 1 + applets/dde-apps/appitem.cpp | 10 +++ applets/dde-apps/appitem.h | 3 + applets/dde-apps/appitemmodel.cpp | 1 + applets/dde-apps/appitemmodel.h | 1 + .../org.deepin.ds.dock.taskmanager.json | 11 +++ panels/dock/taskmanager/globals.h | 1 + panels/dock/taskmanager/taskmanager.cpp | 72 ++++++++++++++++--- panels/dock/taskmanager/taskmanager.h | 1 + .../dock/taskmanager/taskmanagersettings.cpp | 6 ++ panels/dock/taskmanager/taskmanagersettings.h | 2 + 11 files changed, 99 insertions(+), 10 deletions(-) diff --git a/applets/dde-apps/amappitem.cpp b/applets/dde-apps/amappitem.cpp index 6cf3261a9..550b3d98c 100644 --- a/applets/dde-apps/amappitem.cpp +++ b/applets/dde-apps/amappitem.cpp @@ -49,6 +49,7 @@ AMAppItem::AMAppItem(const QDBusObjectPath &path, const ObjectInterfaceMap &sour auto categories = appInfo.value(u8"Categories").toStringList(); AppItem::setDDECategories(AppItemModel::DDECategories(CategoryUtils::parseBestMatchedCategory(categories))); + AppItem::setCategories(categories); auto lastLaunchedTime = appInfo.value(u8"LastLaunchedTime").toULongLong(); AppItem::setLastLaunchedTime(lastLaunchedTime); diff --git a/applets/dde-apps/appitem.cpp b/applets/dde-apps/appitem.cpp index bb7577833..5e9843b3b 100644 --- a/applets/dde-apps/appitem.cpp +++ b/applets/dde-apps/appitem.cpp @@ -99,6 +99,16 @@ void AppItem::setDDECategories(const AppItemModel::DDECategories &categories) return setData(categories, AppItemModel::DDECategoryRole); } +QStringList AppItem::categories() const +{ + return data(AppItemModel::CategoriesRole).toStringList(); +} + +void AppItem::setCategories(const QStringList &categories) +{ + return setData(categories, AppItemModel::CategoriesRole); +} + QString AppItem::actions() const { return data(AppItemModel::ActionsRole).toString(); diff --git a/applets/dde-apps/appitem.h b/applets/dde-apps/appitem.h index f67926a61..0dad6edf1 100644 --- a/applets/dde-apps/appitem.h +++ b/applets/dde-apps/appitem.h @@ -39,6 +39,9 @@ class AppItem : public QStandardItem AppItemModel::DDECategories ddeCategories() const; void setDDECategories(const AppItemModel::DDECategories &categories); + QStringList categories() const; + void setCategories(const QStringList &categories); + QString actions() const; void setActions(const QString &actions); diff --git a/applets/dde-apps/appitemmodel.cpp b/applets/dde-apps/appitemmodel.cpp index aa4db5811..6f9ab9534 100644 --- a/applets/dde-apps/appitemmodel.cpp +++ b/applets/dde-apps/appitemmodel.cpp @@ -20,6 +20,7 @@ QHash AppItemModel::roleNames() const {AppItemModel::NoDisplayRole, QByteArrayLiteral("noDisplay")}, {AppItemModel::ActionsRole, QByteArrayLiteral("actions")}, {AppItemModel::DDECategoryRole, QByteArrayLiteral("ddeCategory")}, + {AppItemModel::CategoriesRole, QByteArrayLiteral("categories")}, {AppItemModel::InstalledTimeRole, QByteArrayLiteral("installedTime")}, {AppItemModel::LastLaunchedTimeRole, QByteArrayLiteral("lastLaunchedTime")}, {AppItemModel::LaunchedTimesRole, QByteArrayLiteral("launchedTimes")}, diff --git a/applets/dde-apps/appitemmodel.h b/applets/dde-apps/appitemmodel.h index 3626e55bf..4b75314c1 100644 --- a/applets/dde-apps/appitemmodel.h +++ b/applets/dde-apps/appitemmodel.h @@ -19,6 +19,7 @@ class AppItemModel : public QStandardItemModel NoDisplayRole, ActionsRole, DDECategoryRole, + CategoriesRole, InstalledTimeRole, LastLaunchedTimeRole, LaunchedTimesRole, diff --git a/panels/dock/taskmanager/dconfig/org.deepin.ds.dock.taskmanager.json b/panels/dock/taskmanager/dconfig/org.deepin.ds.dock.taskmanager.json index cf7141f78..f94670831 100644 --- a/panels/dock/taskmanager/dconfig/org.deepin.ds.dock.taskmanager.json +++ b/panels/dock/taskmanager/dconfig/org.deepin.ds.dock.taskmanager.json @@ -55,6 +55,17 @@ "permissions": "readwrite", "visibility": "private" }, + "cgroupsBasedGroupingSkipCategories": { + "value": ["TerminalEmulator"], + "serial": 0, + "flags": [], + "name": "CGroups-Based Grouping Skipped Categories", + "name[zh_CN]": "基于 cgroups 的任务图标分组所应跳过的应用类别列表", + "description": "List of desktop file categories that cgroups-based grouping should skip checking", + "description[zh_CN]": "一个表示基于 CGroups 的应用分组所应当跳过的应用类别列表", + "permissions": "readwrite", + "visibility": "private" + }, "Docked_Items": { "value": ["id: dde-file-manager,type: amAPP", "id: org.deepin.browser,type: amAPP", "id: deepin-app-store,type: amAPP", "id: org.deepin.dde.control-center, type: amAPP", "id: deepin-music,type: amAPP", "id: deepin-editor,type: amAPP", "id: deepin-mail,type: amAPP","id: deepin-terminal,type: amAPP","id: dde-calendar,type: amAPP", "id: deepin-calculator,type: amAPP"], "serial": 0, diff --git a/panels/dock/taskmanager/globals.h b/panels/dock/taskmanager/globals.h index 32c57697d..240f17969 100644 --- a/panels/dock/taskmanager/globals.h +++ b/panels/dock/taskmanager/globals.h @@ -22,6 +22,7 @@ static inline const QString TASKMANAGER_ALLOWFOCEQUIT_KEY = "Allow_Force_Quit"; static inline const QString TASKMANAGER_WINDOWSPLIT_KEY = "noTaskGrouping"; static inline const QString TASKMANAGER_CGROUPS_BASED_GROUPING_KEY = "cgroupsBasedGrouping"; static inline const QString TASKMANAGER_CGROUPS_BASED_GROUPING_SKIP_APPIDS = "cgroupsBasedGroupingSkipAppIds"; +static inline const QString TASKMANAGER_CGROUPS_BASED_GROUPING_SKIP_CATEGORIES = "cgroupsBasedGroupingSkipCategories"; static inline const QString TASKMANAGER_DOCKEDITEMS_KEY = "Docked_Items"; constexpr auto TASKMANAGER_DOCKEDELEMENTS_KEY = "dockedElements"; diff --git a/panels/dock/taskmanager/taskmanager.cpp b/panels/dock/taskmanager/taskmanager.cpp index cc1b2d969..f55b5f7bb 100644 --- a/panels/dock/taskmanager/taskmanager.cpp +++ b/panels/dock/taskmanager/taskmanager.cpp @@ -63,10 +63,68 @@ static QString getDesktopIdByPid(const QStringList &identifies) qCDebug(taskManagerLog) << "appId is empty, AM failed to identify window with pid:" << windowPid; return {}; } - + return QString::fromUtf8(appId); } +// 检查应用的 Categories 是否在跳过列表中 +static bool shouldSkipCgroupsByCategories(const QString &desktopId, QAbstractItemModel *activeAppModel, const QHash &roleNames) +{ + auto skipCategories = Settings->cgroupsBasedGroupingSkipCategories(); + if (skipCategories.isEmpty() || desktopId.isEmpty()) { + return false; + } + + QStringList categories; + + // 从 dde-apps 的 AppItem 读取 categories + if (activeAppModel) { + auto existingItem = activeAppModel->match(activeAppModel->index(0, 0), roleNames.key("desktopId"), desktopId, 1, Qt::MatchFixedString | Qt::MatchWrap).value(0); + if (existingItem.isValid()) { + categories = activeAppModel->data(existingItem, TaskManager::CategoriesRole).toStringList(); + } + } + + if (categories.isEmpty()) { + return false; + } + + // 检查是否有任何 skipCategory 在应用的 categories 中 + for (const QString &skipCategory : skipCategories) { + if (categories.contains(skipCategory)) { + qCDebug(taskManagerLog) << "Skipping cgroups grouping for" << desktopId + << "due to category:" << skipCategory; + return true; + } + } + + return false; +} + +// 尝试通过 AM(Application Manager) 匹配应用程序 +static QModelIndex tryMatchByApplicationManager(const QStringList &identifies, + QAbstractItemModel *model, + const QHash &roleNames) +{ + if (!Settings->cgroupsBasedGrouping()) { + return QModelIndex(); + } + + auto desktopId = getDesktopIdByPid(identifies); + if (desktopId.isEmpty() || + Settings->cgroupsBasedGroupingSkipIds().contains(desktopId) || + shouldSkipCgroupsByCategories(desktopId, model, roleNames)) { + return QModelIndex(); + } + + auto res = model->match(model->index(0, 0), roleNames.key(MODEL_DESKTOPID), + desktopId, 1, Qt::MatchFixedString | Qt::MatchWrap).value(0); + if (res.isValid()) { + qCDebug(taskManagerLog) << "matched by AM desktop ID:" << desktopId << res; + } + return res; +} + class BoolFilterModel : public QSortFilterProxyModel, public AbstractTaskManagerInterface { Q_OBJECT @@ -157,15 +215,9 @@ bool TaskManager::init() } // 尝试通过AM(Application Manager)匹配应用程序 - if (Settings->cgroupsBasedGrouping()) { - auto desktopId = getDesktopIdByPid(identifies); - if (!desktopId.isEmpty() && !Settings->cgroupsBasedGroupingSkipIds().contains(desktopId)) { - auto res = model->match(model->index(0, 0), roleNames.key(MODEL_DESKTOPID), desktopId, 1, Qt::MatchFixedString | Qt::MatchWrap).value(0); - if (res.isValid()) { - qCDebug(taskManagerLog) << "matched by AM desktop ID:" << desktopId << res; - return res; - } - } + auto amMatchResult = tryMatchByApplicationManager(identifies, model, roleNames); + if (amMatchResult.isValid()) { + return amMatchResult; } auto res = model->match(model->index(0, 0), roleNames.key(MODEL_DESKTOPID), identifies.value(0), 1, Qt::MatchEndsWith); diff --git a/panels/dock/taskmanager/taskmanager.h b/panels/dock/taskmanager/taskmanager.h index d4cabf9c8..6c4a61ac8 100644 --- a/panels/dock/taskmanager/taskmanager.h +++ b/panels/dock/taskmanager/taskmanager.h @@ -51,6 +51,7 @@ class TaskManager : public DS_NAMESPACE::DContainment, public AbstractTaskManage NoDisplayRole, ActionsRole, DDECategoryRole, + CategoriesRole, InstalledTimeRole, LastLaunchedTimeRole, LaunchedTimesRole, diff --git a/panels/dock/taskmanager/taskmanagersettings.cpp b/panels/dock/taskmanager/taskmanagersettings.cpp index 02e03f659..0bed074ba 100644 --- a/panels/dock/taskmanager/taskmanagersettings.cpp +++ b/panels/dock/taskmanager/taskmanagersettings.cpp @@ -54,6 +54,7 @@ TaskManagerSettings::TaskManagerSettings(QObject *parent) m_cgroupsBasedGrouping = m_taskManagerDconfig->value(TASKMANAGER_CGROUPS_BASED_GROUPING_KEY, true).toBool(); m_dockedElements = m_taskManagerDconfig->value(TASKMANAGER_DOCKEDELEMENTS_KEY, {}).toStringList(); m_cgroupsBasedGroupingSkipAppIds = m_taskManagerDconfig->value(TASKMANAGER_CGROUPS_BASED_GROUPING_SKIP_APPIDS, {"deepin-terminal"}).toStringList(); + m_cgroupsBasedGroupingSkipCategories = m_taskManagerDconfig->value(TASKMANAGER_CGROUPS_BASED_GROUPING_SKIP_CATEGORIES, {"TerminalEmulator"}).toStringList(); migrateFromDockedItems(); } @@ -89,6 +90,11 @@ QStringList TaskManagerSettings::cgroupsBasedGroupingSkipIds() const return m_cgroupsBasedGroupingSkipAppIds; } +QStringList TaskManagerSettings::cgroupsBasedGroupingSkipCategories() const +{ + return m_cgroupsBasedGroupingSkipCategories; +} + QStringList TaskManagerSettings::dockedElements() const { return m_dockedElements; diff --git a/panels/dock/taskmanager/taskmanagersettings.h b/panels/dock/taskmanager/taskmanagersettings.h index 03459b503..aeb369e22 100644 --- a/panels/dock/taskmanager/taskmanagersettings.h +++ b/panels/dock/taskmanager/taskmanagersettings.h @@ -31,6 +31,7 @@ class TaskManagerSettings : public QObject bool cgroupsBasedGrouping() const; QStringList cgroupsBasedGroupingSkipIds() const; + QStringList cgroupsBasedGroupingSkipCategories() const; void setDockedElements(const QStringList &elements); void toggleDockedElement(const QString &element); @@ -58,5 +59,6 @@ class TaskManagerSettings : public QObject bool m_cgroupsBasedGrouping; QStringList m_dockedElements; QStringList m_cgroupsBasedGroupingSkipAppIds; + QStringList m_cgroupsBasedGroupingSkipCategories; }; }