Skip to content

fix: rebuild SNI menu on menu path change - #996

Open
GongHeng2017 wants to merge 1 commit into
linuxdeepin:masterfrom
GongHeng2017:master
Open

GongHeng2017 wants to merge 1 commit into
linuxdeepin:masterfrom
GongHeng2017:master

Conversation

@GongHeng2017

@GongHeng2017 GongHeng2017 commented Sep 15, 2026

Copy link
Copy Markdown

Root Cause Analysis

When fcitx switches input method on 1070, it re-registers the SNI service with a new DBus menu path. SNITrayItemWidget::onSNIMenuChanged (snitrayitemwidget.cpp:383) only stores the new menu path (m_sniMenuPath = value) but does not destroy or rebuild the existing m_menu and m_dbusMenuImporter objects. On the next right-click, showContextMenu (snitrayitemwidget.cpp:310) sees m_menu is non-null and skips initMenu(), calling m_menu->popup() on a stale DBus connection that can no longer fetch menu data — the menu fails to appear.

Fix Approach

In onSNIMenuChanged, after storing the new menu path, destroy the old m_menu and m_dbusMenuImporter and set them to nullptr. This forces the next showContextMenu call to re-enter initMenu(), which rebuilds both objects with the updated m_sniMenuPath. The change is 9 lines, all within onSNIMenuChanged, matching the root-cause fix proposed in the analysis report.

Change Safety Assessment

Code Safety

  • Risk Level: Low
  • onSNIMenuChanged was introduced in commit bce2a499 (2024-01-04) as part of a feature change and has never been modified since — no historical fix is being reverted.
  • During widget initialization (snitrayitemwidget.cpp:650), onSNIMenuChanged is called when both m_menu and m_dbusMenuImporter are nullptr, so the new if guards do not trigger — no impact on the initialization path.

Business Impact Scope

Affects SNI tray icon right-click context menus in dde-dock. When an SNI application (e.g., fcitx input method) changes its DBus menu path at runtime, the tray widget now properly rebuilds the menu instead of reusing a stale connection. Other SNI applications (calendar, volume, etc.) that do not change their menu path at runtime are unaffected — their onSNIMenuChanged either is never called or is called with the same path, where the delete+rebuild is a safe no-op visually.

Verification Suggestion

  1. Switch input method (e.g., between Chinese and English) then right-click the input method icon in the taskbar — menu should appear.
  2. Without switching input method, right-click the input method icon — menu should appear (no regression).
  3. Right-click other SNI tray icons (e.g., calendar, volume) — menus should appear (no regression).

根因分析

在 1070 系统上切换输入法时,fcitx 会重新注册 SNI 服务并使用新的 DBus 菜单路径。SNITrayItemWidget::onSNIMenuChangedsnitrayitemwidget.cpp:383)仅存储新菜单路径(m_sniMenuPath = value),未销毁或重建已有的 m_menum_dbusMenuImporter 对象。下次右键点击时,showContextMenusnitrayitemwidget.cpp:310)发现 m_menu 非 null,跳过 initMenu(),直接对过期的 DBus 连接调用 m_menu->popup(),无法获取菜单数据,导致菜单不弹出。

修复方案

onSNIMenuChanged 中存储新菜单路径后,销毁旧的 m_menum_dbusMenuImporter 并置为 nullptr,使下次 showContextMenu 重新进入 initMenu() 用新的 m_sniMenuPath 重建。改动 9 行,全部在 onSNIMenuChanged 内,与分析报告中的根因修复建议一致。

改动安全评估

代码安全评估

  • 风险等级: 低风险
  • onSNIMenuChanged 于 commit bce2a499(2024-01-04)作为功能变更引入,此后从未被修改——不存在撤销历史修复的风险。
  • 初始化路径(snitrayitemwidget.cpp:650)调用 onSNIMenuChangedm_menum_dbusMenuImporter 均为 nullptr,新增的 if 守卫不会触发——对初始化流程无影响。

业务影响范围

影响 dde-dock 中 SNI 托盘图标的右键菜单。当 SNI 应用(如 fcitx 输入法)在运行时变更 DBus 菜单路径时,托盘控件现在会正确重建菜单而非复用过期连接。其他不在运行时变更菜单路径的 SNI 应用(日历、音量等)不受影响——其 onSNIMenuChanged 要么不被调用,要么以相同路径调用,delete+重建在视觉上是无副作用的。

验证建议

  1. 切换输入法(如中英文切换)后右键点击任务栏输入法图标——菜单应正常弹出。
  2. 不切换输入法时右键点击输入法图标——菜单应正常弹出(无回归)。
  3. 右键点击其他 SNI 托盘图标(如日历、音量)——菜单应正常弹出(无回归)。

Summary by Sourcery

Bug Fixes:

  • Rebuild SNI context menus when their DBus menu path changes, restoring right-click menus after runtime service re-registration.

1. Root cause: onSNIMenuChanged only stored the new menu path without
   destroying old m_menu and m_dbusMenuImporter, showContextMenu reused
   stale menu objects with expired DBus connection after input method
   switch
2. Fix: destroy old m_menu and m_dbusMenuImporter and set them to null
   in onSNIMenuChanged, so next showContextMenu triggers initMenu() to
   rebuild with the new menu path
3. Impact: only affects SNI tray items whose menu path changed at
   runtime, normal menu creation flow unchanged

Log: fix SNI tray context menu not opening after input method switch

Influence:
1. Test right-click menu after switching input method
2. Test right-click menu without switching input method
3. Verify other SNI app tray menus are unaffected

fix: 切换输入法后重建 SNI 右键菜单

1. 根因:onSNIMenuChanged 仅存储新菜单路径,未销毁旧的 m_menu 和
   m_dbusMenuImporter,切换输入法后 showContextMenu 复用过期菜单
   对象导致右键菜单无法弹出
2. 方案:在 onSNIMenuChanged 中销毁旧 m_menu 和 m_dbusMenuImporter
   并置 null,下次 showContextMenu 触发 initMenu() 用新路径重建
3. 影响:仅影响运行时菜单路径变更的 SNI 托盘项,正常菜单创建
   流程不受影响

Log: 修复切换输入法后任务栏输入法右键菜单无法打开的问题

Influence:
1. 测试切换输入法后右键菜单能否正常弹出
2. 测试不切换输入法时右键菜单是否正常
3. 验证其他 SNI 应用托盘菜单无回归

PMS: BUG-255089
@sourcery-ai

sourcery-ai Bot commented Sep 15, 2026

Copy link
Copy Markdown
Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Updates SNI menu-change handling to discard stale menu and importer objects so the next right-click rebuilds the context menu using the new DBus menu path, fixing menus that disappear after runtime SNI path changes while preserving normal initialization and unaffected tray icons.

Sequence diagram for rebuilding the SNI menu after a DBus path change

sequenceDiagram
    participant SNI as SNIService
    participant Widget as SNITrayItemWidget
    participant Menu as QMenu
    participant Importer as DBusMenuImporter

    SNI->>Widget: onSNIMenuChanged(value)
    Widget->>Widget: m_sniMenuPath = value
    Widget->>Menu: delete m_menu
    Widget->>Importer: delete m_dbusMenuImporter
    Widget->>Widget: m_menu = nullptr
    Widget->>Widget: m_dbusMenuImporter = nullptr
    Widget->>Widget: showContextMenu()
    Widget->>Widget: initMenu()
    Widget->>Importer: create importer with m_sniMenuPath
    Widget->>Menu: create menu
    Widget->>Menu: popup()
Loading

File-Level Changes

Change Details Files
Invalidate cached SNI menu objects when the DBus menu path changes, forcing lazy reconstruction against the new path.
  • Store the updated menu path before invalidating cached state.
  • Delete and null-check the existing menu and DBus menu importer.
  • Allow the next context-menu request to recreate both objects through the existing initialization path.
frame/window/tray/widgets/snitrayitemwidget.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

@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: GongHeng2017

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 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.

Hey - I've reviewed your changes and they look great!


Sourcery is free for open source - if you like our reviews please consider sharing them ✨

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

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

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 代码变更修复了SNI菜单路径变更后菜单不更新的问题,实现简洁正确。在onSNIMenuChanged中添加了旧菜单对象和DBusMenuImporter对象的清理逻辑,确保下次访问菜单时会使用新路径重新构建。语法正确,逻辑清晰,无安全漏洞。建议添加少量注释说明清理原因。

🔍 详细分析

1. 语法逻辑 ✅

评价: 优秀 ✅ 通过

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

建议: 1.删除顺序正确:先删除子对象m_menu,再删除父对象m_dbusMenuImporter,避免双重释放 2.nullptr检查在delete前虽然技术上非必需(C++允许delete nullptr),但作为防御性编程是好实践


2. 代码质量 ✅

评价: 优秀 ✅ 通过

潜在问题:

  1. frame/window/tray/widgets/snitrayitemwidget.cpp:385 - 新增的清理逻辑缺少注释说明为什么要在此处销毁菜单对象,虽然commit message解释了原因,但代码内注释有助于后续维护者理解

建议: 建议在清理代码前添加注释,如:// 菜单路径变更时,销毁旧菜单对象,下次访问时将使用新路径重新构建


3. 代码性能 ✅

评价: 优秀 ✅ 通过

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

建议: 1.清理旧对象释放内存是正确的资源管理方式,避免内存泄漏 2.下次访问菜单时通过initMenu()惰性重建,避免不必要的预创建


4. 代码安全 🔒

评价: 优秀 ✅ 通过

🔐 发现 0 个安全漏洞

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

建议: 1.正确的内存管理避免了悬垂指针和潜在的use-after-free风险 2.delete后立即置nullptr防止了野指针访问


💡 改进建议代码示例

// 菜单路径变更时,销毁旧菜单对象,下次访问时将使用新路径重新构建
if (m_menu) {
    delete m_menu;
    m_menu = nullptr;
}
if (m_dbusMenuImporter) {
    delete m_dbusMenuImporter;
    m_dbusMenuImporter = nullptr;
}

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

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