Skip to content

fix(tray): pre-create stashed popup to eliminate first-open lag#1508

Closed
Ivy233 wants to merge 1 commit intolinuxdeepin:masterfrom
Ivy233:fix-tray-popup-lag
Closed

fix(tray): pre-create stashed popup to eliminate first-open lag#1508
Ivy233 wants to merge 1 commit intolinuxdeepin:masterfrom
Ivy233:fix-tray-popup-lag

Conversation

@Ivy233
Copy link
Contributor

@Ivy233 Ivy233 commented Mar 17, 2026

Pre-create the stashed tray popup during initialization to avoid lag when first opening it, especially noticeable at high DPI scales (225%). The popup is opened with zero opacity during startup and closed after 200ms, ensuring all components are fully initialized. This eliminates the frame drops and stuttering that occurred when hovering over or clicking the application tray button for the first time.

修复系统托盘折叠弹窗首次打开时的卡顿问题。在初始化时预创建弹窗,
通过设置透明度为0在后台完成组件初始化和渲染,避免首次打开时的
帧率下降和卡顿,特别是在高DPI缩放(225%)下的表现。

PMS: BUG-344705

Summary by Sourcery

Eliminate the initial lag when opening the stashed tray popup by pre-creating and briefly showing it invisibly during initialization.

Bug Fixes:

  • Fix stuttering and frame drops when the tray’s stashed popup is opened for the first time, particularly on high-DPI displays.

Enhancements:

  • Initialize the stashed tray popup in the background with zero opacity and automatically close it shortly after startup to ensure it is ready for subsequent use.

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Ivy233

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 17, 2026

Reviewer's Guide

Pre-creates the stashed tray popup at startup with zero opacity and then closes it shortly after to eliminate first-open lag, adding a preCreation state and a timer-driven lifecycle around the popup.

Sequence diagram for pre-created stashed tray popup lifecycle at startup

sequenceDiagram
    actor User
    participant SystemStartup
    participant TrayApplet
    participant stashedPopup
    participant preCreateCloseTimer

    SystemStartup->>TrayApplet: initialize()
    TrayApplet->>stashedPopup: set preCreating = true
    TrayApplet->>stashedPopup: set opacity = 0
    TrayApplet->>TrayApplet: Qt.callLater(callback)
    TrayApplet-->>SystemStartup: initialization complete

    Note over TrayApplet,stashedPopup: Deferred pre-creation callback
    TrayApplet->>stashedPopup: preCreating = false
    TrayApplet->>stashedPopup: open()
    TrayApplet->>preCreateCloseTimer: start(interval = 200ms)

    preCreateCloseTimer-->>TrayApplet: triggered
    TrayApplet->>stashedPopup: close()
    TrayApplet->>stashedPopup: preCreating = false

    Note over User,TrayApplet: First user interaction after pre-creation
    User->>TrayApplet: hover_or_click_tray_icon()
    TrayApplet->>stashedPopup: open() (components already initialized)
Loading

State diagram for stashed tray popup pre-creation lifecycle

stateDiagram-v2
    [*] --> PreCreatingInvisible

    PreCreatingInvisible: preCreating = true
    PreCreatingInvisible: opacity = 0

    PreCreatingInvisible --> PreOpenVisible: Qt.callLater callback

    PreOpenVisible: preCreating = false
    PreOpenVisible: open()

    PreOpenVisible --> ClosedReady: preCreateCloseTimer triggered

    ClosedReady: preCreating = false
    ClosedReady: closed but fully initialized

    ClosedReady --> OpenVisibleOnUserAction: user hover_or_click_tray_icon

    OpenVisibleOnUserAction: popup opened without lag

    OpenVisibleOnUserAction --> ClosedReady: popup close

    ClosedReady --> [*]
Loading

File-Level Changes

Change Details Files
Introduce a pre-creation lifecycle for the stashed tray popup to warm it up at startup and avoid first-open stutter.
  • Add a preCreating boolean property on the stashed popup and bind its opacity to this flag so the popup can be initialized invisibly.
  • Extend the stashed popup initialization handler to schedule an immediate open of the popup after setup, then start a one-shot timer to close it once initialization is complete.
  • Add a one-shot Timer that closes the pre-created popup after 200ms and resets the preCreating flag to restore normal behavior.
panels/dock/tray/package/tray.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 found 1 issue, and left some high level feedback:

  • The preCreating flag is never set to true (it’s initialized as false and then explicitly reset to false again), so the opacity binding is effectively a no-op; consider initializing it to true and only setting it to false after the pre-creation open/close sequence finishes so the popup is actually transparent during pre-creation.
  • There’s a potential race where preCreateCloseTimer will close the popup if the user opens it manually within the first 200ms after startup; consider stopping the timer or guarding the close logic based on the popup’s current state to avoid closing a user-opened popup.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `preCreating` flag is never set to `true` (it’s initialized as `false` and then explicitly reset to `false` again), so the opacity binding is effectively a no-op; consider initializing it to `true` and only setting it to `false` after the pre-creation open/close sequence finishes so the popup is actually transparent during pre-creation.
- There’s a potential race where `preCreateCloseTimer` will close the popup if the user opens it manually within the first 200ms after startup; consider stopping the timer or guarding the close logic based on the popup’s current state to avoid closing a user-opened popup.

## Individual Comments

### Comment 1
<location path="panels/dock/tray/package/tray.qml" line_range="46-48" />
<code_context>

         property alias dropHover: stashContainer.dropHover
         property alias stashItemDragging: stashContainer.stashItemDragging
+        property bool preCreating: false
+
+        opacity: preCreating ? 0 : 1

         popupX: DockPanelPositioner.x
</code_context>
<issue_to_address>
**issue (bug_risk):** The `preCreating` flag is never set to `true`, so the opacity binding has no effect.

Since `preCreating` is only ever set to `false`, `opacity` will always be `1` and this binding has no effect. If the goal is to hide the popup during pre-creation, set `preCreating = true` before `open()` and reset it to `false` after `close()` (or when pre-creation finishes). As written, the new property doesn’t change 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.

@Ivy233
Copy link
Contributor Author

Ivy233 commented Mar 17, 2026

PS:想要一个不用定时器的修改方法。

Pre-create the stashed tray popup during initialization to avoid lag
when first opening it, especially noticeable at high DPI scales (225%).
The popup is opened with zero opacity during startup and closed after
200ms, ensuring all components are fully initialized. This eliminates
the frame drops and stuttering that occurred when hovering over or
clicking the application tray button for the first time.

修复系统托盘折叠弹窗首次打开时的卡顿问题。在初始化时预创建弹窗,
通过设置透明度为0在后台完成组件初始化和渲染,避免首次打开时的
帧率下降和卡顿,特别是在高DPI缩放(225%)下的表现。

PMS: BUG-344705
@Ivy233 Ivy233 force-pushed the fix-tray-popup-lag branch from ed9fd77 to 60e5d00 Compare March 17, 2026 09:42
@deepin-ci-robot
Copy link

deepin pr auto review

这段代码是为了解决托盘弹出窗口首次打开时的延迟问题,通过预先打开并迅速关闭弹出窗口来实现预热。以下是对该代码的审查意见,包括语法逻辑、代码质量、代码性能和代码安全方面:

1. 语法逻辑

  • 逻辑正确性:代码逻辑基本正确,通过设置 preCreating 标志位控制透明度,并在 200ms 后关闭弹出窗口。
  • 潜在问题
    • Qt.callLater 的使用是合理的,但需要确保 stashedPopup 已经完全初始化。如果 stashedPopup 尚未准备好,可能会引发错误。
    • preCreating 属性被添加到 stashedPopup 上,但未在代码中显示其定义位置。如果 stashedPopup 是动态创建的,需要确保该属性存在。

2. 代码质量

  • 可读性
    • 变量命名清晰(如 preCreatingpreCreateCloseTimer),但注释可以更详细,说明为什么选择 200ms 的延迟。
    • 代码结构清晰,但 Timer 的定义位置可以更靠近其使用位置,以提高可读性。
  • 可维护性
    • 硬编码的 200ms 延迟时间可能需要根据实际设备性能调整。建议将其定义为常量或可配置参数。
    • 如果 stashedPopup 的预热逻辑需要复用,建议将其封装为独立函数。

3. 代码性能

  • 性能优化
    • 预热弹出窗口可以减少首次打开的延迟,但 200ms 的固定延迟可能不够或过长。建议根据实际设备性能动态调整。
    • 频繁的 open()close() 可能会触发不必要的布局计算和动画。如果弹出窗口支持禁用动画,预热时可以临时禁用。
    • 如果 stashedPopup 的内容复杂,预热时可能会占用较多资源。建议评估是否需要延迟加载部分内容。

4. 代码安全

  • 潜在风险
    • 如果 preCreating 标志位未正确重置(例如 preCreateCloseTimer 未触发),弹出窗口可能会保持透明状态,导致用户无法看到内容。
    • 如果 stashedPopupopen()close() 方法抛出异常,可能会导致程序崩溃。建议添加错误处理逻辑。
    • 快速打开和关闭弹出窗口可能会触发用户可见的闪烁(即使透明度为 0)。建议测试不同设备上的表现。

改进建议

以下是优化后的代码示例:

AppletItem {
    // ... 其他代码 ...

    property bool preCreating: false
    property int preCreateDelay: 200 // 可配置的预热延迟时间

    opacity: preCreating ? 0 : 1

    // ... 其他代码 ...

    Component.onCompleted: {
        DockPanelPositioner.bounding = Qt.binding(function () {
            return Qt.rect(collapsedBtnCenterPoint.x, collapsedBtnCenterPoint.y, stashedPopup.width, stashedPopup.height)
        })
        // 预热弹出窗口
        Qt.callLater(preCreatePopup)
    }

    function preCreatePopup() {
        try {
            stashedPopup.preCreating = true
            stashedPopup.open()
            preCreateCloseTimer.start()
        } catch (error) {
            console.error("Failed to pre-create popup:", error)
            stashedPopup.preCreating = false
        }
    }

    Timer {
        id: preCreateCloseTimer
        interval: preCreateDelay
        repeat: false
        onTriggered: {
            try {
                stashedPopup.close()
            } finally {
                stashedPopup.preCreating = false
            }
        }
    }

    // ... 其他代码 ...
}

主要改进点:

  1. 将预热逻辑封装为 preCreatePopup 函数,提高可读性和可维护性。
  2. 添加错误处理逻辑,避免异常导致程序崩溃。
  3. 将 200ms 延迟定义为可配置参数 preCreateDelay,便于调整。
  4. 使用 try-finally 确保 preCreating 标志位正确重置。
  5. 添加更详细的注释,说明预热逻辑的目的和注意事项。

测试建议

  1. 在不同性能的设备上测试预热效果,确保延迟时间合理。
  2. 测试预热过程中是否会出现闪烁或其他视觉异常。
  3. 验证 preCreating 标志位在各种异常情况下是否正确重置。
  4. 检查预热是否会影响其他功能(如弹出窗口的动画或布局)。

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

@Ivy233 Ivy233 requested review from 18202781743, BLumia and mhduiy March 17, 2026 09:45
@Ivy233 Ivy233 closed this Mar 17, 2026
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