Skip to content

fix(popup): focus window popups for input#638

Open
mhduiy wants to merge 1 commit into
linuxdeepin:masterfrom
mhduiy:popupwindowfocus
Open

fix(popup): focus window popups for input#638
mhduiy wants to merge 1 commit into
linuxdeepin:masterfrom
mhduiy:popupwindowfocus

Conversation

@mhduiy

@mhduiy mhduiy commented Jun 16, 2026

Copy link
Copy Markdown
Contributor
  1. Enable focus for popups using window mode.
  2. Request activation when the popup window is shown.
  3. Ensure input controls inside popup windows can trigger the input method.

Log: Focus window popups on show so embedded input controls can open the input method.

fix(popup): 让窗口弹窗支持输入法

  1. 为窗口模式的弹窗启用焦点。
  2. 在弹窗窗口显示时请求激活。
  3. 确保窗口弹窗内的输入控件可以调起输入法。

Log: 显示窗口弹窗时获取焦点,使内部输入控件可以调起输入法。

Summary by Sourcery

Ensure window-based popups gain focus and activation when shown so embedded input controls can properly receive input and trigger the input method.

Bug Fixes:

  • Request focus and window activation for visible window-mode popups on show to restore input method behavior for embedded input controls.

Enhancements:

  • Set QML window-mode popups to be focusable by default to align popup focus behavior with input expectations.

@deepin-ci-robot

Copy link
Copy Markdown
Contributor

[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 Jun 16, 2026

Copy link
Copy Markdown

Reviewer's Guide

Ensures window-mode popups request focus and activation on show so that embedded input controls can receive focus and trigger the input method, by wiring popup focus properties in QML to a new focus-request helper in the popup window handle.

Sequence diagram for popup window focus request on show

sequenceDiagram
    participant PopupWin as QQuickWindow_m_popupWin
    participant Handle as DPopupWindowHandle
    participant Popup as QObject_m_popup
    participant Item as QQuickItem_popupItem

    PopupWin->>Handle: eventFilter(watched=PopupWin, event: QEvent::Show)
    alt watched is m_popupWin and event is Show
        Handle->>Handle: requestPopupFocus()
        Handle->>Handle: QMetaObject::invokeMethod(this, lambda, QueuedConnection)
        Note over Handle: Queued lambda executes later
        Handle->>Popup: property focus
        alt isEnabled and popup focus and popupWin visible
            Handle->>PopupWin: requestActivate()
            Handle->>Item: forceActiveFocus(Qt::ActiveWindowFocusReason)
        end
    end
Loading

File-Level Changes

Change Details Files
Request focus and window activation when a window-mode popup is shown so its content can gain active focus.
  • Hook QEvent::Show for the popup window in the event filter to trigger a focus request.
  • Add a requestPopupFocus helper that validates state, then asynchronously requests window activation and forces active focus on the popup item when appropriate.
  • Guard focus-activation logic with checks for handle enabled state, popup visibility, focus property, and pointer validity.
src/private/dpopupwindowhandle.cpp
src/private/dpopupwindowhandle_p.h
Mark window-type popups as focusable from QML so the C++ focus logic is enabled.
  • Set the focus property on the Popup control when popupType is Popup.Window so that window popups are treated as focusable.
  • Rely on the existing popup focus property in C++ to decide whether to request focus on show.
qt6/src/qml/Popup.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

@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 found 1 issue, and left some high level feedback:

  • In requestPopupFocus(), instead of capturing popupItem() in a QPointer<QQuickItem> before the queued invocation, consider resolving the current popup item inside the lambda to avoid focusing a stale or deleted item if the content changes between the Show event and the queued execution.
  • The check popup->property("focus").toBool() is performed both before and inside the queued lambda; you could drop the outer check and rely on the inner one to reduce duplicated property lookups and keep the decision logic in a single place.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `requestPopupFocus()`, instead of capturing `popupItem()` in a `QPointer<QQuickItem>` before the queued invocation, consider resolving the current popup item inside the lambda to avoid focusing a stale or deleted item if the content changes between the `Show` event and the queued execution.
- The check `popup->property("focus").toBool()` is performed both before and inside the queued lambda; you could drop the outer check and rely on the inner one to reduce duplicated property lookups and keep the decision logic in a single place.

## Individual Comments

### Comment 1
<location path="src/private/dpopupwindowhandle.cpp" line_range="287-306" />
<code_context>
         m_popupWin->setPosition(newPos);
 }

+void DPopupWindowHandle::requestPopupFocus()
+{
+    if (!m_popup || !isEnabled() || !m_popupWin || !m_popupWin->isVisible())
+        return;
+    if (!m_popup->property("focus").toBool())
+        return;
+
+    QPointer<QObject> popup = m_popup;
+    QPointer<QQuickWindow> popupWin = m_popupWin;
+    QPointer<QQuickItem> item = popupItem();
+
+    QMetaObject::invokeMethod(this, [this, popup, popupWin, item] {
+        if (!isEnabled() || !popup || !popup->property("focus").toBool() || !popupWin || popupWin != m_popupWin || !popupWin->isVisible())
+            return;
+
+        popupWin->requestActivate();
+        if (item && item->window() == popupWin)
+            item->forceActiveFocus(Qt::ActiveWindowFocusReason);
+    }, Qt::QueuedConnection);
+}
+
 DQUICK_END_NAMESPACE
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Avoid capturing a potentially stale popup item and consider resolving it at invocation time.

Because `item` is captured before the queued call executes, it may no longer match the actual popup item when the lambda runs (e.g. due to reparenting or delayed creation changing `popupItem()`). Instead, construct the `QPointer<QQuickItem>` inside the lambda by calling `popupItem()` there, then validate it (and its window) before requesting focus.

```suggestion
void DPopupWindowHandle::requestPopupFocus()
{
    if (!m_popup || !isEnabled() || !m_popupWin || !m_popupWin->isVisible())
        return;
    if (!m_popup->property("focus").toBool())
        return;

    QPointer<QObject> popup = m_popup;
    QPointer<QQuickWindow> popupWin = m_popupWin;

    QMetaObject::invokeMethod(this, [this, popup, popupWin] {
        if (!isEnabled() || !popup || !popup->property("focus").toBool() || !popupWin || popupWin != m_popupWin || !popupWin->isVisible())
            return;

        popupWin->requestActivate();

        QPointer<QQuickItem> item = popupItem();
        if (item && item->window() == popupWin)
            item->forceActiveFocus(Qt::ActiveWindowFocusReason);
    }, Qt::QueuedConnection);
}
```
</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 src/private/dpopupwindowhandle.cpp
1. Enable focus for popups using window mode.
2. Request activation when the popup window is shown.
3. Ensure input controls inside popup windows can trigger the input method.

Log: Focus window popups on show so embedded input controls can open the input method.

fix(popup): 让窗口弹窗支持输入法

1. 为窗口模式的弹窗启用焦点。
2. 在弹窗窗口显示时请求激活。
3. 确保窗口弹窗内的输入控件可以调起输入法。

Log: 显示窗口弹窗时获取焦点,使内部输入控件可以调起输入法。
pms: BUG-366067
@mhduiy mhduiy force-pushed the popupwindowfocus branch from 5dd16ba to 904e41e Compare June 16, 2026 05:13
@deepin-ci-robot

Copy link
Copy Markdown
Contributor

deepin pr auto review

★ 总体评分:95分

■ 【总体评价】

代码实现了Popup弹窗自动获取焦点的修复,逻辑严谨且无安全漏洞
逻辑正确且通过异步安全调用与生命周期检查保障了稳定性,给予高分

■ 【详细分析】

  • 1.语法逻辑(完全正确)✓

DPopupWindowHandle::eventFilter 中正确监听 QEvent::Show 事件,并在新增的 requestPopupFocus 函数中采用 Qt::QueuedConnection 异步调用,避免了在 Show 事件链中直接操作窗口状态可能引发的异常。同时大量使用 QPointer 进行生命周期校验,有效防止了悬空指针和野指针解引用。

建议:无

  • 2.代码质量(良好)✓

函数命名清晰,职责划分明确,QML 层与 C++ 层配合默契,仅对 Popup.Window 类型赋予 focus: true,避免了 Tooltip 等非窗口组件抢夺焦点。但新增的 C++ 函数缺少必要的注释说明。

建议:在 requestPopupFocus 函数上方添加简要注释,说明为何需要使用异步调用及 QPointer 校验

  • 3.代码性能(无性能问题)✓

使用 QMetaObject::invokeMethod 进行异步排队调用,不阻塞当前事件分发。虽然通过字符串 m_popup->property("focus").toBool() 获取属性存在极微小的哈希查找开销,但在 UI 事件触发场景下完全可以忽略。

建议:无

  • 4.代码安全(存在0个安全漏洞)✓

漏洞对比统计:新增漏洞 0 个,减少漏洞 0 个,持平 0 个
代码未引入任何安全风险,通过 QPointer 严格校验了 m_popupm_popupWinpopupItem() 的有效性,并在 Lambda 执行前二次校验对象状态与指针归属,彻底杜绝了 Use-After-Free 等内存安全问题。

  • 建议:保持现有的安全编码习惯

■ 【改进建议代码示例】

// 简要注释:在 Popup 对应的窗口 Show 事件时触发焦点请求逻辑,确保弹窗显示时能自动获取焦点
void DPopupWindowHandle::requestPopupFocus()
{
    if (!m_popup || !isEnabled() || !m_popupWin || !m_popupWin->isVisible())
        return;
    if (!m_popup->property("focus").toBool())
        return;

    QPointer<QObject> popup = m_popup;
    QPointer<QQuickWindow> popupWin = m_popupWin;

    // 使用异步调用防止在 Show 事件链中直接操作引发异常
    QMetaObject::invokeMethod(this, [this, popup, popupWin] {
        // 二次校验确保对象生命周期安全及状态一致
        if (!isEnabled() || !popup || !popup->property("focus").toBool() || !popupWin || popupWin != m_popupWin || !popupWin->isVisible())
            return;

        QPointer<QQuickItem> item = popupItem();
        if (!item || item->window() != popupWin)
            return;

        popupWin->requestActivate();
        item->forceActiveFocus(Qt::ActiveWindowFocusReason);
    }, Qt::QueuedConnection);
}

return;

popupWin->requestActivate();
item->forceActiveFocus(Qt::ActiveWindowFocusReason);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

QPointer<QQuickWindow> popupWin = m_popupWin;

QMetaObject::invokeMethod(this, [this, popup, popupWin] {
if (!isEnabled() || !popup || !popup->property("focus").toBool() || !popupWin || popupWin != m_popupWin || !popupWin->isVisible())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

这个在this里有成员变量,是QPointer的,还需要在外面传入么,

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