Skip to content

fix: allow right-click long press to trigger context menu on touchscreen#755

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
wjyrich:fix-bug-358827
May 7, 2026
Merged

fix: allow right-click long press to trigger context menu on touchscreen#755
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
wjyrich:fix-bug-358827

Conversation

@wjyrich
Copy link
Copy Markdown
Contributor

@wjyrich wjyrich commented Apr 29, 2026

  1. Previously, onPressAndHold handlers only triggered when mouse.button was Qt.NoButton
  2. Added Qt.RightButton as an additional trigger condition for long press
  3. This allows right-click long press to also trigger context menus
  4. Applied consistently across all relevant QML files: IconItemDelegate, AppListView, FreeSortListView, and windowed IconItemDelegate

Log: Fixed context menu not opening on right-click long press

Influence:

  1. Test right-click long press on icons to verify context menu appears
  2. Test regular long press (no button) still works as before
  3. Verify no regression for touchscreen long press behavior
  4. Test in both normal and windowed mode

fix: 允许右键长按触发上下文菜单

  1. 之前 onPressAndHold 处理器仅在 mouse.button 为 Qt.NoButton 时触发
  2. 增加了 Qt.RightButton 作为长按的额外触发条件
  3. 使右键长按也能触发上下文菜单
  4. 在所有相关的 QML 文件中统一应用此修改:IconItemDelegate、 AppListView、FreeSortListView 和窗口模式下的 IconItemDelegate

Log: 修复右键长按时上下文菜单无法打开的问题

Influence:

  1. 在图标上测试右键长按,验证上下文菜单是否弹出
  2. 测试常规长按(无按钮)是否仍正常工作
  3. 验证触控屏长按行为没有回归问题
  4. 在普通模式和窗口模式下分别测试

PMS: BUG-358827

Summary by Sourcery

Bug Fixes:

  • Fix context menus not opening when performing a right-click long-press on icons across list and icon delegates in both normal and windowed modes.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented Apr 29, 2026

Reviewer's guide (collapsed on small PRs)

Reviewer's Guide

Allows long-press context menus to be triggered by both touch (no button) and right mouse button across icon and app list delegates, by relaxing the onPressAndHold button check in relevant QML views.

Sequence diagram for long press context menu triggering with touch and right-click

sequenceDiagram
    actor User
    participant InputDevice
    participant QMLDelegate
    participant ContextMenu

    User->>InputDevice: LongPressOnIcon
    InputDevice->>QMLDelegate: onPressAndHold(mouse)

    alt Touchscreen_long_press
        Note right of InputDevice: mouse.button = Qt.NoButton
        QMLDelegate->>QMLDelegate: checkButton(mouse.button)
        QMLDelegate->>ContextMenu: open()
    else Right_click_long_press
        Note right of InputDevice: mouse.button = Qt.RightButton
        QMLDelegate->>QMLDelegate: checkButton(mouse.button)
        QMLDelegate->>ContextMenu: open()
    else Other_buttons
        QMLDelegate->>QMLDelegate: ignore event
    end
Loading

File-Level Changes

Change Details Files
Allow right-click long-press to trigger the same context menu logic as touch long-press across icon/list delegates.
  • Updated onPressAndHold handlers to accept both Qt.NoButton and Qt.RightButton before invoking context menu actions.
  • Applied the updated condition consistently in main IconItemDelegate and windowed variants to keep behavior uniform.
  • Ensured app list and free-sort list views share the same expanded trigger condition for showing context menus.
qml/IconItemDelegate.qml
qml/windowed/AppListView.qml
qml/windowed/FreeSortListView.qml
qml/windowed/IconItemDelegate.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
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 IconItemDelegate.qml the updated condition uses ||| instead of ||, which will cause a syntax error and needs to be corrected.
  • Since the same mouse.button === Qt.NoButton || mouse.button === Qt.RightButton condition is now repeated across several QML files, consider extracting this into a shared helper or function to keep the behavior consistent and easier to maintain.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `IconItemDelegate.qml` the updated condition uses `|||` instead of `||`, which will cause a syntax error and needs to be corrected.
- Since the same `mouse.button === Qt.NoButton || mouse.button === Qt.RightButton` condition is now repeated across several QML files, consider extracting this into a shared helper or function to keep the behavior consistent and easier to maintain.

## Individual Comments

### Comment 1
<location path="qml/IconItemDelegate.qml" line_range="161" />
<code_context>
                         // touchscreen long press.
                         onPressAndHold: function (mouse) {
-                            if (mouse.button === Qt.NoButton) {
+                            if (mouse.button === Qt.NoButton ||| mouse.button === Qt.RightButton) {
                                 root.menuTriggered()
                             }
</code_context>
<issue_to_address>
**issue (bug_risk):** Fix the `|||` operator, which is invalid JavaScript/QML syntax.

Use `||` here (as in the other handlers) so the condition parses correctly and matches the intended `NoButton` or `RightButton` behavior.
</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 qml/IconItemDelegate.qml Outdated
reliability

Replaced the `onPressAndHold` event handler with a `TapHandler`
component for touchscreen long press interactions across multiple
QML files. This change prevents duplicate handling of touch events
by introducing a flag `isTouchLongPressed` that blocks the subsequent
`onClicked` execution. The old `onPressAndHold` approach was unreliable
and caused duplicated menu triggers.

Log: Improved touchscreen long press reliability by using TapHandler

Influence:
1. Test touchscreen long press on icon items to trigger context menu
2. Verify that short tap still properly triggers the default action
(e.g., launching app)
3. Ensure no duplicate menu popups occur during touch interaction
4. Test with mouse input to confirm no regression in right-click context
menu
5. Verify drag-and-drop behavior remains unaffected on touch devices

fix: 使用 TapHandler 替代触摸长按处理以提高可靠性

将多个 QML 文件中的 `onPressAndHold` 事件处理器替换为 `TapHandler` 组件
来处理触摸屏长按交互。此修改通过引入 `isTouchLongPressed` 标志位来阻止后
续的 `onClicked` 重复执行,解决了原有 `onPressAndHold` 方法不可靠导致的
菜单重复触发问题。

Log: 通过使用 TapHandler 提高触摸长按的可靠性

Influence:
1. 测试触摸屏长按图标项是否正常触发上下文菜单
2. 验证短触是否仍能正常触发默认操作(如启动应用)
3. 确保触摸交互期间不会出现重复的菜单弹窗
4. 测试鼠标输入,确认右键上下文菜单无回归问题
5. 验证触摸设备上的拖拽功能不受影响

PMS: BUG-358827
@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

这段代码主要是对QML中触摸屏长按(Long Press)和鼠标点击(Click)事件的交互逻辑进行了重构。它将原来使用 MouseArea 的 onPressAndHold 处理触摸长按的方式,改为使用 TapHandler 来专门处理触摸事件,并引入了一个标志位 isTouchLongPressed 来解决长按后触发 onClicked 的问题。

以下是对这段代码的审查意见,包括语法逻辑、代码质量、代码性能和代码安全方面:

1. 语法逻辑

  • 逻辑正确性

    • 改进点:原代码中 onPressAndHold 在某些触摸设备上可能不够灵敏,且在长按释放手指时往往会紧接着触发 onClicked,导致菜单弹出后应用又立即打开(或触发其他点击行为)。新代码通过 TapHandler 专门监听触摸屏,并在 onLongPressed 中设置标志位 isTouchLongPressed = true,然后在 onClicked 中检查该标志位并拦截,逻辑上是正确的,能有效解决"长按后触发点击"的竞态问题。
    • 状态重置时机:代码在 onPressed 中将 isTouchLongPressed 重置为 false。这是合理的,因为每次新的按下操作都应该重置长按状态。TapHandleronLongPressed 会在按下一段时间后触发,此时 onPressed 早已执行完毕,所以不会冲突。
  • 手势策略

    • gesturePolicy: TapHandler.DragThreshold 设置是合理的。这意味着用户的手指必须移动超过一定阈值(系统默认)才会被视为拖拽,否则视为点击或长按。这有助于区分用户是想滚动列表/拖拽图标,还是想点击/长按图标。

2. 代码质量

  • 可读性与可维护性

    • 改进点:将触摸逻辑(TapHandler)与鼠标逻辑(MouseArea)分离,使得代码意图更加清晰。TapHandler 专门处理 PointerDevice.TouchScreen,而 MouseArea 继续处理鼠标按钮事件,这种职责分离提高了代码的可读性。
    • 注释:添加了 // 记录是否是触摸长按导致的,防止在 onClicked 中重复处理 注释,清楚地解释了引入 isTouchLongPressed 变量的原因,有助于后续维护。
  • 一致性

    • 修改在 IconItemDelegate.qmlAppListView.qmlFreeSortListView.qml 中保持了一致的模式,这是很好的做法,保证了不同视图下的交互体验一致。

3. 代码性能

  • 性能影响
    • 轻微增加:引入了 TapHandler 作为 MouseArea 的子项,会增加少量的对象创建和事件分发开销。但在现代设备上,这种开销微乎其微,几乎可以忽略不计。
    • 优化TapHandleracceptedDevices: PointerDevice.TouchScreen 限制了它只响应触摸屏事件,避免了不必要的鼠标事件处理,这是一个好的性能实践。

4. 代码安全

  • 潜在风险
    • 事件竞争:虽然引入了标志位,但 TapHandlerMouseArea 在某些特定的触摸屏驱动或 Qt 版本下,可能对事件的处理顺序存在微妙的差异。
    • 拖拽干扰:在 FreeSortListView.qml 中,MouseArea 设置了 drag.target: itemDelegate。当用户进行长按操作时,如果手指有轻微抖动,可能会触发 MouseArea 的拖拽逻辑,从而干扰 TapHandler 的长按判定。不过,由于 TapHandler 设置了 gesturePolicy: TapHandler.DragThreshold,这应该能过滤掉轻微抖动,风险较低。

5. 改进建议

  1. 属性命名

    • isTouchLongPressed 是一个布尔标志位。在 QML 中,为了避免与属性绑定的混淆,通常建议使用更具描述性的名称,或者在逻辑非常明确的情况下保持现状。当前名称是可以接受的,但也可以考虑 touchLongPressHandledsuppressNextClick 来更明确地表达其用途(即"抑制下一次点击")。
  2. 事件处理的互斥性

    • MouseArea 中,可以考虑根据设备类型动态禁用某些事件。例如,如果检测到是纯触摸设备,可以尝试禁用 MouseArea 的某些属性以防止事件冲突。但这通常比较复杂,当前的标志位方案已经足够简单有效。
  3. 代码复用

    • 由于这段逻辑(TapHandler + isTouchLongPressed 检查)在四个文件中重复出现,如果项目规模允许,可以考虑将其封装为一个自定义的 QML 组件(例如 TouchMouseAreaInteractiveMouseArea),在这个组件内部统一处理触摸和鼠标事件的互斥逻辑。这样可以减少重复代码,便于统一修改交互行为。

    示例封装思路:

    // InteractiveMouseArea.qml
    MouseArea {
        id: root
        property bool isTouchLongPressed: false
    
        TapHandler {
            acceptedDevices: PointerDevice.TouchScreen
            gesturePolicy: TapHandler.DragThreshold
            onLongPressed: {
                root.isTouchLongPressed = true
                root.touchLongPressed() // 暴露一个信号给外部
            }
        }
    
        onPressed: function (mouse) {
            root.isTouchLongPressed = false
        }
    
        // 可以在这里统一处理 onClicked 的拦截逻辑,或者只提供标志位
        signal touchLongPressed()
    }
  4. GesturePolicy 的配置

    • TapHandler.DragThreshold 是默认行为,显式写出是好的。如果应用中有特殊的拖拽需求(例如非常小的图标),可能需要确认这个阈值是否合适。但在启动器/列表视图场景下,默认阈值通常是最佳体验。

总结

这段代码的修改是积极且有效的。它通过引入 TapHandler 和状态标志位,解决了触摸屏长按与点击事件冲突的常见问题,提升了用户体验。代码逻辑清晰,注释得当。主要的改进空间在于消除重复代码(通过组件封装),但对于当前的功能实现来说,代码已经达到了较高的质量标准。

@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

@wjyrich
Copy link
Copy Markdown
Contributor Author

wjyrich commented May 7, 2026

/forcemerge

@deepin-bot
Copy link
Copy Markdown

deepin-bot Bot commented May 7, 2026

This pr force merged! (status: behind)

@deepin-bot deepin-bot Bot merged commit 957e8a7 into linuxdeepin:master May 7, 2026
11 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