Skip to content

fix: persist display scale after logout and re-login#3226

Merged
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
caixr23:bug-360835
May 14, 2026
Merged

fix: persist display scale after logout and re-login#3226
deepin-bot[bot] merged 1 commit into
linuxdeepin:masterfrom
caixr23:bug-360835

Conversation

@caixr23
Copy link
Copy Markdown
Contributor

@caixr23 caixr23 commented May 12, 2026

  1. Set this as parent for two QDBusPendingCallWatcher objects in DisplayWorker::active()
  2. Without a parent, the watcher cannot be moved to the correct thread during thread switches, causing its connected slots to never execute, so scale factors are not saved
  3. Affects GetScaleFactor and GetScreenScaleFactors watchers

PMS: BUG-360835

Influence:

  1. Switch display scale, log out and re-login, verify the scale setting is correctly preserved
  2. Set different scale factors per monitor, log out and re-login to verify each monitor keeps its scale

fix: 修复切换缩放后注销再登录缩放恢复为100%的问题

  1. 为 DisplayWorker::active() 中的两个 QDBusPendingCallWatcher 对象设置 this 作为 parent
  2. 未设置 parent 时,切换线程后 watcher 无法找到目标线程, 导致连接的槽函数永远不会执行,缩放比例未能正确保存
  3. 影响 GetScaleFactor 和 GetScreenScaleFactors 的 watcher

PMS: BUG-360835

Influence:

  1. 切换缩放比例后注销再重新登录,验证缩放设置是否被正确保持
  2. 多显示器场景下分别设置不同缩放比例后注销再登录验证

@caixr23 caixr23 requested a review from mhduiy May 12, 2026 05:15
Copy link
Copy Markdown

@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.

Sorry @caixr23, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@deepin-ci-robot
Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: caixr23, robertkill

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

1. Set `this` as parent for two QDBusPendingCallWatcher objects
   in DisplayWorker::active()
2. Without a parent, the watcher cannot be moved to the correct
   thread during thread switches, causing its connected slots to
   never execute, so scale factors are not saved
3. Affects GetScaleFactor and GetScreenScaleFactors watchers

PMS: BUG-360835

Influence:
1. Switch display scale, log out and re-login, verify the scale
   setting is correctly preserved
2. Set different scale factors per monitor, log out and re-login
   to verify each monitor keeps its scale

fix: 修复切换缩放后注销再登录缩放恢复为100%的问题

1. 为 DisplayWorker::active() 中的两个 QDBusPendingCallWatcher
   对象设置 this 作为 parent
2. 未设置 parent 时,切换线程后 watcher 无法找到目标线程,
   导致连接的槽函数永远不会执行,缩放比例未能正确保存
3. 影响 GetScaleFactor 和 GetScreenScaleFactors 的 watcher

PMS: BUG-360835

Influence:
1. 切换缩放比例后注销再重新登录,验证缩放设置是否被正确保持
2. 多显示器场景下分别设置不同缩放比例后注销再登录验证
@caixr23
Copy link
Copy Markdown
Contributor Author

caixr23 commented May 14, 2026

/forcemerge

@deepin-bot
Copy link
Copy Markdown

deepin-bot Bot commented May 14, 2026

This pr force merged! (status: blocked)

@deepin-bot deepin-bot Bot merged commit 2252acd into linuxdeepin:master May 14, 2026
16 of 19 checks passed
@deepin-ci-robot
Copy link
Copy Markdown

deepin pr auto review

你好!我是CodeGeeX,你的智能编程助手。我已经仔细审查了你提供的 Git Diff 输入。

本次代码修改的核心是:为两个新创建的 QDBusPendingCallWatcher 对象指定了父对象(this,即 DisplayWorker)。这是一个非常优秀且关键的改进。下面我将从语法逻辑、代码质量、代码性能和代码安全四个维度为你进行详细的审查和点评:

总体评价

这次修改虽然只有两行,但解决了一个非常经典的 Qt 编程隐患——对象生命周期管理(内存泄漏)。将 this 传递给 QDBusPendingCallWatcher 的构造函数,利用了 Qt 的对象树机制来自管理内存,是一个高质量的修复。


详细审查意见

1. 语法逻辑 ✅ 优秀

  • 符合 Qt 对象树机制:在 Qt 中,所有继承自 QObject 的类在构造时都可以指定一个父对象。当父对象被销毁时,它的所有子对象也会被自动销毁。QDBusPendingCallWatcher 继承自 QObject,将 DisplayWorkerthis)设为父对象,逻辑完全正确。
  • 异步回调逻辑闭环:代码中使用了 connect 将 watcher 的 finished 信号与槽函数绑定。当异步 D-Bus 调用完成时,触发槽函数。此时 watcher 的使命完成,指定父对象确保了在槽函数处理完毕后,或者 DisplayWorker 提前销毁时,watcher 能够被合理回收,不会产生悬空指针。

2. 代码质量 ✅ 显著提升

  • 修复潜在内存泄漏
    • 修改前new QDBusPendingCallWatcher(...) 没有指定父对象。如果 finished 信号触发,在槽函数 onGetScaleFinished 等实现中,开发者必须显式调用 watcher->deleteLater()delete watcher 来释放内存。如果槽函数中遗漏了这一步,或者由于某些异常导致槽函数未执行,就会产生内存泄漏
    • 修改后:即使槽函数中忘记调用 deleteLater(),当 DisplayWorker 析构时,Qt 的对象树机制也会确保这两个 watcher 被安全删除,代码的健壮性大大增强。

3. 代码性能 ✅ 无负面影响

  • 轻微的构造开销可忽略不计:将 this 传递给构造函数,底层会执行将该子对象加入父对象 children 列表的操作(涉及链表插入和信号连接)。这在对象创建时会有极微小的开销,但相比于它所避免的内存泄漏风险,以及 D-Bus 远程调用的网络/I/O延迟,这点性能开销完全可以忽略不计。
  • 避免野指针崩溃:如果 DisplayWorker 被销毁,而 watcher 依然存活并发出 finished 信号,由于没有指定父对象且未解绑信号,可能会引发野指针崩溃。指定父对象后,Qt 会在析构时自动解绑信号与槽,提升了运行时的稳定性。

4. 代码安全 ✅ 提升了安全性

  • 防止资源耗尽(DoS 隐患):如果 active() 函数被频繁调用,而 watcher 没有被正确释放,内存会持续增长,形成内存泄漏,极端情况下可能被恶意利用导致系统资源耗尽。指定父对象后,这些 watcher 的生命周期被严格限制在 DisplayWorker 的生命周期内,消除了这一隐患。
  • 线程安全考量QDBusPendingCallWatcher 通常在创建它的线程中完成回调。只要确保 DisplayWorker 对象及其所属线程的生命周期管理正常(即 watcher 和 DisplayWorker 同属一个线程,或者遵循 Qt 跨线程对象销毁的规则),这种写法就是安全的。

💡 进阶改进建议

虽然当前的修改已经很好,但为了追求更完美的代码质量,我建议检查或补充以下几点:

  1. 检查槽函数中的内存释放代码
    请检查 onGetScaleFinishedonGetScreenScalesFinished 这两个槽函数的实现。如果里面原本有 watcher->deleteLater(); 这样的代码,现在依然可以保留。因为 deleteLater() 会安全地将对象标记为待删除,并在下一次事件循环中销毁它,这比等到 DisplayWorker 析构时才销毁更及时,能更快地释放内存。如果槽函数里没有这行代码,现在不加也不会泄漏了,但加上能更及时地回收资源。

  2. 注意 DisplayWorker 的生命周期与异步调用的竞态
    如果 DisplayWorker 可能在 D-Bus 异步调用还未返回时就被销毁,Qt 的对象树会自动 delete 这两个 watcher。这会导致 finished 信号不再发出,槽函数也不会执行。这在逻辑上是安全的(不会崩溃),但需要确保业务逻辑上允许“如果 Worker 销毁了,就不处理 D-Bus 的返回结果”。

  3. Lambda 表达式的捕获安全(扩展提醒)
    如果未来有其他地方使用 Lambda 代替 this 槽函数来接收 finished 信号,例如:

    connect(scalewatcher, &QDBusPendingCallWatcher::finished, this, [this](QDBusPendingCallWatcher* w){
        // 处理逻辑
        w->deleteLater();
    });

    务必确保 Lambda 捕获的是 this(或者使用 QPointer 智能指针),避免当 DisplayWorker 提前销毁时,Lambda 中访问 this 成员导致崩溃。

总结:这是一次非常棒的提交,精准地修复了 Qt 编程中常见的内存管理问题。代码逻辑正确,质量提升显著,请放心合并!

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