Skip to content

fix: improve window icon handling and model reset logic#1578

Open
wjyrich wants to merge 1 commit intolinuxdeepin:masterfrom
wjyrich:feat-hoverpreview
Open

fix: improve window icon handling and model reset logic#1578
wjyrich wants to merge 1 commit intolinuxdeepin:masterfrom
wjyrich:feat-hoverpreview

Conversation

@wjyrich
Copy link
Copy Markdown
Contributor

@wjyrich wjyrich commented Apr 29, 2026

  1. Fixed DockCombineModel to respect window split setting for icon display
  2. Simplified DockItemModel source model change to use full reset instead of incremental updates
  3. Optimized AppItem icon loading to avoid retaining while window is active
  4. Added explicit icon update for X11 windows on mapping

The changes fix icon display inconsistencies where window-specific icons were incorrectly overridden by application icons when window split is disabled. The model reset simplification fixes edge cases where incremental row updates could cause state corruption. The icon loading optimization improves performance by not retaining loading states for active windows.

Log: Fixed window icon display logic and model synchronization

Influence:

  1. Test dock icon display with multiple windows, verify window-specific icons show correctly
  2. Test window split mode toggle, verify icon behavior changes accordingly
  3. Test quick window switching, verify no icon loading artifacts
  4. Test X11 window mapping, verify icons update immediately
  5. Test model source changes, verify no crashes or data corruption
  6. Test with high window count, verify performance is not degraded

fix: 改进窗口图标处理和模型重置逻辑

  1. 修复 DockCombineModel 中图标显示逻辑,遵循窗口分裂设置
  2. 简化 DockItemModel 源模型变更时的处理,使用全量重置替代增量更新
  3. 优化 AppItem 图标加载,窗口活跃时不再保留加载状态
  4. 为 X11 窗口映射时添加显式图标更新

这些修改修复了当窗口分裂功能禁用时,窗口特定图标被应用程序图标错误覆盖的
问题。模型重置的简化修复了增量行更新可能导致的内部状态损坏问题。图标加载
优化通过不在活动窗口中保留加载状态来提高性能。

Log: 修复了窗口图标显示逻辑和模型同步问题

Influence:

  1. 测试多窗口 dock 图标显示,验证窗口特定图标正确显示
  2. 测试窗口分裂模式切换,验证图标行为相应变更
  3. 测试快速窗口切换,验证无图标加载残留
  4. 测试 X11 窗口映射,验证图标立即更新
  5. 测试模型源变更,验证无崩溃或数据损坏
  6. 测试高窗口数量场景,验证性能不下降

PMS: TASK-389031

Summary by Sourcery

Improve dock task manager icon handling and model synchronization for better window-specific icon display and stability.

Bug Fixes:

  • Ensure DockCombineModel prefers window icons over application icons when window split mode is enabled and avoids overriding valid window icons.
  • Prevent potential model state corruption by resetting DockItemModel fully when the source model changes instead of performing partial row updates.
  • Ensure X11 windows refresh their icons immediately upon mapping to avoid stale or missing icons.

Enhancements:

  • Adjust AppItem icon loading behavior to avoid retaining loading state for active windows, reducing visual artifacts and improving performance.

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: wjyrich

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 29, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Refactors dock task manager models and related window/icon handling to use a full model reset on source changes, respect window-split settings for choosing window vs. app icons, optimize QML icon loading for active windows, and immediately refresh X11 window icons upon mapping.

Sequence diagram for X11 window mapping and immediate icon update

sequenceDiagram
    participant XServer
    participant X11WindowMonitor
    participant Window
    participant AbstractWindowMonitor

    XServer->>X11WindowMonitor: MapNotify(xcb_window)
    activate X11WindowMonitor
    X11WindowMonitor->>X11WindowMonitor: onWindowMapped(xcb_window)
    X11WindowMonitor->>X11WindowMonitor: xcb_change_window_attributes
    X11WindowMonitor->>Window: trackWindow(window)
    X11WindowMonitor->>Window: updateIcon()
    X11WindowMonitor->>AbstractWindowMonitor: windowAdded(window)
    deactivate X11WindowMonitor
Loading

Class diagram for updated dock task manager models and window/icon handling

classDiagram
    class DockItemModel {
        +bool m_isUpdating
        +void setSourceModel(QAbstractItemModel *model)
    }

    class QAbstractProxyModel {
        +void setSourceModel(QAbstractItemModel *model)
        +int rowCount()
    }

    DockItemModel --|> QAbstractProxyModel

    class DockCombineModel {
        +QVariant data(const QModelIndex &index, int role) const
        -QHash<int,int> m_roleMaps
        +DockCombineModel(QAbstractItemModel *major, QAbstractItemModel *minor, int majorRoles, CombineFunc func, QObject *parent)
    }

    class RoleCombineModel {
        +QVariant data(const QModelIndex &index, int role) const
    }

    DockCombineModel --|> RoleCombineModel

    class TaskManager {
        <<enumeration>>
        +int IconNameRole
        +int WinIconRole
    }

    DockCombineModel ..> TaskManager : uses roles

    class TaskManagerSettings {
        +static TaskManagerSettings* instance()
        +bool isWindowSplit() const
    }

    DockCombineModel ..> TaskManagerSettings : queries isWindowSplit

    class X11WindowMonitor {
        +void onWindowMapped(xcb_window_t xcb_window)
        +void trackWindow(Window *window)
    }

    class AbstractWindowMonitor {
        +void windowAdded(QPointer<AbstractWindow> window)
    }

    X11WindowMonitor --|> AbstractWindowMonitor

    class Window {
        +void updateIcon()
    }

    X11WindowMonitor ..> Window : trackWindow

    class AppItem {
        +bool titleActive
        +Image iconImage
    }

    class Image {
        +bool retainWhileLoading
    }

    AppItem *-- Image : contains iconImage
Loading

Flow diagram for DockCombineModel icon selection logic

flowchart TD
    A(Start) --> B[Request data for IconNameRole]
    B --> C[Read winIcon from WinIconRole]
    C --> D{isWindowSplit and winIcon not empty}
    D -- Yes --> E[Return winIcon]
    D -- No --> F[Read icon from IconNameRole]
    F --> G{icon empty}
    G -- Yes --> H[Set icon to winIcon]
    G -- No --> I[Keep app icon]
    H --> J[Return icon]
    I --> J[Return icon]
    E --> K(End)
    J --> K(End)
Loading

Flow diagram for DockItemModel source model reset logic

flowchart TD
    A(Start setSourceModel) --> B{Existing sourceModel}
    B -- Yes --> C[Disconnect old source model signals]
    B -- No --> D[Skip disconnect]
    C --> E
    D --> E
    E[beginResetModel] --> F["QAbstractProxyModel::setSourceModel new model"]
    F --> G[endResetModel]
    G --> H[Connect rowsInserted, rowsRemoved, rowsMoved, dataChanged signals]
    H --> I[Set m_isUpdating to false]
    I --> J(End)
Loading

File-Level Changes

Change Details Files
Switch DockItemModel source model updates to a full model reset instead of manual row insert/remove and dataChanged handling.
  • Wrap QAbstractProxyModel::setSourceModel in beginResetModel/endResetModel when changing the source model.
  • Remove manual row count comparison and beginInsertRows/beginRemoveRows logic.
  • Remove explicit dataChanged emission after adjusting rows and rely on the reset to notify views.
  • Keep existing row-inserted/removed/moved signal connections unchanged.
panels/dock/taskmanager/dockitemmodel.cpp
Adjust DockCombineModel icon selection to respect window-split settings and favor per-window icons only when appropriate.
  • Include TaskManagerSettings to access dock configuration.
  • Retrieve the window icon separately and return it directly when non-empty and window split is enabled.
  • Fall back to the application icon first, and only then to the window icon if the app icon is empty, when window split is disabled.
  • Update SPDX copyright header to cover years 2025-2026.
panels/dock/taskmanager/dockcombinemodel.cpp
Optimize QML AppItem icon loading behavior for active windows to avoid unnecessary retention of loading placeholders.
  • Change the Image element's retainWhileLoading property to be disabled while the window title is active by binding it to !root.titleActive.
panels/dock/taskmanager/package/AppItem.qml
Ensure X11 window icons are refreshed immediately when a window is mapped.
  • After tracking a newly mapped X11 window, explicitly call updateIcon() before emitting windowAdded.
  • Leave existing X11 event mask setup and windowAdded emission logic intact.
panels/dock/taskmanager/x11windowmonitor.cpp

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • In DockItemModel::setSourceModel, consider skipping the beginResetModel/endResetModel path when the new source model is identical to the current one to avoid unnecessary full model resets and view churn.
  • DockCombineModel::data now depends on TaskManagerSettings::isWindowSplit(), but the model does not emit any dataChanged signals when this setting toggles; consider listening to the setting change and triggering a suitable dataChanged/model reset so views update their icons immediately when the split mode changes.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In DockItemModel::setSourceModel, consider skipping the beginResetModel/endResetModel path when the new source model is identical to the current one to avoid unnecessary full model resets and view churn.
- DockCombineModel::data now depends on TaskManagerSettings::isWindowSplit(), but the model does not emit any dataChanged signals when this setting toggles; consider listening to the setting change and triggering a suitable dataChanged/model reset so views update their icons immediately when the split mode changes.

## Individual Comments

### Comment 1
<location path="panels/dock/taskmanager/x11windowmonitor.cpp" line_range="189" />
<code_context>
     xcb_change_window_attributes(X11->getXcbConnection(), xcb_window, XCB_CW_EVENT_MASK, value_list);
     trackWindow(window.get());
+
+    window->updateIcon();
     Q_EMIT AbstractWindowMonitor::windowAdded(static_cast<QPointer<AbstractWindow>>(window.get()));
 }
</code_context>
<issue_to_address>
**question (bug_risk):** Check for any ordering assumptions between `updateIcon()` and `windowAdded`.

Calling `updateIcon()` before emitting `windowAdded` changes the lifecycle: listeners now see a window whose icon may already be updated, and any signals from `updateIcon()` fire first. Please confirm that no existing `windowAdded` consumers assume they run before icon‑related updates; if they do, consider keeping `updateIcon()` after `windowAdded` or clearly documenting this new ordering.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

xcb_change_window_attributes(X11->getXcbConnection(), xcb_window, XCB_CW_EVENT_MASK, value_list);
trackWindow(window.get());

window->updateIcon();
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

question (bug_risk): Check for any ordering assumptions between updateIcon() and windowAdded.

Calling updateIcon() before emitting windowAdded changes the lifecycle: listeners now see a window whose icon may already be updated, and any signals from updateIcon() fire first. Please confirm that no existing windowAdded consumers assume they run before icon‑related updates; if they do, consider keeping updateIcon() after windowAdded or clearly documenting this new ordering.

@deepin-bot
Copy link
Copy Markdown

deepin-bot Bot commented Apr 29, 2026

TAG Bot

New tag: 2.0.39
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1580

@wjyrich wjyrich force-pushed the feat-hoverpreview branch from 9380555 to a8ac6c7 Compare May 6, 2026 02:24
1. Add a new dconfig setting "windowIconWhitelist" with default value
["wechat"]
2. When window split mode is enabled, the dock now checks the whitelist
to decide whether to use window icons instead of app icons for specific
applications
3. Fix model reset in DockItemModel::setSourceModel to use
beginResetModel/endResetModel instead of manual row insertion/removal
for better model consistency
4. Update X11 window monitor to trigger icon update when a new window
is mapped

The window icon whitelist is needed for apps like WeChat that provide
superior window icon quality compared to their app icons, enhancing the
visual experience when window split is disabled.

Log: Added window icon whitelist config for dock task manager

Influence:
1. Verify WeChat and other whitelisted apps display correct icons when
window split is disabled
2. Test default whitelist behavior with WeChat running
3. Check that non-whitelisted apps still use app icons when window split
is disabled
4. Test the new dconfig setting can be modified and persists correctly
5. Ensure DockItemModel resets work correctly without data corruption
6. Verify X11 window monitor still functions properly with icon update
call

feat: 为任务栏任务管理器添加窗口图标白名单功能

1. 添加新的 dconfig 设置"windowIconWhitelist",默认值为["wechat"]
2. 当窗口拆分模式启用时,任务栏会检查白名单,决定是否对特定应用使用窗口
图标而非应用图标
3. 修复 DockItemModel::setSourceModel 中的模型重置,改用
beginResetModel/endResetModel 替代手动行插入/删除,以提高模型一致性
4. 更新 X11 窗口监视器,在新窗口映射时触发图标更新

对于微信等提供比应用图标更优质窗口图标的应用,窗口图标白名单是必要的,可
在窗口拆分禁用时提升视觉体验。

Log: 为任务栏添加窗口图标白名单配置

Influence:
1. 验证在白名单中的应用(如微信)在禁用窗口拆分时显示正确图标
2. 使用微信测试默认白名单行为
3. 检查非白名单应用在禁用窗口拆分时仍使用应用图标
4. 测试新的 dconfig 设置可以被修改并持久保存
5. 确保 DockItemModel 重置操作正常,无数据损坏
6. 验证 X11 窗口监视器在添加图标更新调用后仍正常工作

PMS: TASK-389031
@wjyrich wjyrich force-pushed the feat-hoverpreview branch from a8ac6c7 to 7907104 Compare May 6, 2026 02:27
@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这份代码diff主要实现了在Dock任务栏中新增"窗口图标白名单"功能,允许在特定条件下(窗口合并关闭时)优先使用窗口图标而非应用图标。以下是对代码的详细审查意见:

1. 语法与逻辑审查

dockcombinemodel.cpp

  • 逻辑改进:在 IconNameRole 的处理中,使用了 desktopId.contains(id) 来判断应用是否在白名单中。这存在潜在的逻辑风险。
    • 问题contains 是子串匹配。如果白名单中有 chat,那么 weixinkchat 等应用也会被匹配到,导致非预期的行为。
    • 建议:通常 desktopId(如 com.weixin.WeChat.desktop)与应用标识符(如 wechat)的匹配应当更精确。如果白名单存储的是完整的 desktop file basename(如 com.weixin.WeChat),建议使用 QString::compare 或直接相等判断。如果白名单存储的是简短ID,建议至少确认 desktopId 的结尾或特定部分匹配,或者确认 desktopId 本身就是简短ID。
    • 代码示例
      // 假设白名单存的是desktop file的basename,建议改为:
      if (desktopId == id + ".desktop" || desktopId == id) { ... }
      // 或者如果确定desktopId就是简短ID:
      if (desktopId == id) { ... }

dockitemmodel.cpp

  • 逻辑改进setSourceModel 中将原本精细的 beginInsertRows / beginRemoveRows / dataChanged 逻辑改为了 beginResetModel / endResetModel
    • 问题:这是一个较大的改动。beginResetModel 会导致代理模型(如QListView)认为整个模型都被销毁并重建了。这虽然简化了代码逻辑,但会导致视图丢失当前的滚动位置、选中状态和展开状态(如果是树形模型),且性能开销较大(触发全量重绘)。
    • 建议:除非原代码在处理模型替换时存在严重的Bug或极端复杂的情况,否则不建议为了简化代码而牺牲用户体验和性能。建议保留原有的增量更新逻辑,或者确认该场景下视图状态丢失是可以接受的。

x11windowmonitor.cpp

  • 逻辑改进:在 onWindowMapped 中添加了 window->updateIcon()
    • 问题:这看起来是为了配合白名单功能,在窗口创建时强制更新一次图标。逻辑上是合理的,但需确保 updateIcon() 方法内部是高效的,不会阻塞主线程或重复获取资源。

2. 代码质量

  • 命名规范
    • windowIconWhitelist 命名清晰,符合驼峰命名法。
    • TASKMANAGER_WINDOW_ICON_WHITELIST_KEY 常量命名符合宏命名规范。
  • 注释
    • 缺少对新增逻辑的注释。例如,在 dockcombinemodel.cpp 中判断白名单的逻辑块前,建议添加注释说明为何要检查 isWindowSplit() 以及白名单匹配的意图。
  • 代码复用
    • dockcombinemodel.cpp 中获取 whitelistdesktopId 的逻辑清晰,但建议将白名单匹配逻辑提取为一个私有辅助函数(如 isInWindowIconWhitelist),以提高可读性和可测试性。

3. 代码性能

  • dockcombinemodel.cpp
    • TaskManagerSettings::instance()->windowIconWhitelist() 每次调用都会返回一个 QStringList。如果这个列表很长,且 data() 函数被频繁调用(例如鼠标悬停、动画更新时),可能会产生不必要的拷贝开销。
    • 建议:虽然 QStringList 是隐式共享的,开销不大,但可以考虑在 DockCombineModel 中缓存白名单列表,或者确保 TaskManagerSettings 内部返回的是 const QStringList& 引用,避免深拷贝(如果实现允许)。
  • dockitemmodel.cpp
    • 如前所述,使用 resetModel 会导致视图全量刷新。如果任务栏图标数量很多,用户可能会感觉到闪烁。

4. 代码安全

  • 输入验证
    • windowIconWhitelist 的值来自配置文件(JSON)。虽然 dconfig 通常由系统管理,但仍需考虑配置文件被篡改或格式错误的情况。目前的 toStringList() 调用通常是安全的,但应确保 TaskManagerSettings 初始化时对异常值有容错处理。
  • 空指针检查
    • TaskManagerSettings::instance() 需要确保是线程安全的单例模式(虽然通常在Qt主线程调用没问题,但作为静态方法需注意)。
    • dockcombinemodel.cppdata(index, TaskManager::DesktopIdRole).toString() 如果返回空字符串,后续的 contains 逻辑依然安全(返回false),这是好的。

5. 其他建议

  • 版权年份dockcombinemodel.cpp 中的版权年份从 2025 改为了 2025 - 2026。请确认这是否符合实际开发计划,通常应覆盖当前年份。
  • 默认值:白名单默认值设为 ["wechat"]。这是一个硬编码的业务逻辑。建议在代码注释或文档中说明为何微信需要特殊处理(例如:微信在Linux下通常由多个窗口组成,且窗口图标更能反映当前状态)。

总结

代码整体实现了预期的功能,但在 dockitemmodel.cpp 中的模型重置逻辑有性能和体验回退的风险,建议评估是否回退。在 dockcombinemodel.cpp 中的字符串匹配逻辑建议从 contains 改为更精确的匹配,以防止误判。建议补充必要的注释以提高可维护性。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants