Skip to content

fix(application-tray): add tiered fallback for SNI left-click Activate - #514

Closed
mhduiy wants to merge 1 commit into
masterfrom
fix/sni-leftclick-activate-fallback
Closed

mhduiy wants to merge 1 commit into
masterfrom
fix/sni-leftclick-activate-fallback

Conversation

@mhduiy

@mhduiy mhduiy commented Sep 14, 2026 •

Copy link
Copy Markdown
Contributor

背景 / Background

PMS Bug 360241:百度网盘等基于 Chromium 的应用未实现 StatusNotifierItem.Activate 方法,左键点击其托盘图标无任何反应。

根因:dde-tray-loader 的 SNI 托盘左键点击处理(SniTrayProtocolHandler::eventFilter)对 Activate DBus 调用采用「发后即忘」方式,未监听回复、无错误处理、无 fallback。当应用未实现 Activate 时,DBus 返回 org.freedesktop.DBus.Error.UnknownMethod,该错误被静默丢弃,点击事件丢失。

修复方案 / Fix

按确认的修复方向,在 sniprotocolhandler.cpp 中为 Activate 调用增加 QDBusPendingCallWatcher 错误监听与分级 fallback:

左键点击 → 检查 ItemIsMenu:若 true → 直接弹 DBus 菜单
          → 若 false → 调 Activate(QDBusPendingCallWatcher 监听)
            → Activate 成功 → 结束
            → Activate 失败 → 调 SecondaryActivate(watcher 监听)
              → SecondaryActivate 失败 → 弹 DBus 菜单(若有 Menu path)/ 调 ContextMenu
                → 仍无 DBus 菜单 → X11 下用 WindowId 经 EWMH(_NET_ACTIVE_WINDOW) 激活窗口

改动点

  1. ItemIsMenu 预检:声明 ItemIsMenu=true 的托盘项左键直接弹菜单(符合 SNI 规范),不再误调 Activate。
  2. Activate 错误监听:用 QDBusPendingCallWatcher 监听 Activate 异步回复,取代发后即忘。
  3. SecondaryActivate fallback:Activate 失败时调用 SecondaryActivate(同样监听)。
  4. DBus 菜单 / ContextMenu fallback:均失败时优先展示 DBus 菜单(复用右键菜单逻辑),无菜单时调用 ContextMenu。
  5. X11 窗口激活末级兜底:新增 Util::activateWindow(),通过已有 xcb 连接发送 EWMH _NET_ACTIVE_WINDOW ClientMessage 请求窗口管理器激活应用窗口。仅在 X11 可用(isXAvaliable())、WindowId 非零且窗口有效时触发,Wayland 下自动跳过。
  6. 重构:将右键菜单展示逻辑抽取为共享的 showTrayMenu(),左键 fallback 与右键共用,行为保持一致。

安全性

  • 所有 QDBusPendingCallWatcher 以 this 为 parent,finished 回调中 deleteLater();handler 析构时 watcher(子对象)随之销毁并断开连接,无悬空回调。
  • 对正常实现 Activate 的应用:Activate 成功即结束,行为与改动前一致,无回归。
  • 仅在 Activate/SecondaryActivate 均失败时才触发 fallback,影响面限于未合规实现 SNI 的应用。
  • X11 激活为末级兜底且有平台/有效性三重守卫,Wayland 下完全跳过。

自审 / Self-review

  • 根因定位:Activate 发后即忘、无 fallback(确认)
  • ItemIsMenu 预检(规范合规,低风险)
  • QDBusPendingCallWatcher 错误监听
  • 分级 fallback:SecondaryActivate → DBus 菜单 → X11 窗口激活
  • watcher 生命周期安全(parent=this + deleteLater)
  • 右键菜单逻辑保持不变(抽取共享方法)
  • 语法校验:sniprotocolhandler.cpp 在真实 Qt6/DTK6 头文件 + 正确生成的 SNI 接口下 -fsyntax-only 通过;Util::activateWindow 的 xcb 用法对真实 <xcb/xcb.h> 校验通过

注:完整编译需 CI 环境(本机缺 DTK qdbusxml2cpp-fix 工具与部分 xcb 扩展 dev 头文件),已做针对性语法校验。

关联 / Related

Summary by Sourcery

Restore SNI tray left-click behavior by handling activation failures with progressively broader fallbacks.

New Features:

  • Add tiered left-click activation fallback for SNI tray items, including secondary activation, menu display, context menu invocation, and X11 window activation.

Bug Fixes:

  • Fix lost left-click events for SNI applications that do not implement the Activate method.

Enhancements:

  • Honor ItemIsMenu tray items by opening their menu directly and share menu presentation logic between left-click fallbacks and right-click handling.
  • Monitor asynchronous D-Bus activation results and safely manage pending-call watchers.

PMS Bug 360241: left-clicking the tray icon of apps that do not
implement StatusNotifierItem.Activate (e.g. Baidu Netdisk, Chromium
based) did nothing. The Activate DBus call was fire-and-forget with no
error handling, so the org.freedesktop.DBus.Error.UnknownMethod reply
was silently dropped.

Rework the left-click handling in SniTrayProtocolHandler::eventFilter:

1. Pre-check ItemIsMenu: items declaring ItemIsMenu now show the DBus
   menu directly instead of calling Activate (spec-compliant).
2. Wrap Activate(0,0) in a QDBusPendingCallWatcher to monitor the reply
   instead of ignoring it.
3. On Activate error, fall back to SecondaryActivate (also watched).
4. On SecondaryActivate error, show the DBus menu when a Menu path is
   available, otherwise call ContextMenu and finally attempt X11
   window activation (EWMH _NET_ACTIVE_WINDOW) as a last resort.

The X11 fallback is guarded by isXAvaliable()/non-zero WindowId and is
skipped on Wayland. The DBus menu display path used by right-click is
extracted into showTrayMenu() and reused by the fallback chain.

Add Util::activateWindow() to issue the _NET_ACTIVE_WINDOW client
message via the existing xcb connection.

Refs: https://pms.uniontech.com/bug-view-360241.html

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @mhduiy, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 1 day and 3 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mhduiy

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

sourcery-ai Bot commented Sep 14, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds asynchronous SNI Activate error handling with SecondaryActivate, menu, ContextMenu, and X11 window-activation fallbacks, while factoring shared tray-menu behavior and preserving XDG activation-token support.

Sequence diagram for tiered SNI tray activation fallback

sequenceDiagram
    participant User
    participant Handler as SniTrayProtocolHandler
    participant SNI as SNI DBus item
    participant Menu as DBusMenuImporter
    participant Util as Util X11

    User->>Handler: activateWithFallback(clickPos)
    alt ItemIsMenu
        Handler->>Menu: showTrayMenu(clickPos)
    else ItemIsMenu is false
        Handler->>Handler: beginActivate(token, clickPos)
        Handler->>SNI: Activate(0, 0)
        SNI-->>Handler: Activate reply
        alt Activate succeeds
        else Activate fails
            Handler->>SNI: SecondaryActivate(0, 0)
            SNI-->>Handler: SecondaryActivate reply
            alt SecondaryActivate succeeds
            else SecondaryActivate fails
                alt DBus menu available
                    Handler->>Menu: showTrayMenu(clickPos)
                else No DBus menu
                    Handler->>SNI: ContextMenu(0, 0)
                    Handler->>Util: activateWindow(windowId)
                end
            end
        end
    end
Loading

File-Level Changes

Change Details Files
Replaced fire-and-forget SNI activation with asynchronous reply handling and a tiered left-click fallback chain.
  • Pre-checks ItemIsMenu and opens the DBus menu directly when set.
  • Uses QDBusPendingCallWatcher for Activate and SecondaryActivate errors.
  • Falls back from activation to the DBus menu or ContextMenu, then to X11 window activation when applicable.
  • Preserves XDG activation-token handling before issuing Activate.
plugins/application-tray/sniprotocolhandler.cpp
plugins/application-tray/sniprotocolhandler.h
Centralized tray-menu presentation so left-click fallbacks and right-click handling share the same behavior.
  • Extracted menu importing, lazy menu update, popup positioning, and display into showTrayMenu().
  • Retained ContextMenu behavior when no DBus menu importer is available.
plugins/application-tray/sniprotocolhandler.cpp
plugins/application-tray/sniprotocolhandler.h
Added an X11 EWMH-based last-resort window activation utility.
  • Validates the X11 connection and target window before acting.
  • Maps the window and sends an _NET_ACTIVE_WINDOW client message through the existing XCB connection.
  • Automatically remains unused when X11 is unavailable, such as under Wayland.
plugins/application-tray/util.cpp
plugins/application-tray/util.h

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

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 99 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 代码实现质量高,修复了PMS Bug 360241描述的托盘图标左键点击无反应问题。分级fallback机制设计合理,异步DBus调用处理规范,内存管理正确,无安全漏洞。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: []


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['trySecondaryActivate 方法可添加简短功能注释']


3. 代码性能 ✅

评价: 优秀 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: []


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: []


💡 改进建议代码示例

// 暂无代码示例

本报告由 AI 代码审查工具自动生成

@mhduiy

mhduiy commented Sep 15, 2026

Copy link
Copy Markdown
Contributor Author

该 BUG 是应用自己的问题,桌面环境层面无需解决

@mhduiy mhduiy closed this Sep 15, 2026
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