Skip to content

fix: filter unsupported dock applets in DBus proxy#1563

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
wjyrich:feat-dockapplete-1
Apr 20, 2026
Merged

fix: filter unsupported dock applets in DBus proxy#1563
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
wjyrich:feat-dockapplete-1

Conversation

@wjyrich
Copy link
Copy Markdown
Contributor

@wjyrich wjyrich commented Apr 17, 2026

  1. Added isSupported property to DAppletDock class to mark applet compatibility
  2. Modified dock DBus proxy to skip unsupported applets when updating plugin visibility and listing plugins
  3. Enhanced MultiTaskView to dynamically update supported status based on window compositor availability
  4. Fixed visible property calculation to consider both m_visible and m_isSupported flags
  5. Added proper signal emission when supported status changes affect effective visibility

Log: Fixed dock applet visibility issues when compositor is unavailable

Influence:

  1. Test dock applet visibility when switching between composited and non-composited modes
  2. Verify DBus plugin list excludes unsupported applets
  3. Check that MultiTaskView correctly appears/disappears based on compositor support
  4. Test that visibleChanged signal fires appropriately when supported status changes
  5. Verify dock settings UI correctly reflects available applets

fix: 在DBus代理中过滤不支持的停靠小程序

  1. 在DAppletDock类中添加isSupported属性以标记小程序兼容性
  2. 修改停靠DBus代理,在更新插件可见性和列出插件时跳过不支持的小程序
  3. 增强MultiTaskView以根据窗口合成器可用性动态更新支持状态
  4. 修复visible属性计算,同时考虑m_visible和m_isSupported标志
  5. 当支持状态变化影响有效可见性时添加适当的信号发射

Log: 修复合成器不可用时停靠小程序可见性问题

Influence:

  1. 测试在合成和非合成模式间切换时停靠小程序的可见性
  2. 验证DBus插件列表排除不支持的小程序
  3. 检查MultiTaskView是否根据合成器支持正确显示/隐藏
  4. 测试当支持状态变化时visibleChanged信号是否适当触发
  5. 验证停靠设置UI正确反映可用的小程序

Summary by Sourcery

Ensure dock applets respect both visibility and platform support, and exclude unsupported applets from DBus-exposed plugin state.

New Features:

  • Add a supported property to dock applets to represent platform/compositor compatibility.

Bug Fixes:

  • Fix dock applet visibility so that items are hidden when unsupported, particularly when the window compositor or effects are unavailable.
  • Prevent unsupported dock applets from appearing in the DBus plugin list or being updated via DBus visibility settings.

Enhancements:

  • Update MultiTaskView to track compositor and effect availability, updating its supported and effective visibility status accordingly.
  • Unify dock item visibility reporting to rely on the applet's effective visible state.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 17, 2026

Reviewer's Guide

Adds an explicit supported state to dock applets, wires MultiTaskView’s support to compositor/KWin effect availability, and updates the DBus proxy to ignore unsupported applets for visibility and plugin listing, ensuring visibility and signals reflect both user choice and platform support.

Sequence diagram for compositor changes affecting MultiTaskView visibility

sequenceDiagram
    participant DWindowManagerHelper
    participant MultiTaskView
    participant DAppletDock as BaseDockApplet

    DWindowManagerHelper->>MultiTaskView: hasCompositeChanged(newHasComposite)
    activate MultiTaskView
    MultiTaskView-->>MultiTaskView: Q_EMIT visibleChanged()
    MultiTaskView->>MultiTaskView: setSupported(m_kWinEffect && hasComposite())
    alt supported state unchanged
        MultiTaskView-->>MultiTaskView: return (no signal change)
    else supported state changed
        MultiTaskView->>BaseDockApplet: setSupported(bool supported)
        activate BaseDockApplet
        BaseDockApplet-->>BaseDockApplet: oldEffectiveVisible = visible()
        BaseDockApplet-->>BaseDockApplet: m_isSupported = supported
        BaseDockApplet-->>BaseDockApplet: Q_EMIT supportedChanged()
        alt effective visibility changed
            BaseDockApplet-->>BaseDockApplet: Q_EMIT visibleChanged()
        end
        deactivate BaseDockApplet
    end
    deactivate MultiTaskView
Loading

Sequence diagram for DockDBusProxy filtering unsupported dock applets

sequenceDiagram
    participant Client
    participant DockDBusProxy
    participant DockApplet1
    participant DockApplet2

    Client->>DockDBusProxy: updateDockPluginsVisible(pluginsVisible)
    activate DockDBusProxy
    loop for each dockApplet in dockApplets(parent)
        alt dockApplet is unsupported
            DockDBusProxy->>DockApplet1: isSupported()
            DockApplet1-->>DockDBusProxy: false
            DockDBusProxy-->>DockDBusProxy: continue (skip applet)
        else dockApplet is supported
            DockDBusProxy->>DockApplet2: isSupported()
            DockApplet2-->>DockDBusProxy: true
            DockDBusProxy->>DockApplet2: dockItemInfo()
            DockApplet2-->>DockDBusProxy: DockItemInfo
            DockDBusProxy-->>DockDBusProxy: apply pluginsVisible[itemKey]
        end
    end
    deactivate DockDBusProxy

    Client->>DockDBusProxy: plugins()
    activate DockDBusProxy
    loop for each dockApplet in dockApplets(parent)
        alt dockApplet is unsupported
            DockDBusProxy->>DockApplet1: isSupported()
            DockApplet1-->>DockDBusProxy: false
            DockDBusProxy-->>DockDBusProxy: skip appending
        else dockApplet is supported
            DockDBusProxy->>DockApplet2: isSupported()
            DockApplet2-->>DockDBusProxy: true
            DockDBusProxy->>DockApplet2: dockItemInfo()
            DockApplet2-->>DockDBusProxy: DockItemInfo
            DockDBusProxy-->>DockDBusProxy: iteminfos.append(info)
        end
    end
    DockDBusProxy-->>Client: DockItemInfos (supported applets only)
    deactivate DockDBusProxy
Loading

Class diagram for dock applet support and visibility model

classDiagram
    class DAppletDockPrivate {
        bool m_visible
        bool m_isSupported
    }

    class DAppletDock {
        +bool visible()
        +void setVisible(bool visible)
        +bool isSupported()
        +void setSupported(bool supported)
        +DockItemInfo dockItemInfo()
        +void init()
        <<signals>>
        +void visibleChanged()
        +void supportedChanged()
    }

    class MultiTaskView {
        +MultiTaskView(QObject parent)
        +bool init()
        +DockItemInfo dockItemInfo()
        -bool m_kWinEffect
        -QScopedPointer multitaskview
    }

    class DockDBusProxy {
        +QRect geometry()
        +void updateDockPluginsVisible(QVariantMap pluginsVisible)
        +DockItemInfos plugins()
    }

    class DWindowManagerHelper {
        +static DWindowManagerHelper instance()
        +bool hasComposite()
        <<signals>>
        +void hasCompositeChanged(bool hasComposite)
    }

    class DockItemInfo {
        QString displayName
        QString itemKey
        QString settingKey
        bool visible
        QString dccIcon
    }

    DAppletDockPrivate <.. DAppletDock : uses
    DAppletDock *-- DAppletDockPrivate : owns
    MultiTaskView --|> DAppletDock
    DockDBusProxy ..> DAppletDock : iterates_dockApplets
    DWindowManagerHelper ..> MultiTaskView : notifies_compositor_change
    DAppletDock ..> DockItemInfo : returns
    MultiTaskView ..> DockItemInfo : returns
Loading

File-Level Changes

Change Details Files
Introduce supported state to DAppletDock and integrate it with visibility and signals.
  • Add m_isSupported flag to DAppletDockPrivate with default true
  • Expose supported state via Q_PROPERTY, isSupported() getter, and setSupported() setter on DAppletDock
  • Change visible() to return conjunction of m_visible and m_isSupported
  • Guard visibleChanged emission in setVisible() based on effective visibility change
  • Emit supportedChanged in setSupported() and conditionally emit visibleChanged when support impacts effective visibility
panels/dock/frame/dappletdock.cpp
panels/dock/frame/dappletdock.h
Make MultiTaskView dynamically update its supported/visible state based on compositor and KWin effect availability.
  • Replace direct hasCompositeChanged-to-visibleChanged connection with a lambda that also updates supported based on m_kWinEffect and hasComposite()
  • On KWin effects configuration changes, update m_kWinEffect, emit visibleChanged, and update supported accordingly
  • During init(), set both supported and visible based on m_kWinEffect and compositor availability before calling base init()
  • Use visible() instead of recomputing visibility when filling DockItemInfo.visible
panels/dock/multitaskview/multitaskview.cpp
Filter out unsupported dock applets in the DBus proxy for visibility updates and plugin enumeration.
  • In updateDockPluginsVisible(), skip applets whose isSupported() is false before applying visibility changes
  • In plugins(), skip unsupported applets when collecting DockItemInfos
panels/dock/dockdbusproxy.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 MultiTaskView, the hasCompositeChanged and kWinEffect changed handlers both emit visibleChanged and then call setSupported, which can emit visibleChanged again; consider relying on setSupported’s effective-visibility detection to avoid redundant signal emissions.
  • The condition m_kWinEffect && DWindowManagerHelper::instance()->hasComposite() is duplicated in several places in MultiTaskView (constructor lambda, kWinEffect change, init); consider extracting a small helper (e.g. updateSupportFromCompositor()) or using isSupported() consistently to keep the logic centralized and less error-prone.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In MultiTaskView, the hasCompositeChanged and kWinEffect changed handlers both emit visibleChanged and then call setSupported, which can emit visibleChanged again; consider relying on setSupported’s effective-visibility detection to avoid redundant signal emissions.
- The condition `m_kWinEffect && DWindowManagerHelper::instance()->hasComposite()` is duplicated in several places in MultiTaskView (constructor lambda, kWinEffect change, init); consider extracting a small helper (e.g. `updateSupportFromCompositor()`) or using `isSupported()` consistently to keep the logic centralized and less error-prone.

## Individual Comments

### Comment 1
<location path="panels/dock/multitaskview/multitaskview.cpp" line_range="28-30" />
<code_context>
     , m_iconName("deepin-multitasking-view")
 {
-    connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasCompositeChanged, this, &MultiTaskView::visibleChanged);
+    connect(DWindowManagerHelper::instance(), &DWindowManagerHelper::hasCompositeChanged, this, [this]() {
+        Q_EMIT visibleChanged();
+        setSupported(m_kWinEffect && DWindowManagerHelper::instance()->hasComposite());
+    });
     auto platformName = QGuiApplication::platformName();
</code_context>
<issue_to_address>
**issue (bug_risk):** Avoid potentially emitting `visibleChanged` twice on compositor changes.

Because the lambda always emits `visibleChanged()`, and `setSupported()` can emit it again when the effective visibility changes, a single compositor change may trigger duplicate notifications. Either rely on `setSupported()` alone to emit `visibleChanged()` when needed, or emit `visibleChanged()` here only when `supported` actually changes (e.g. compute the new supported state, compare to `isSupported()`, then call `setSupported()` without the unconditional `Q_EMIT visibleChanged()`).
</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.

Comment thread panels/dock/multitaskview/multitaskview.cpp
@wjyrich wjyrich force-pushed the feat-dockapplete-1 branch from 92fe171 to d46d828 Compare April 20, 2026 03:07
1. Added isSupported property to DAppletDock class to mark applet
compatibility
2. Modified dock DBus proxy to skip unsupported applets when updating
plugin visibility and listing plugins
3. Enhanced MultiTaskView to dynamically update supported status based
on window compositor availability
4. Fixed visible property calculation to consider both m_visible and
m_isSupported flags
5. Added proper signal emission when supported status changes affect
effective visibility

Log: Fixed dock applet visibility issues when compositor is unavailable

Influence:
1. Test dock applet visibility when switching between composited and
non-composited modes
2. Verify DBus plugin list excludes unsupported applets
3. Check that MultiTaskView correctly appears/disappears based on
compositor support
4. Test that visibleChanged signal fires appropriately when supported
status changes
5. Verify dock settings UI correctly reflects available applets

fix: 在DBus代理中过滤不支持的停靠小程序

1. 在DAppletDock类中添加isSupported属性以标记小程序兼容性
2. 修改停靠DBus代理,在更新插件可见性和列出插件时跳过不支持的小程序
3. 增强MultiTaskView以根据窗口合成器可用性动态更新支持状态
4. 修复visible属性计算,同时考虑m_visible和m_isSupported标志
5. 当支持状态变化影响有效可见性时添加适当的信号发射

Log: 修复合成器不可用时停靠小程序可见性问题

Influence:
1. 测试在合成和非合成模式间切换时停靠小程序的可见性
2. 验证DBus插件列表排除不支持的小程序
3. 检查MultiTaskView是否根据合成器支持正确显示/隐藏
4. 测试当支持状态变化时visibleChanged信号是否适当触发
5. 验证停靠设置UI正确反映可用的小程序
@wjyrich wjyrich force-pushed the feat-dockapplete-1 branch from d46d828 to 402b3b2 Compare April 20, 2026 03:41
@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, 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

@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这份代码变更主要实现了对Dock插件(Applet)的"支持状态"(supported)进行管理,使得插件不仅可以通过visible控制显示,还可以通过supported控制其是否可用。这对于像"多任务视图"这样依赖特定系统环境(如合成器支持、KWin特效等)的插件非常有用。

以下是对代码的详细审查和改进建议:

1. 语法逻辑

问题:DockDBusProxy 构造函数中的循环连接风险
panels/dock/dockdbusproxy.cpp 中:

for (auto *dockApplet : dockApplets(parent)) {
    connect(dockApplet, &DS_NAMESPACE::DAppletDock::supportedChanged, this, [this]() {
        auto pluginsVisible = DockSettings::instance()->pluginsVisible();
        updateDockPluginsVisible(pluginsVisible);
        Q_EMIT pluginsChanged();
    });
}

分析:这个循环中存在一个潜在的逻辑问题。Lambda 表达式 [this]() 捕获了 this 指针,但没有捕获当前的 dockApplet。虽然逻辑上是为了通知 "任意一个插件支持状态改变,就刷新所有插件的可见性",但这会导致信号槽的连接数量与插件数量成正比。假设有 N 个插件,每个插件改变状态都会触发 N 次 pluginsChanged 信号(虽然 updateDockPluginsVisible 内部会处理,但信号发射是多余的)。此外,如果插件列表是动态变化的,这里没有处理断开连接的逻辑,可能导致悬空指针或内存泄漏。

改进建议

  1. 如果 DockDBusProxy 是管理所有 Dock Applet 的中心,建议在 DAppletDock 对象创建或销毁时动态连接/断开,而不是在构造函数中一次性遍历。
  2. 如果必须在构造函数中连接,请确保逻辑清晰。目前的写法会导致信号风暴。建议确认是否真的需要在这里连接,或者是否可以由 DockPanel 统一管理并转发信号。
  3. 更安全的做法:不要在循环中直接连接每个对象的信号到同一个槽,除非你确定这是预期的行为。更好的方式可能是让 DockDBusProxy 监听一个容器(如 QList<DAppletDock*>)的变化,或者由父对象 DockPanel 转发一个统一的 appletSupportedChanged 信号。

问题:MultiTaskView::dockItemInfo 逻辑变更

// 旧代码
info.visible = m_kWinEffect && DWindowManagerHelper::instance()->hasComposite();

// 新代码
info.visible = visible();

分析:这里将可见性的判断逻辑直接委托给了基类的 visible() 属性。由于 QML 中 shouldVisible 已经被修改为 Applet.visible && Applet.supported,这个改动在逻辑上是自洽的。但需要注意,DAppletDockvisible 属性和 supported 属性现在是两个独立的开关。

2. 代码质量

问题:DockItemInfo 的填充逻辑
panels/dock/multitaskview/multitaskview.cpp 中,dockItemInfo 方法现在返回 visible()。这意味着 DockItemInfo 中的 visible 字段不再直接反映硬件/系统支持情况,而是反映了最终的显示状态。这通常是好的,但需要确保 DockDBusProxy::updateDockPluginsVisible 中的逻辑与之一致。
目前的逻辑是:

if (!dockApplet->isSupported()) {
    continue;
}
// ... 后续处理 pluginsVisible

这里如果 !isSupported,直接跳过,不会更新其 visible 状态。这意味着如果 supported 变为 false,该插件会从列表中消失。如果 supported 变为 true,它需要重新进入列表。目前的实现看起来是正确的,但依赖于 pluginsChanged 信号的触发。

改进建议
建议在 dappletdock.h 中为 supported 属性添加详细的注释,说明它与 visible 的关系:visible 控制用户是否想看到它,supported 控制系统是否允许它显示。

3. 代码性能

问题:频繁的信号发射
如前所述,在 DockDBusProxy 构造函数中,如果有 N 个插件,就会有 N 个连接。任何一个插件触发 supportedChanged,都会执行 updateDockPluginsVisible 并发射 pluginsChanged
如果 updateDockPluginsVisible 内部逻辑较重(虽然目前看起来是 O(N)),频繁调用可能影响性能。

改进建议
考虑在 DockDBusProxy 中增加一个防抖机制或者标志位,避免在短时间内多次发射 pluginsChanged 信号。或者,优化连接逻辑,确保一次状态变更只触发一次更新。

4. 代码安全

问题:Lambda 捕获与生命周期
DockDBusProxy 构造函数中:

connect(dockApplet, &DS_NAMESPACE::DAppletDock::supportedChanged, this, [this]() { ... });

如果 dockAppletDockDBusProxy 析构之前被销毁,Qt 会自动断开连接,这是安全的。但是,如果 DockDBusProxy 析构时,dockApplet 仍然存在,连接会自动断开,也是安全的。这里没有明显的内存安全问题,但前提是 dockApplet 必须是 QObject 派生类且父子关系正确(或者由其他机制管理生命周期)。

问题:空指针检查
DockDBusProxy::updateDockPluginsVisibleDockDBusProxy::plugins 中,使用了 dockApplets(parent())。需要确保 parent() 始终有效且返回的对象不为空。虽然通常在构造函数中 parent 已设置,但在多线程或复杂析构顺序中需谨慎。

总结与修改建议

建议对 panels/dock/dockdbusproxy.cpp 进行重构,以避免信号风暴和潜在的连接管理问题。

修改后的 dockdbusproxy.cpp 构造函数部分建议:

如果 DockDBusProxy 是作为 DockPanel 的子对象,建议将信号连接移至 DockPanel 或者使用一个统一的槽来处理所有 DAppletDock 的变化。如果必须保留在 DockDBusProxy 中,可以考虑如下方式优化(伪代码):

// 在 DockDBusProxy 类中添加一个槽函数
private slots:
    void onAppletSupportedChanged() {
        // 可以在这里加一些判断,比如检查发送者是否在当前列表中
        auto pluginsVisible = DockSettings::instance()->pluginsVisible();
        updateDockPluginsVisible(pluginsVisible);
        Q_EMIT pluginsChanged();
    }

// 在构造函数中
DockDBusProxy::DockDBusProxy(DockPanel* parent)
    : QObject(parent)
{
    // ... 其他初始化代码 ...

    // 监听父对象(假设是 DockPanel)的信号,当有新 Applet 添加时连接
    if (parent) {
        // 假设 parent 有 appletAdded 信号
        connect(parent, &DockPanel::appletAdded, this, [this](DAppletDock *applet) {
            if (applet) {
                connect(applet, &DAppletDock::supportedChanged, this, &DockDBusProxy::onAppletSupportedChanged);
            }
        });
        
        // 初始化连接现有的 applets
        for (auto *dockApplet : dockApplets(parent)) {
            connect(dockApplet, &DAppletDock::supportedChanged, this, &DockDBusProxy::onAppletSupportedChanged);
        }
    }
}

注意:上述代码假设 DockPanel 会通知 Applet 的增减。如果没有这样的机制,原代码的写法在静态列表下是可以工作的,但需注意多次触发的问题。

其他文件

  • AppletDockItem.qml:修改合理,逻辑清晰。
  • dappletdock.cpp/h:标准的 Q_PROPERTY 实现,没有问题。
  • multitaskview.cpp:逻辑修正正确,将环境检查逻辑正确地绑定到了 supported 属性上。

总体而言,代码逻辑是正确的,主要风险在于 DockDBusProxy 中的信号连接管理。建议优化该部分的实现以提高健壮性。

@wjyrich
Copy link
Copy Markdown
Contributor Author

wjyrich commented Apr 20, 2026

/forcemerge

@deepin-bot
Copy link
Copy Markdown

deepin-bot Bot commented Apr 20, 2026

This pr force merged! (status: blocked)

@deepin-bot deepin-bot Bot merged commit ac054d1 into linuxdeepin:master Apr 20, 2026
9 of 12 checks passed
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.

3 participants