Skip to content

fix: improve notification center margin calculation#1363

Merged
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
wjyrich:fix-bug-340795
Feb 4, 2026
Merged

fix: improve notification center margin calculation#1363
deepin-bot[bot] merged 1 commit intolinuxdeepin:masterfrom
wjyrich:fix-bug-340795

Conversation

@wjyrich
Copy link
Contributor

@wjyrich wjyrich commented Nov 28, 2025

  1. Replaced simple windowMargin function with comprehensive updateMargins function
  2. Added proper handling for dock visibility and position
  3. Implemented device pixel ratio conversion for accurate geometry calculations
  4. Added special handling for bottom dock to prevent flickering
  5. Added properties to store margin values instead of recalculating each time
  6. Connected to frontendWindowRectChanged signal for dynamic updates

Log: Fixed notification center positioning issues when dock is visible

fix: 改进通知中心边距计算

  1. 将简单的 windowMargin 函数替换为全面的 updateMargins 函数
  2. 添加对任务栏可见性和位置的正确处理
  3. 实现设备像素比转换以确保几何计算准确
  4. 为底部任务栏添加特殊处理以防止闪烁
  5. 添加属性存储边距值而不是每次都重新计算
  6. 连接 frontendWindowRectChanged 信号以实现动态更新

Log: 修复任务栏可见时通知中心定位问题

PMS: BUG-340795

剪切板相关修复: #1308 linuxdeepin/dde-clipboard#215

@sourcery-ai
Copy link

sourcery-ai bot commented Nov 28, 2025

Reviewer's Guide

Refactors notification center margin handling to use dynamic, screen-aware dock geometry with device-pixel–aware calculations and stored margin properties, fixing positioning issues and flicker when the dock is shown/hidden or moved.

Sequence diagram for dynamic dock geometry margin updates

sequenceDiagram
    actor User
    participant DockApplet
    participant NotificationCenterWindow as RootWindow
    participant DLayerShellWindow
    participant Screen

    User->>DockApplet: Change dock visibility/position
    DockApplet->>DockApplet: Update frontendWindowRect
    DockApplet-->>NotificationCenterWindow: frontendWindowRectChanged(frontendWindowRect)
    NotificationCenterWindow->>NotificationCenterWindow: updateMargins(frontendRect)
    NotificationCenterWindow->>DockApplet: Read screenName, position, hideState, dockSize
    NotificationCenterWindow->>Screen: Read name, devicePixelRatio, virtualX, virtualY, width, height
    NotificationCenterWindow->>NotificationCenterWindow: Compute dockGeometry and screenGeometry
    alt Dock on same screen and visible
        alt DockPositionTop
            NotificationCenterWindow->>NotificationCenterWindow: Set topMarginValue
        else DockPositionRight
            NotificationCenterWindow->>NotificationCenterWindow: Set rightMarginValue
        else DockPositionBottom
            NotificationCenterWindow->>DockApplet: Read hideState and dockSize
            NotificationCenterWindow->>NotificationCenterWindow: Set bottomMarginValue with anti_flicker_logic
        end
    else Dock on other screen or not valid
        NotificationCenterWindow->>NotificationCenterWindow: Reset all margin values to 0
    end
    NotificationCenterWindow-->>DLayerShellWindow: topMargin, rightMargin, bottomMargin bindings updated
    DLayerShellWindow->>User: Notification center repositions without flicker
Loading

Class diagram for updated notification center margin handling

classDiagram
    class RootWindow {
        +int topMarginValue
        +int rightMarginValue
        +int bottomMarginValue
        +updateMargins(frontendRect)
        +onRequestClosePopup()
        +onFrontendWindowRectChanged(frontendWindowRect)
    }

    class DockApplet {
        +string screenName
        +int hideState
        +int position
        +int dockSize
        +rect frontendWindowRect
        +frontendWindowRectChanged(frontendWindowRect)
    }

    class Screen {
        +string name
        +double devicePixelRatio
        +int virtualX
        +int virtualY
        +int width
        +int height
    }

    class DLayerShellWindow {
        +int topMargin
        +int rightMargin
        +int bottomMargin
        +int exclusionZone
        +int keyboardInteractivity
    }

    RootWindow --> DockApplet : reads_properties_and_listens_to_signal
    RootWindow --> Screen : uses_for_geometry_and_dpr
    RootWindow --> DLayerShellWindow : binds_margin_properties
    DLayerShellWindow ..> Screen : positioned_on
Loading

File-Level Changes

Change Details Files
Replace simple dock-based margin calculation with a comprehensive, geometry-based updateMargins function and stored margin properties.
  • Introduce topMarginValue, rightMarginValue, and bottomMarginValue properties on the root Window to hold current margins instead of recomputing them in bindings.
  • Replace windowMargin(position) helper with updateMargins(frontendRect) that initializes margins to zero when dock/screen are unavailable or mismatched.
  • Within updateMargins, fetch dockApplet.frontendWindowRect (if no rect is provided) and early-return with zero margins when absent.
panels/notification/center/package/main.qml
Make margin calculation device-pixel–aware and dependent on actual dock geometry for each edge of the screen.
  • Convert dock frontendWindowRect from device pixels to logical pixels using root.screen.devicePixelRatio before calculations.
  • Construct screenGeometry from root.screen virtual coordinates and logical width/height to compare with dock geometry.
  • Compute top, right, and bottom margins based on dock position and visible overlap between dockGeometry and screenGeometry, guarding for zero/invalid dock size.
panels/notification/center/package/main.qml
Add special handling for bottom dock hide behavior and wire margins to DLayerShellWindow and dock signals for dynamic, flicker-free updates.
  • For DOCK_BOTTOM, avoid geometry-based computation and instead set bottom margin to 0 when dockApplet.hideState is Dock.Hide, otherwise use dockApplet.dockSize to prevent flicker.
  • Bind DLayerShellWindow.topMargin/rightMargin/bottomMargin to the new margin properties instead of calling a function per-binding.
  • Handle onFrontendWindowRectChanged(frontendWindowRect) in the dock notification to call root.updateMargins(frontendWindowRect), ensuring margins are updated when the dock frontend rect changes.
panels/notification/center/package/main.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 there - I've reviewed your changes - here's some feedback:

  • The updateMargins function repeats the pattern of resetting all margin values to 0 in several early-return branches; consider extracting this into a small helper (e.g. resetMargins()) to reduce duplication and make the intent clearer.
  • The switch (dockPosition) uses raw numeric values (0/1/2) with comments for DOCK_TOP/RIGHT/BOTTOM; if the dock API exposes an enum or constants for these positions, using them instead of magic numbers would make the code more self-documenting and less error-prone.
  • For the bottom dock you explicitly gate the margin on hideState === Dock.Hide, but for top and right positions the hide state is not considered (only geometry); it may be worth clarifying or aligning this behavior so that margin handling for hidden/auto-hidden docks is consistent across all positions.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The `updateMargins` function repeats the pattern of resetting all margin values to 0 in several early-return branches; consider extracting this into a small helper (e.g. `resetMargins()`) to reduce duplication and make the intent clearer.
- The `switch (dockPosition)` uses raw numeric values (0/1/2) with comments for `DOCK_TOP/RIGHT/BOTTOM`; if the dock API exposes an enum or constants for these positions, using them instead of magic numbers would make the code more self-documenting and less error-prone.
- For the bottom dock you explicitly gate the margin on `hideState === Dock.Hide`, but for top and right positions the hide state is not considered (only geometry); it may be worth clarifying or aligning this behavior so that margin handling for hidden/auto-hidden docks is consistent across all positions.

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.

@deepin-bot
Copy link

deepin-bot bot commented Dec 4, 2025

TAG Bot

New tag: 2.0.21
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1364

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves the notification center's margin calculation to properly account for the dock's position and visibility. The change replaces a simple position-based margin calculation with a comprehensive geometry-based approach that handles device pixel ratios and dynamic dock state changes.

Key changes:

  • Replaced windowMargin(position) function with updateMargins(frontendRect) that uses dock geometry instead of simple position checks
  • Added property storage for margin values (topMarginValue, rightMarginValue, bottomMarginValue) to avoid recalculation on every access
  • Implemented device pixel ratio conversion to translate dock geometry from device pixels to logical pixels for accurate positioning

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@deepin-bot
Copy link

deepin-bot bot commented Dec 11, 2025

TAG Bot

New tag: 2.0.22
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1366

@deepin-bot
Copy link

deepin-bot bot commented Dec 18, 2025

TAG Bot

New tag: 2.0.23
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1371

@deepin-bot
Copy link

deepin-bot bot commented Dec 25, 2025

TAG Bot

New tag: 2.0.24
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1380

@deepin-bot
Copy link

deepin-bot bot commented Jan 7, 2026

TAG Bot

New tag: 2.0.25
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1394

@deepin-bot
Copy link

deepin-bot bot commented Jan 14, 2026

TAG Bot

New tag: 2.0.26
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1396

@deepin-bot
Copy link

deepin-bot bot commented Jan 23, 2026

TAG Bot

New tag: 2.0.27
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1401

@deepin-bot
Copy link

deepin-bot bot commented Jan 29, 2026

TAG Bot

New tag: 2.0.28
DISTRIBUTION: unstable
Suggest: synchronizing this PR through rebase #1415

@wjyrich wjyrich force-pushed the fix-bug-340795 branch 2 times, most recently from 1c076fd to 4f2f176 Compare February 2, 2026 08:21
@wjyrich wjyrich requested a review from 18202781743 February 2, 2026 08:22
@wjyrich wjyrich force-pushed the fix-bug-340795 branch 2 times, most recently from 62b019d to 4de5744 Compare February 3, 2026 03:12
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

1. Fixed notification center window positioning logic to use
frontendWindowRect for accurate dock geometry
2. Added special handling for bottom dock to avoid jitter by checking
hideState
3. Improved margin calculation by considering actual visible dock area
on screen edges
4. Added property binding for frontendRect updates when dock geometry
changes

Log: Fixed notification center positioning issues near dock edges

Influence:
1. Test notification center positioning when dock is at top/right/bottom
positions
2. Verify no jitter when dock is at bottom with hide/show states
3. Test positioning accuracy when dock spans multiple screens
4. Verify correct margin calculation when dock is partially off-screen
5. Test notification center behavior during dock position changes
6. Verify frontendRect updates properly when dock geometry changes

fix: 修复通知中心窗口定位问题

1. 修复通知中心窗口定位逻辑,使用 frontendWindowRect 获取准确的 dock 几
何信息
2. 为底部 dock 添加特殊处理,通过检查 hideState 避免抖动问题
3. 改进边距计算,考虑屏幕边缘 dock 的实际可见区域
4. 添加 frontendRect 属性绑定,在 dock 几何信息变化时更新

Log: 修复通知中心在 dock 边缘的定位问题

Influence:
1. 测试通知中心在 dock 位于顶部/右侧/底部时的定位
2. 验证 dock 在底部隐藏/显示状态时无抖动
3. 测试 dock 跨多个屏幕时的定位准确性
4. 验证 dock 部分超出屏幕时的边距计算正确性
5. 测试 dock 位置变化时通知中心的行为
6. 验证 dock 几何信息变化时 frontendRect 正确更新

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

deepin pr auto review

这段代码主要对 Dock 面板(DockPanel)的窗口矩形计算逻辑进行了重构,并修改了通知中心(Notification Center)中关于 Dock 边距的计算逻辑。

以下是针对语法逻辑、代码质量、代码性能和代码安全的详细审查意见:

1. 语法逻辑

  • 逻辑变更分析
    • C++ 部分:将 frontendWindowRect 从一个"计算并返回"的函数重构为"更新成员变量"的 setFrontendWindowRect 函数。这是一种典型的从"即时计算"(Just-in-time)到"缓存/状态化"(Stateful)的转变。
    • QML 部分windowMargin 函数不再简单地判断 Dock 是否隐藏,而是基于 frontendWindowRect 进行复杂的可见性计算。
  • 潜在逻辑缺陷(严重)
    • 初始化缺失:在 DockPanel 类中引入了新成员 m_frontendWindowRect,但代码片段中未显示其在构造函数中的初始化。如果 frontendWindowRect()setFrontendWindowRect 被首次调用前被访问(例如通过 QML 绑定),将读取未初始化的内存,导致未定义行为(UB)。
    • 状态同步风险:C++ 代码依赖于 onWindowGeometryChangednotifyDockPositionChanged 来更新 m_frontendWindowRect。如果存在其他修改窗口几何属性但未触发这两个信号的路径(例如直接调用 setGeometry 或某些底层窗口事件),m_frontendWindowRect 将过时,导致 QML 获取错误的边距数据。
    • QML 计算逻辑不一致:在 windowMargin 的 QML 代码中,case 2: // DOCK_BOTTOM 直接返回了 dockApplet.dockSize,而 case 0case 1 进行了复杂的几何交集计算。这看起来是不一致的。如果 Dock 位于底部且部分被遮挡(例如分屏场景),直接返回 dockSize 可能会导致通知中心布局错误。

2. 代码质量

  • 命名与封装
    • 函数名 setFrontendWindowRect 带有 set 前缀,通常意味着这是一个 Setter,用于设置外部传入的值。但这里的实现是根据 transformOffsetX/Y 和当前状态计算并更新内部值。建议重命名为 updateFrontendWindowRect 以更准确地反映其行为。
    • m_frontendWindowRect 是一个私有成员,通过 frontendWindowRect() 暴露。这符合封装原则。
  • 代码冗余
    • notifyDockPositionChangedonWindowGeometryChanged 中,都重复了"更新 -> 发射信号"的模式。这虽然目前看起来还好,但如果未来有更多地方需要触发更新,建议封装一个私有的 updateAndNotifyFrontendRect() 函数来减少重复代码。

3. 代码性能

  • C++ 性能
    • 缓存收益:将计算结果缓存到 m_frontendWindowRect 中,避免了每次调用 frontendWindowRect() 时都进行乘除法和屏幕几何查询。如果该属性被 QML 频繁读取(例如在动画或布局传递中),这将显著提高性能。
  • QML 性能
    • 频繁计算:QML 中的 windowMargin 包含了较多的数学运算和对象属性访问(root.screen.virtualX 等)。如果这个函数在属性绑定中被频繁触发(例如窗口大小改变、动画过程中),可能会造成 UI 卡顿。
    • 除法运算frontendRect.x / dpr 等除法运算在 QML 绑定中频繁执行效率较低。虽然现代 JS 引擎优化较好,但在高频调用的场景下仍需注意。

4. 代码安全

  • 空指针检查
    • setFrontendWindowRect 中保留了 if(!window()) return; 的检查,这是很好的防御性编程实践,防止在窗口未初始化时崩溃。
  • 除零风险
    • QML 代码中使用了 root.screen.devicePixelRatio 作为除数。虽然 devicePixelRatio 通常不会为 0,但在极端异常情况下(或某些驱动问题),为了绝对安全,建议添加检查:let dpr = root.screen.devicePixelRatio || 1.0

改进建议

  1. 修复初始化问题
    DockPanel 构造函数中初始化成员变量。

    // 在 dockpanel.cpp 的构造函数中
    DockPanel::DockPanel(...) 
        : m_frontendWindowRect() // 确保初始化为空矩形
        , ... 
    {
        // ...
    }
  2. 修正 QML 底部 Dock 的计算逻辑
    确保底部 Dock 的逻辑与其他位置一致,或者明确注释为什么底部可以直接返回 dockSize。如果需要统一逻辑,建议如下修改:

    case 2: { // DOCK_BOTTOM
        // 计算可见高度,与 TOP 逻辑类似但方向不同
        let visibleHeight = Math.max(0, screenGeometry.y + screenGeometry.height - dockGeometry.y);
        return Math.min(visibleHeight, dockGeometry.height);
    }
  3. 优化 QML 性能与安全

    let dockApplet = DS.applet("org.deepin.ds.dock")
    if (!dockApplet || !root.screen) return 0; // 增加 screen 的检查
    
    // ... 前面的代码 ...
    
    let dpr = root.screen.devicePixelRatio;
    if (dpr <= 0) dpr = 1.0; // 防御性编程,防止除零
    
    // ... 后续代码 ...
  4. C++ 函数重命名
    setFrontendWindowRect 改为 updateFrontendWindowRect,语义更清晰。

  5. 逻辑一致性检查
    原代码中 let dockIsHide = dockHideState === 2,新代码移除了对 HideState 的显式检查。这暗示现在的逻辑是:即使 Dock 处于隐藏状态(HideState == 2),只要 frontendWindowRect 返回了非空矩形,QML 就会计算边距。

    • 确认点:请确认 frontendWindowRect 在 Dock 隐藏时是否正确返回了空矩形或完全在屏幕外的矩形。如果 setFrontendWindowRect 在隐藏时没有正确处理 m_frontendWindowRect,可能会导致通知中心误以为 Dock 依然占据空间。

总结:这次重构通过缓存计算结果提升了 C++ 端的性能,但引入了状态管理的复杂性(需要确保缓存始终有效)。QML 端的计算逻辑更加精细,但需注意边界情况和性能开销。最重要的是补全成员变量的初始化并修正 QML 中底部 Dock 的计算逻辑。

@deepin-ci-robot
Copy link

[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
Contributor Author

wjyrich commented Feb 4, 2026

/forcemerge

@deepin-bot
Copy link

deepin-bot bot commented Feb 4, 2026

This pr force merged! (status: behind)

@deepin-bot deepin-bot bot merged commit 0bedee1 into linuxdeepin:master Feb 4, 2026
10 of 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