[Feedback on issues] dde-shell dock 图标映射错乱 bug
Tofloor
poster avatar
金城
deepin
2026-06-11 11:09
Author

dde-shell dock 图标映射错乱 bug

环境

  • 系统:Deepin 25 (Desktop Community)
  • dde-shell 版本:2.0.42
  • 桌面协议:X11 (xcb)
  • 运行时长:连续运行 20+ 小时后触发

现象

任务栏(dock)的图标与对应窗口的映射发生错乱。点击某个应用图标时,激活的是另一个应用的窗口。例如:点击"终端"图标弹出的是 SecureCRT,点击"微信"图标弹出的是终端。

已验证的事实

以下信息通过实际工具输出确认,非推测:

  1. DBus 模型层数据正确 — 通过 busctl --user tree org.deepin.ds.Dockbusctl --user introspect 实际读取了每个 AppItem 的 id/name/icon 属性,数据与预期一致
  2. 视觉表现与模型数据不对应 — 用户看到的图标排列和点击行为与 DBus 中记录的 AppItem 顺序/标识不一致
  3. 重启 dde-shell@DDE.servicesystemctl --user restart dde-shell@DDE.service)后问题消失 — 实际执行并验证
  4. 非持久化数据损坏 — 重启即修复说明问题状态在内存中,不在配置文件

架构分析(基于源码阅读,非运行时调试)

阅读了 dde-shell 2.0.42 源码(克隆自 linuxdeepin/dde-shell):

数据模型链:

DockGlobalElementModel (QAbstractListModel, 维护 m_data)
  → DockItemModel (QAbstractProxyModel, 1:1 代理)
    → QML DelegateModel (visualModel, 维护 items-to-model 映射表)
      → 每个 delegate 使用 visualModel.modelIndex(index) 取模型索引

点击处理路径(TaskManager.qml 第 85-139 行):

model: DelegateModel {
    id: visualModel
    model: taskmanager.Applet.dataModel  // DockItemModel
    delegate: Item {
        required property int index
        property var modelIndex: visualModel.modelIndex(index)
        onClicked: {
            let index = root.modelIndex;
            TaskManager.requestActivate(index);
        }
    }
}

注意到的代码特征:

DockGlobalElementModeldockglobalelementmodel.cpp)中大量使用 Qt::QueuedConnection 处理模型变更信号:

  • 第 57 行:m_appsModelrowsRemoved
  • 第 124 行:m_activeAppModelrowsInserted
  • 第 186 行:m_activeAppModelrowsRemoved
  • 第 212 行:m_activeAppModeldataChanged

推测(未通过运行时调试确认)

以下为基于代码分析的推测,未在运行中的进程内验证:

DBus 数据正确但视觉映射错误,说明断层在 DBus 暴露的 C++ 模型层之下、QML 渲染层之上。DelegateModel 的 modelIndex(index) 是唯一位于这个区间且维护独立映射表的组件。

可能机制:Qt 的 DelegateModel 内部维护 items-to-model 映射表,通过监听模型的 rowsInserted/rowsRemoved 等信号增量更新。当 DockGlobalElementModel 通过 QueuedConnection 异步发出变更信号时,若短时间内有多个插入/删除/移动操作交叉,DelegateModel 收到的增量更新可能与实际模型状态产生偏差。长时间运行后偏差累积,映射表错乱。

需要开发者确认的点:

  1. 运行中的 DelegateModel 内部映射表是否确实偏离了底层模型
  2. QueuedConnection 是否为实际诱因,或存在其他因素
  3. 是否有 DelegateModel 复用 delegate 实例时未正确更新 modelIndex 绑定的问题

建议

  1. 在 DelegateModel 模型变更的关键路径上增加诊断日志,对比 visualModel.modelIndex(index) 与实际模型索引
  2. 评估将 QueuedConnection 改为 DirectConnection 的可行性
  3. 考虑在模型发生批量变更后强制 DelegateModel 全量刷新而非依赖增量更新

相关文件

  • panels/dock/taskmanager/package/TaskManager.qml — DelegateModel 使用处
  • panels/dock/taskmanager/dockglobalelementmodel.cpp — 数据模型,QueuedConnection 信号处理
  • panels/dock/taskmanager/dockitemmodel.cpp — QAbstractProxyModel 代理层
Reply Favorite View the author
All Replies

No replies yet