Skip to content

fix: restore timer-based rotation detection for phone screen mirroring - #812

Draft
re2zero wants to merge 1 commit into
linuxdeepin:masterfrom
re2zero:agent/pms-bug-bot/bf3c79beb0ae
Draft

re2zero wants to merge 1 commit into
linuxdeepin:masterfrom
re2zero:agent/pms-bug-bot/bf3c79beb0ae

Conversation

@re2zero

@re2zero re2zero commented Oct 23, 2026 •

Copy link
Copy Markdown
Contributor

修复说明

问题

BUG-314949:移动端切换横屏但没有发消息到PC切换

手机投屏过程中,移动端切换横竖屏时 PC 端投屏画面未跟随旋转。

根因

  1. frameTimerTimeout() 中基于定时器的屏幕旋转检测逻辑在提交 d5800f77 中被移除,改用 ScreenSizeChanged 回调,但该回调随后被注释掉(系统 libvncclient 0.9.15 无此字段)
  2. 后续在 updateImage() 中添加了逐帧检测,但存在性能开销(每帧检测)和可靠性问题(依赖下一帧数据到达,存在时序窗口)
  3. m_phoneScale 仅在初始化时计算一次,旋转后未重算,导致显示尺寸/比例错误
  4. handleSizeChange() 中"只放大不缩小"的条件限制(> 改为 !=)

修复方案

  1. vncviewer.cpp - frameTimerTimeout():恢复定时器周期性尺寸检测,读取 m_rfbCli->width/height 与 m_phoneMode 比较,检测到旋转时重算 m_phoneScale(与 start() 初始化逻辑一致),清除图像缓存,调用 setSurfaceSize() 并 emit sizeChanged
  2. vncviewer.cpp - updateImage():简化为纯图像更新,移除逐帧旋转检测逻辑(现由定时器处理)
  3. screenmirroringwindow.cpp - handleSizeChange():将条件从 w > this->width() || h > this->height() 改为 w != this->width() || h != this->height(),支持双向 resize

改动文件

  • src/lib/cooperation/core/gui/phone/vncviewer.cpp
  • src/lib/cooperation/core/gui/phone/screenmirroringwindow.cpp

测试建议

  • 测试手机投屏时竖屏转横屏的旋转切换
  • 测试手机投屏时横屏转竖屏的旋转切换
  • 验证持续投屏过程中无性能下降

PMS: BUG-314949

Summary by Sourcery

Restore timer-based rotation handling for phone screen mirroring and support bidirectional display resizing.

Bug Fixes:

  • Restore reliable phone screen rotation detection during mirroring so portrait-to-landscape and landscape-to-portrait changes update the PC display correctly.
  • Allow the mirroring window to resize in both directions when the screen dimensions change.

Enhancements:

  • Move rotation handling out of per-frame image updates and into periodic timer-based checks, while recalculating the display scale and refreshing the rendered surface after rotation.

1. Root cause: timer-based screen rotation detection in
   frameTimerTimeout() was removed in d5800f7, replaced by a
   ScreenSizeChanged callback that was later commented out, then a
   per-frame detection in updateImage() with performance and
   reliability issues; m_phoneScale was never recalculated after
   rotation causing incorrect display dimensions
2. Fix: restore periodic size check in frameTimerTimeout() that reads
   m_rfbCli->width/height and recalculates m_phoneScale on rotation
   change, matching the init logic in start(); simplify updateImage()
   to pure image update; change handleSizeChange() condition from
   greater-than to not-equal for bidirectional resize support
3. Impact: phone screen mirroring now correctly detects and handles
   both portrait-to-landscape and landscape-to-portrait rotations with
   proper scale recalculation

Log: fix phone screen mirroring rotation detection

Influence:
1. Test portrait-to-landscape rotation during phone screen mirroring
2. Test landscape-to-portrait rotation during phone screen mirroring
3. Verify no performance degradation during continuous mirroring

fix: 恢复手机投屏的定时器旋转检测机制

1. 根因:frameTimerTimeout() 中基于定时器的屏幕旋转检测在
   d5800f7 中被移除,改用 ScreenSizeChanged 回调后被注释,
   后续在 updateImage() 中逐帧检测存在性能和可靠性问题;
   m_phoneScale 旋转后未重算导致显示尺寸不正确
2. 方案:在 frameTimerTimeout() 中恢复周期性尺寸检测,读取
   m_rfbCli->width/height 并在旋转变化时重算 m_phoneScale,
   与 start() 初始化逻辑一致;简化 updateImage() 为纯图像更新;
   handleSizeChange() 条件从大于改为不等于以支持双向 resize
3. 影响:手机投屏现在能正确检测并处理竖屏转横屏和横屏转竖屏,
   并正确重算缩放比例

Log: 修复手机投屏旋转检测问题

Influence:
1. 测试手机投屏时竖屏转横屏的旋转切换
2. 测试手机投屏时横屏转竖屏的旋转切换
3. 验证持续投屏过程中无性能下降

PMS: BUG-314949
@re2zero
re2zero marked this pull request as draft October 23, 2026 08:09
@deepin-ci-robot

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: re2zero

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 Oct 23, 2026

Copy link
Copy Markdown

Sorry @re2zero, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 5 days and 1 hour by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 23, 2026

Copy link
Copy Markdown

Reviewer's Guide

Restores periodic framebuffer-based rotation detection in the timer callback, where orientation changes now recalculate scaling, clear stale image state, resize the rendering surface, and notify the window; removes the costlier per-frame detection and enables bidirectional window resizing.

Sequence diagram for timer-based screen rotation handling

sequenceDiagram
    participant Timer as frameTimerTimeout()
    participant Viewer as VncViewer
    participant Framebuffer as m_rfbCli
    participant Window as ScreenMirroringWindow

    Timer->>Viewer: frameTimerTimeout()
    Viewer->>Framebuffer: read width and height
    alt orientation changed
        Viewer->>Viewer: recalculate m_phoneScale
        Viewer->>Viewer: setSurfaceSize(size)
        Viewer->>Viewer: emit sizeChanged(size)
        Viewer-->>Window: sizeChanged(size)
        Window->>Window: handleSizeChange(size)
        Window->>Window: resize(w, h)
    end

    Viewer->>Viewer: updateImage(image)
    Viewer->>Viewer: store m_image and update()
Loading

Flow diagram for bidirectional mirroring window resize

flowchart TD
    A["handleSizeChange(size)"] --> B{size differs from current window?}
    B -- Yes --> C[Reset m_expectSize]
    C --> D["resize(w, h)"]
    B -- No --> E[Store m_expectSize]
Loading

File-Level Changes

Change Details Files
Restores timer-driven detection of phone orientation changes and recalculates the display scale and surface dimensions when the VNC framebuffer aspect changes.
  • Adds connection- and client-state checks before polling framebuffer dimensions.
  • Compares framebuffer orientation with the current phone mode under the existing mutex.
  • Recomputes portrait/landscape scaling, clears the cached image, resizes the surface, and emits the updated size.
src/lib/cooperation/core/gui/phone/vncviewer.cpp
Removes per-frame orientation detection so image updates only cache and refresh the incoming frame.
  • Deletes image-aspect-ratio rotation checks and associated resize signaling from the frame update path.
  • Retains mutex protection, null-image filtering, image assignment, and repaint scheduling.
src/lib/cooperation/core/gui/phone/vncviewer.cpp
Allows the mirroring window to resize in either direction when the requested dimensions differ from the current dimensions.
  • Changes the resize guard from growth-only to any width or height mismatch.
  • Resets the expected-size state after performing a resize.
src/lib/cooperation/core/gui/phone/screenmirroringwindow.cpp

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

@deepin-ci-robot

Copy link
Copy Markdown

deepin pr auto review

🤖 AI 代码审查报告

总体评分: 98 分 (通过阈值: 70分)

Pass


📊 总体评价

项目 结果
审查结论 代码审查通过
评分详情 本次提交重构了VNC屏幕旋转检测逻辑,将旋转检测从updateImage()回调移至frameTimerTimeout()定时器回调,通过直接检查RFB客户端尺寸提高检测可靠性;同时修改ScreenMirroringWindow的缩放条件,使窗口在尺寸变小时也能正确缩放。代码逻辑正确,线程安全处理得当,无安全漏洞,仅存在一处变量命名拼写错误(curentMode应为currentMode)。

🔍 详细分析

1. 语法逻辑 ✅

评价: 语法正确,逻辑清晰 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['无需修改']


2. 代码质量 ✅

评价: 代码结构清晰,注释完整 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['将 curentMode 修正为 currentMode,与原 updateImage() 中的命名保持一致']


3. 代码性能 ✅

评价: 性能良好,资源使用合理 ✅ 通过

潜在问题:
✅ 未发现明显问题

建议: ['无需修改']


4. 代码安全 🔒

评价: 存在0个安全漏洞 ✅ 通过

🔐 发现 0 个安全漏洞

安全漏洞详情:
✅ 未发现安全漏洞

建议: ['无需修改']


💡 改进建议代码示例

// 修正变量命名拼写错误
// vncviewer.cpp, frameTimerTimeout() 函数中

// 修改前:
// int curentMode = (m_rfbCli->width < m_rfbCli->height) ? PORTRAIT : LANDSCAPE;

// 修改后:
int currentMode = (m_rfbCli->width < m_rfbCli->height) ? PORTRAIT : LANDSCAPE;
if (currentMode != m_phoneMode) {
    DLOG << "Screen rotation detected by timer - old mode: " << m_phoneMode << " new mode: " << currentMode;
    m_phoneMode = currentMode;
    // ... 后续逻辑不变
}

本报告由 AI 代码审查工具自动生成

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