Skip to content

fix: improve menu interaction and notification center handling#1514

Merged
18202781743 merged 1 commit intolinuxdeepin:masterfrom
qxp930712:master
Mar 20, 2026
Merged

fix: improve menu interaction and notification center handling#1514
18202781743 merged 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.

@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

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.

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

@18202781743 18202781743 requested a review from BLumia March 19, 2026 12:39
@qxp930712 qxp930712 force-pushed the master branch 2 times, most recently from c16a03a to 177fa1f Compare March 20, 2026 02:45
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: 18202781743, 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

@deepin-ci-robot
Copy link

deepin pr auto review

这段代码主要涉及三个方面的修改:键盘焦点抓取、版权年份更新以及焦点获取。以下是对代码的详细审查和改进建议:

1. 代码逻辑审查

修改点1:PanelMenu.qml 中添加键盘抓取

DS.grabKeyboard(menuWindow)        // 打开菜单时抓取键盘
DS.grabKeyboard(menuWindow, false) // 关闭菜单时释放键盘
  • 逻辑正确性:在菜单打开时抓取键盘,关闭时释放,逻辑是正确的。这可以防止键盘事件泄露到其他窗口。
  • 潜在问题DS.grabKeyboard 的第二个参数 false 表示释放,这种 API 设计有些隐晦。建议检查 API 文档,确保 false 确实代表释放,或者是否有更明确的 API 如 ungrabKeyboard() 可用。

修改点2:TrayItemSurfacePopup.qml 中添加焦点获取

popupMenuContent.takeFocus()
  • 逻辑正确性:在菜单打开后立即获取焦点,确保键盘导航(如上下键切换)能正常工作。
  • 潜在问题takeFocus() 是一个自定义方法,需确保其实现是线程安全的,并且不会与其他焦点管理逻辑冲突。

2. 代码质量审查

修改点3:版权年份更新

-// SPDX-FileCopyrightText: 2024 UnionTech Software Technology Co., Ltd.
+// SPDX-FileCopyrightText: 2024-2026 UnionTech Software Technology Co., Ltd.
  • 建议:将版权年份改为范围(如 2024-2026)是合理的,但建议使用更通用的格式,如 2024-20262024, 2026,以符合 SPDX 标准。

3. 代码性能审查

  • 键盘抓取的性能影响:频繁调用 grabKeyboardungrabKeyboard 可能会影响性能,尤其是在菜单快速打开/关闭时。建议确保这些操作是轻量级的,并且不会阻塞主线程。
  • 焦点获取的性能影响takeFocus() 可能会触发额外的布局或事件处理,需确保其不会导致性能瓶颈。

4. 代码安全审查

  • 键盘抓取的安全性grabKeyboard 可能会被恶意利用(例如阻止用户输入),需确保只有受信任的代码才能调用此方法。
  • 焦点管理的安全性takeFocus() 可能会被用于窃取焦点,需确保其调用是受控的。

5. 改进建议

  1. API 设计改进

    • 如果 DS 提供了更明确的键盘抓取/释放 API(如 grabKeyboard/ungrabKeyboard),建议优先使用。
    • 如果 takeFocus() 是自定义方法,建议重命名为更明确的名称,如 requestFocus()forceFocus()
  2. 错误处理

    • 添加对 grabKeyboardtakeFocus 的错误处理,例如:
      if (!DS.grabKeyboard(menuWindow)) {
          console.warn("Failed to grab keyboard for menu window")
      }
  3. 文档注释

    • grabKeyboardtakeFocus 添加注释,说明其作用和可能的副作用。
  4. 版权年份格式

    • 建议统一版权年份的格式,例如:
      // SPDX-FileCopyrightText: 2024-2026 UnionTech Software Technology Co., Ltd.

6. 示例改进代码

// PanelMenu.qml
Item {
    function openMenu() {
        menuWindow.title = windowTitle
        menuWindow.show()
        if (!DS.grabKeyboard(menuWindow)) {
            console.warn("Failed to grab keyboard for menu window")
        }
    }

    function closeMenu() {
        menuWindow.close()
        menuWindow.currentItem = null
        if (!DS.ungrabKeyboard(menuWindow)) { // 假设存在 ungrabKeyboard
            console.warn("Failed to release keyboard for menu window")
        }
    }
}

// TrayItemSurfacePopup.qml
Item {
    function openPopupMenu() {
        popupMenu.open()
        // 确保键盘导航正常工作
        if (!popupMenuContent.requestFocus()) { // 假设重命名为 requestFocus
            console.warn("Failed to request focus for menu content")
        }
    }
}

总结

这段代码的修改逻辑是正确的,但可以通过更明确的 API 设计、错误处理和文档注释来提升代码质量和可维护性。建议在后续开发中逐步优化这些方面。

@18202781743 18202781743 merged commit d98c937 into linuxdeepin:master Mar 20, 2026
11 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.

4 participants