Skip to content

fix: improve menu interaction and notification center handling#1514

Open
qxp930712 wants to merge 1 commit intolinuxdeepin:masterfrom
qxp930712:master
Open

fix: improve menu interaction and notification center handling#1514
qxp930712 wants to merge 1 commit intolinuxdeepin:masterfrom
qxp930712:master

Conversation

@qxp930712
Copy link

@qxp930712 qxp930712 commented Mar 19, 2026

  1. Add keyboard grab when showing panel menus to ensure proper input focus
  2. Release keyboard grab when closing menus to prevent input conflicts
  3. Close notification center panel when opening various dock menus (dock menu, app context menu, tray popups) to avoid overlapping UI elements
  4. Add focus handling for tray item popups to ensure proper keyboard navigation
  5. Update copyright years for consistency

Log: Fixed menu interactions by ensuring proper focus management and preventing overlapping with notification center

Influence:

  1. Test opening dock menu while notification center is open - notification center should close
  2. Verify app context menus close notification center when opened
  3. Check tray popups properly close notification center
  4. Test keyboard navigation in all menu types
  5. Verify input focus is correctly managed between menus and other UI elements
  6. Test menu interactions with multiple open applications

PMS: BUG-284867

Summary by Sourcery

Improve panel and tray menu interaction by managing focus and avoiding conflicts with the notification center.

Bug Fixes:

  • Ensure opening dock menus, app context menus, and tray popups closes the notification center panel to prevent overlapping UI.
  • Fix panel menus not properly releasing keyboard focus when closed, avoiding input conflicts.

Enhancements:

  • Add keyboard focus handling for panel and tray menus to support consistent keyboard navigation.
  • Update copyright notices in tray popup QML files to the 2024-2026 range for consistency.

1. Add keyboard grab when showing panel menus to ensure proper input
focus
2. Release keyboard grab when closing menus to prevent input conflicts
3. Close notification center panel when opening various dock menus (dock
menu, app context menu, tray popups) to avoid overlapping UI elements
4. Add focus handling for tray item popups to ensure proper keyboard
navigation
5. Update copyright years for consistency

Log: Fixed menu interactions by ensuring proper focus management and
preventing overlapping with notification center

Influence:
1. Test opening dock menu while notification center is open -
notification center should close
2. Verify app context menus close notification center when opened
3. Check tray popups properly close notification center
4. Test keyboard navigation in all menu types
5. Verify input focus is correctly managed between menus and other UI
elements
6. Test menu interactions with multiple open applications

PMS: BUG-284867
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: qxp930712

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

sourcery-ai bot commented Mar 19, 2026

Reviewer's Guide

This PR tightens focus and visibility handling around dock-related menus and tray popups by grabbing the keyboard for panel menus and auto-closing the notification center when opening dock menus, app context menus, and tray popups, while also updating copyright years.

Sequence diagram for dock or tray menu opening with notification center handling

sequenceDiagram
    actor User
    participant DockOrTrayItem
    participant MenuHelper
    participant PanelMenuWindow
    participant DS
    participant NotificationCenterPanel

    User->>DockOrTrayItem: click()
    DockOrTrayItem->>DS: applet(org.deepin.ds.notificationcenter)
    DS-->>DockOrTrayItem: notifyPanel
    alt Notification center is visible
        DockOrTrayItem->>NotificationCenterPanel: close()
    end
    DockOrTrayItem->>MenuHelper: openMenu(menuItem)
    MenuHelper->>PanelMenuWindow: show()
    MenuHelper->>PanelMenuWindow: setTitle(windowTitle)
    MenuHelper->>DS: grabMouse(menuWindow)
    MenuHelper->>DS: grabKeyboard(menuWindow)

    User->>PanelMenuWindow: interact with menu (keyboard)

    User->>PanelMenuWindow: close menu
    PanelMenuWindow->>PanelMenuWindow: close()
    PanelMenuWindow->>PanelMenuWindow: setCurrentItem(null)
    PanelMenuWindow->>DS: grabKeyboard(menuWindow, false)
    PanelMenuWindow->>DS: grabMouse(menuWindow, false)
Loading

Updated class diagram for dock menus, tray popups, and notification center focus handling

classDiagram
    class DS {
        +applet(id)
        +grabMouse(window)
        +grabMouse(window, release)
        +grabKeyboard(window)
        +grabKeyboard(window, release)
    }

    class NotificationCenterPanel {
        +visible bool
        +close()
    }

    class MenuHelper {
        +openMenu(menuItem)
    }

    class PanelMenuWindow {
        +title string
        +currentItem Item
        +show()
        +close()
    }

    class PanelMenu {
        +windowTitle string
        +menuWindow PanelMenuWindow
        +showMenu()
        +closeMenu()
    }

    class TrayItemSurfacePopup {
        +popupMenu Item
        +popupMenuContent Item
        +openPopupMenu()
    }

    class SurfacePopup {
        +menu Item
        +openSurfaceMenu()
    }

    class AppItem {
        +contextMenuLoader Item
        +requestAppItemMenu()
    }

    DS --> NotificationCenterPanel : returns
    PanelMenu --> PanelMenuWindow : owns
    MenuHelper --> PanelMenuWindow : opens

    TrayItemSurfacePopup --> DS : queries_applet
    SurfacePopup --> DS : queries_applet
    AppItem --> DS : queries_applet

    TrayItemSurfacePopup --> NotificationCenterPanel : close_if_visible
    SurfacePopup --> NotificationCenterPanel : close_if_visible
    AppItem --> NotificationCenterPanel : close_if_visible

    PanelMenu --> DS : grabMouse
    PanelMenu --> DS : grabKeyboard

    TrayItemSurfacePopup --> MenuHelper : indirect_menu_behavior
    SurfacePopup --> MenuHelper : indirect_menu_behavior
    AppItem --> MenuHelper : open_context_menu
Loading

File-Level Changes

Change Details Files
Ensure notification center automatically closes when opening dock menus, app context menus, and tray-related popups.
  • Before opening the main dock menu, request the notification center applet and close it if currently visible.
  • Before opening an app item context menu, close the visible notification center applet if present.
  • Before opening generic tray item popups, close the notification center applet when it is visible.
  • Before opening a specific tray surface popup menu, close the notification center if it is visible, then explicitly focus the popup content for keyboard interaction.
panels/dock/package/main.qml
panels/dock/taskmanager/package/AppItem.qml
panels/dock/tray/SurfacePopup.qml
panels/dock/tray/TrayItemSurfacePopup.qml
Improve keyboard focus handling for panel menus to avoid input conflicts and ensure correct navigation.
  • When showing a panel menu window, in addition to grabbing the mouse, also grab the keyboard for that window.
  • When closing a panel menu window, release the keyboard grab to restore normal input handling.
frame/qml/PanelMenu.qml
Update copyright headers for tray popup QML files.
  • Extend SPDX-FileCopyrightText years from 2024 to 2024-2026 in tray popup components.
panels/dock/tray/TrayItemSurfacePopup.qml
panels/dock/tray/SurfacePopup.qml

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

deepin pr auto review

这段代码主要涉及QML界面的交互逻辑,特别是关于菜单弹出、焦点管理和通知中心关闭的处理。以下是对这段代码的详细审查和改进意见:

1. 语法逻辑

问题 1:重复代码
panels/dock/package/main.qmlpanels/dock/taskmanager/package/AppItem.qmlpanels/dock/tray/SurfacePopup.qml 中,存在完全相同的代码块用于关闭通知中心:

let notifyPanel = DS.applet("org.deepin.ds.notificationcenter")
if (notifyPanel && notifyPanel.visible) {
    notifyPanel.close()
}

改进建议:建议将这段逻辑封装成一个独立的函数或工具类,例如在 MenuHelper 中添加一个 closeNotificationCenter() 方法,以避免代码重复。这样不仅提高了可维护性,也减少了出错的可能性。

问题 2:键盘抓取逻辑不一致
PanelMenu.qml 中,打开菜单时抓取键盘 DS.grabKeyboard(menuWindow),关闭时释放键盘 DS.grabKeyboard(menuWindow, false)。但在 TrayItemSurfacePopup.qml 中,使用的是 popupMenuContent.takeFocus()
改进建议:统一键盘焦点的处理方式。如果 DS.grabKeyboard 是推荐的方式,应该在所有菜单打开的地方使用它;如果 takeFocus 更合适,则应统一使用 takeFocus

2. 代码质量

问题 1:版权年份更新
SurfacePopup.qmlTrayItemSurfacePopup.qml 中,版权年份从 2024 更新为 2024-2026
改进建议:通常版权年份的范围应该是从创建年份到当前年份,而不是未来年份。如果这是为了提前规划,建议在项目发布前再更新年份,避免造成混淆。

问题 2:缺少错误处理
在获取通知中心面板时:

let notifyPanel = DS.applet("org.deepin.ds.notificationcenter")

改进建议:虽然后面有 if (notifyPanel && notifyPanel.visible) 的检查,但建议添加更详细的错误处理或日志记录,以便在调试时能更快定位问题。

3. 代码性能

问题 1:频繁调用 DS.applet
每次打开菜单时都会调用 DS.applet("org.deepin.ds.notificationcenter"),这可能会带来不必要的性能开销。
改进建议:可以考虑在初始化时缓存通知中心面板的引用,避免每次打开菜单时都重新获取。例如:

property var notifyPanel: DS.applet("org.deepin.ds.notificationcenter")

// 在需要关闭的地方
if (notifyPanel && notifyPanel.visible) {
    notifyPanel.close()
}

4. 代码安全

问题 1:潜在的竞态条件
PanelMenu.qml 中,键盘抓取和释放的逻辑是分开的,如果在抓取键盘后、释放前发生异常,可能会导致键盘焦点无法正确释放。
改进建议:确保在任何情况下(包括异常)都能正确释放键盘资源。可以考虑使用 try-finally 模式(如果QML支持类似机制)或者确保在组件销毁时释放资源。

问题 2:外部依赖
代码中直接依赖 DS.applet("org.deepin.ds.notificationcenter"),如果通知中心的ID发生变化,或者通知中心不存在,可能会导致问题。
改进建议:将通知中心的ID定义为常量或配置项,避免硬编码。同时,确保在通知中心不存在时,程序仍能正常工作。

5. 其他建议

建议 1:添加注释
对于键盘抓取和通知中心关闭的逻辑,建议添加注释说明为什么需要这样做,特别是在多个地方重复的代码。

建议 2:单元测试
对于菜单打开、关闭以及通知中心关闭的逻辑,建议编写单元测试或集成测试,确保在各种场景下都能正常工作。

总结

这段代码的主要改进方向是:

  1. 消除重复代码,封装公共逻辑。
  2. 统一键盘焦点的处理方式。
  3. 优化性能,缓存不必要的重复调用。
  4. 增强代码的健壮性和安全性,添加错误处理和资源释放保证。

通过以上改进,代码的可维护性、性能和安全性都会得到提升。

Copy link

@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 left some high level feedback:

  • The logic to fetch and close the notification center (DS.applet("org.deepin.ds.notificationcenter") and visibility check) is duplicated in several places; consider extracting this into a shared helper (e.g., a function in a common utility QML) to keep behavior consistent and easier to maintain.
  • In TrayItemSurfacePopup.qml, popupMenuContent.takeFocus() is called unconditionally; it may be safer to guard this with a null/visibility check (or use forceActiveFocus() on a known focusable item) to avoid runtime errors if popupMenuContent is not yet instantiated or focusable.
  • When adding DS.grabKeyboard(menuWindow) in PanelMenu.qml, ensure that all paths that hide/destroy the menu window consistently go through closeMenu() (where DS.grabKeyboard(menuWindow, false) is called), or otherwise release the keyboard grab to avoid lingering grabs in edge cases.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The logic to fetch and close the notification center (`DS.applet("org.deepin.ds.notificationcenter")` and visibility check) is duplicated in several places; consider extracting this into a shared helper (e.g., a function in a common utility QML) to keep behavior consistent and easier to maintain.
- In `TrayItemSurfacePopup.qml`, `popupMenuContent.takeFocus()` is called unconditionally; it may be safer to guard this with a null/visibility check (or use `forceActiveFocus()` on a known focusable item) to avoid runtime errors if `popupMenuContent` is not yet instantiated or focusable.
- When adding `DS.grabKeyboard(menuWindow)` in `PanelMenu.qml`, ensure that all paths that hide/destroy the menu window consistently go through `closeMenu()` (where `DS.grabKeyboard(menuWindow, false)` is called), or otherwise release the keyboard grab to avoid lingering grabs in edge cases.

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.

Panel.requestClosePopup()
viewDeactivated()
hideTimer.stop()
let notifyPanel = DS.applet("org.deepin.ds.notificationcenter")
Copy link
Contributor

Choose a reason for hiding this comment

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

必须要这样跟任务栏通讯么,如果这样的话,那剪切板怎么处理呢?
能不能通过失去焦点来处理?

menuWindow.title = windowTitle
menuWindow.show()
DS.grabMouse(menuWindow)
DS.grabKeyboard(menuWindow)
Copy link
Contributor

Choose a reason for hiding this comment

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

测下grabKeyboard之后有没有其它的问题,之前好像是有这个,后来为了避免啥才删掉的,

@18202781743 18202781743 requested a review from BLumia March 19, 2026 12:39
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.

4 participants