Skip to content

Conversation

@yixinshark
Copy link
Contributor

@yixinshark yixinshark commented Aug 21, 2025

Consider multiple screen combination styles

Log: as title
Pms: TASK-380785

Summary by Sourcery

Reimplement the exclusion zone calculation to support multi-screen layouts and proper DPI scaling for all panel anchor positions, replacing the previous single-screen logic and adding comprehensive documentation.

New Features:

  • Support exclusion zone calculation for multiple monitors and mixed screen arrangements (horizontal, vertical, and hybrid).

Enhancements:

  • Revise the algorithm to compute desktop boundaries across screens and correctly convert between logical and physical pixels using Qt’s mixed coordinate system.
  • Add detailed debug logging for exclusion zone values per anchor (left, right, top, bottom).

Documentation:

  • Add exclusion_zone_calculation.md with in-depth rules, formulas, and examples for the new calculation method.

@sourcery-ai
Copy link

sourcery-ai bot commented Aug 21, 2025

Reviewer's Guide

Rework onExclusionZoneChanged to calculate exclusion zones based on physical screen coordinates and scale factors for multi-screen setups, and add documentation outlining the algorithm and usage.

Class diagram for LayerShellEmulation exclusion zone calculation

classDiagram
    class LayerShellEmulation {
        +onExclusionZoneChanged()
        -m_dlayerShellWindow: DLayerShellWindow
        -m_window: QWindow
    }
    class DLayerShellWindow {
        +anchors()
        +exclusionZone()
    }
    class QScreen {
        +geometry()
    }
    class QWindow {
        +screen()
        +geometry()
        +height()
        +width()
        +winId()
    }
    LayerShellEmulation --> DLayerShellWindow
    LayerShellEmulation --> QWindow
    QWindow --> QScreen
Loading

Flow diagram for exclusion zone calculation logic

flowchart TD
    A[Start: onExclusionZoneChanged] --> B{Which anchor?}
    B -->|AnchorLeft| C[Calculate left exclusion zone: screen.x + exclusionZone * scaleFactor]
    B -->|AnchorRight| D[Find desktop right boundary]
    D --> E[Calculate current screen right boundary]
    E --> F[Calculate distance to desktop right]
    F --> G[Calculate right exclusion zone: distance + exclusionZone * scaleFactor]
    B -->|AnchorTop| H[Calculate top exclusion zone: screen.y + exclusionZone * scaleFactor]
    B -->|AnchorBottom| I{Find below screens with horizontal overlap}
    I -->|Found| J[Sum below screens height]
    J --> K[Calculate bottom exclusion zone: belowScreensHeight * scaleFactor + exclusionZone * scaleFactor]
    I -->|Not found| L[Find desktop bottom boundary]
    L --> M[Calculate distance to desktop bottom]
    M --> N[Calculate bottom exclusion zone: distance + exclusionZone * scaleFactor]
    C --> O[Update strut_partial]
    G --> O
    H --> O
    K --> O
    N --> O
    O --> P[End]
Loading

File-Level Changes

Change Details Files
Overhaul exclusion zone computation logic
  • Replace previous QRect-based calculations with QScreen geometry and scaleFactor conversions
  • Implement per-anchor strut_partial assignments using physical coordinate formulas
  • Compute global desktop boundaries and multi-screen distances for right and bottom anchors
  • Detect overlapping screens below the current screen with a fallback to desktop boundary
  • Add qCDebug logging statements for each anchor case
frame/layershell/x11dlayershellemulation.cpp
Add comprehensive exclusion zone calculation documentation
  • Introduce a markdown file explaining the mixed coordinate system and scaling
  • Detail formulas, layout examples, and anchor-specific computation rules
  • Include debugging log examples and usage scenarios
frame/layershell/exclusion_zone_calculation.md

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 and they look great!

Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments

### Comment 1
<location> `frame/layershell/x11dlayershellemulation.cpp:266` </location>
<code_context>
+                            << "result=" << strut_partial.bottom;
+
+        strut_partial.bottom_start_x = static_cast<uint32_t>(m_window->geometry().x());
+        strut_partial.bottom_end_x = static_cast<uint32_t>(m_window->geometry().x() + m_window->geometry().width() * scaleFactor);
     }

</code_context>

<issue_to_address>
Potential for overflow or precision loss when casting to uint32_t.

Use a safe rounding method and validate for overflow before casting to uint32_t to prevent data loss.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        strut_partial.bottom_start_x = static_cast<uint32_t>(m_window->geometry().x());
        strut_partial.bottom_end_x = static_cast<uint32_t>(m_window->geometry().x() + m_window->geometry().width() * scaleFactor);
=======
        {
            double start_x = m_window->geometry().x();
            double end_x = m_window->geometry().x() + m_window->geometry().width() * scaleFactor;

            auto safe_cast = [](double value) -> uint32_t {
                if (value < 0) {
                    qWarning() << "Value underflow in bottom_start_x/bottom_end_x:" << value << ", clamping to 0";
                    return 0;
                }
                if (value > static_cast<double>(UINT32_MAX)) {
                    qWarning() << "Value overflow in bottom_start_x/bottom_end_x:" << value << ", clamping to UINT32_MAX";
                    return UINT32_MAX;
                }
                return static_cast<uint32_t>(std::round(value));
            };

            strut_partial.bottom_start_x = safe_cast(start_x);
            strut_partial.bottom_end_x = safe_cast(end_x);
        }
>>>>>>> REPLACE

</suggested_fix>

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 on lines +265 to +266
strut_partial.bottom_start_x = static_cast<uint32_t>(m_window->geometry().x());
strut_partial.bottom_end_x = static_cast<uint32_t>(m_window->geometry().x() + m_window->geometry().width() * scaleFactor);
Copy link

Choose a reason for hiding this comment

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

suggestion (bug_risk): Potential for overflow or precision loss when casting to uint32_t.

Use a safe rounding method and validate for overflow before casting to uint32_t to prevent data loss.

Suggested change
strut_partial.bottom_start_x = static_cast<uint32_t>(m_window->geometry().x());
strut_partial.bottom_end_x = static_cast<uint32_t>(m_window->geometry().x() + m_window->geometry().width() * scaleFactor);
{
double start_x = m_window->geometry().x();
double end_x = m_window->geometry().x() + m_window->geometry().width() * scaleFactor;
auto safe_cast = [](double value) -> uint32_t {
if (value < 0) {
qWarning() << "Value underflow in bottom_start_x/bottom_end_x:" << value << ", clamping to 0";
return 0;
}
if (value > static_cast<double>(UINT32_MAX)) {
qWarning() << "Value overflow in bottom_start_x/bottom_end_x:" << value << ", clamping to UINT32_MAX";
return UINT32_MAX;
}
return static_cast<uint32_t>(std::round(value));
};
strut_partial.bottom_start_x = safe_cast(start_x);
strut_partial.bottom_end_x = safe_cast(end_x);
}

Consider multiple screen combination styles

Log: as title
Pms: TASK-380785
@yixinshark yixinshark force-pushed the fix-allExclusionZoneErrors branch from 93a567a to 07b5e46 Compare August 21, 2025 09:25
@deepin-ci-robot
Copy link

deepin pr auto review

代码审查报告:DDE-Shell 独占区域计算

总体评价

代码实现了复杂的屏幕布局和独占区域计算逻辑,考虑了多种屏幕配置和缩放比例。整体设计合理,但存在一些可以改进的地方。

详细分析

1. 代码逻辑

优点:

  • 完整实现了文档中描述的所有锚定类型的计算规则
  • 正确处理了Qt混合坐标系统
  • 支持多种屏幕布局(垂直、水平、混合)
  • 包含详细的调试日志

问题:

  • AnchorBottom 的实现逻辑较为复杂,可能存在边界情况处理不当
  • 缺少对异常输入(如负数的exclusionZone)的验证
  • 一些计算步骤可以进一步优化,减少重复计算

2. 代码质量

优点:

  • 代码结构清晰,每个锚定类型的处理逻辑独立
  • 添加了适当的注释说明关键计算步骤
  • 使用了static_cast确保类型安全

问题:

  • 部分变量命名可以更具描述性(如boundary改为maxBoundary)
  • 一些代码块过长,可以进一步拆分
  • 缺少对scaleFactor为0的特殊情况处理

3. 性能分析

优点:

  • 在计算桌面边界时只遍历一次屏幕列表
  • 合理使用static_cast避免不必要的类型转换

问题:

  • 在AnchorBottom处理中,对每个屏幕都进行重叠检测,可能影响性能
  • 一些计算(如currentScreenRightPhysical)在多个分支中重复计算

4. 安全性

优点:

  • 使用static_cast确保类型转换安全
  • 对strut_partial结构体进行了初始化

问题:

  • 缺少对scaleFactor的有效性检查(如是否为0或负数)
  • 没有对exclusionZone的值范围进行验证
  • 在计算过程中可能存在整数溢出的风险(特别是乘法运算后)

改进建议

1. 代码逻辑优化

// 在AnchorBottom处理中,可以预先计算当前屏幕的物理边界
const int currentScreenBottomPhysical = currentScreen->geometry().y() + 
    static_cast<int>(currentScreen->geometry().height() * scaleFactor);
const QRect currentRect = currentScreen->geometry();

// 添加输入验证
if (scaleFactor <= 0 || m_dlayerShellWindow->exclusionZone() < 0) {
    qCWarning(layershell) << "Invalid scaleFactor or exclusionZone";
    return;
}

2. 性能优化

// 可以预先计算并缓存常用的值
struct ScreenBounds {
    int leftPhysical;
    int rightPhysical;
    int bottomPhysical;
};

// 在循环外预先计算
const auto currentScreenRightPhysical = currentRect.x() + 
    static_cast<int>(currentRect.width() * scaleFactor);

3. 安全性增强

// 添加数值范围检查
if (m_dlayerShellWindow->exclusionZone() > MAX_EXCLUSION_ZONE) {
    qCWarning(layershell) << "Exclusion zone too large";
    return;
}

// 使用安全的乘法运算,防止溢出
auto safeMultiply = [](int a, double b) {
    if (a > INT_MAX / b || a < INT_MIN / b) {
        qCWarning(layershell) << "Potential integer overflow";
        return INT_MAX;
    }
    return static_cast<int>(a * b);
};

4. 代码结构优化

// 将每个锚定类型的处理提取为单独的函数
void calculateLeftAnchoredStrut(...);
void calculateRightAnchoredStrut(...);
void calculateTopAnchoredStrut(...);
void calculateBottomAnchoredStrut(...);

// 主函数简化为:
switch (anchors) {
    case DLayerShellWindow::AnchorLeft:
    case (DLayerShellWindow::AnchorLeft | DLayerShellWindow::AnchorTop | DLayerShellWindow::AnchorBottom):
        calculateLeftAnchoredStrut(...);
        break;
    // ... 其他情况
}

总结

代码整体实现良好,但仍有改进空间。主要改进方向包括:

  1. 增加输入验证和错误处理
  2. 优化性能,减少重复计算
  3. 增强安全性,防止数值溢出
  4. 改进代码结构,提高可维护性
  5. 添加单元测试,确保各种边界情况都能正确处理

这些改进将使代码更加健壮、高效和易于维护。

@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: 18202781743, yixinshark

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

@yixinshark yixinshark merged commit f4e82cf into linuxdeepin:master Aug 21, 2025
8 of 10 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