From 02f66fcffebb712cfa8df503b2f36f4b007bcd89 Mon Sep 17 00:00:00 2001 From: zhangkun Date: Sat, 30 May 2026 15:47:07 +0800 Subject: [PATCH] fix(power): fix idle ignored after wakeup, add wakeup lock, and support output hotplug MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Reset prepareSuspend to PS_Normal in HandleIdleOff so idle-on events are not permanently ignored after suspend/resume cycle 2. Call doLock in handleBeforeSleep unconditionally (not just Wayland) and in the wakeup delayed callback when sleepLock is set, ensuring lock screen shows after idle-timeout suspend 3. Keep wl_registry alive in WaylandScreenController to receive output hotplug events (zwlr_output_power_v1 and treeland color control for new monitors) 4. Use pointer-based lookup in signal handlers instead of captured vector index to avoid stale references after output removal 5. Switch brightness animation key from int index to registryName to survive output reordering on unplug Log: Fix idle state reset after wakeup, add wakeup lock logic, and support DPMS/brightness for hotplugged Wayland outputs fix(power): 修复唤醒后 idle 被忽略、增加唤醒锁屏、支持屏幕热插拔 1. HandleIdleOff 中重置 prepareSuspend 为 PS_Normal,修复待机唤醒后 idle 事件被永久忽略的问题 2. handleBeforeSleep 中不再限制 Wayland 才锁屏,handleWakeup 延迟回调中 sleepLock 开启时调用 doLock,确保 idle 超时待机唤醒后显示锁屏界面 3. WaylandScreenController 保持 wl_registry 活跃以接收热插拔事件,新接入屏幕自动获取 DPMS 和亮度控制 4. 信号回调改用裸指针查找当前 index,避免拔屏后 index 偏移导致访问错误 output 5. 亮度动画 key 改为 registryName,拔屏后 key 不受 index 偏移影响 Log: 修复唤醒后 idle 状态重置、增加唤醒锁屏、支持 Wayland 屏幕热插拔 DPMS/亮度管控 --- src/plugin-qt/power/session/powermanager.cpp | 15 ++-- src/plugin-qt/power/session/powersaveplan.cpp | 1 + .../session/screen/screencontroller_wl.cpp | 70 +++++++++++++------ .../session/screen/screencontroller_wl.h | 3 +- 4 files changed, 61 insertions(+), 28 deletions(-) diff --git a/src/plugin-qt/power/session/powermanager.cpp b/src/plugin-qt/power/session/powermanager.cpp index e48e2c1..ff9de2a 100644 --- a/src/plugin-qt/power/session/powermanager.cpp +++ b/src/plugin-qt/power/session/powermanager.cpp @@ -358,8 +358,8 @@ void PowerManager::handleBeforeSleep(bool) qDebug(logPowerSession) << "System is going to sleep, prepare suspend state:" << m_prepareSuspendState; m_prepareSuspendState = PS_Sleeping; setBlackScreenActive(true); - if (m_useWayland && m_sleepLock) { - m_proxy->lockSession(currentSessionId()); + if (m_sleepLock) { + doLock(true); } } @@ -370,11 +370,18 @@ void PowerManager::handleWakeup() m_delayInActive = true; QTimer::singleShot(m_delayWakeupInterval * 1000, this, [this]() { m_delayInActive = false; + if (m_sleepLock) { + qCDebug(logPowerSession) << "Locking session after wakeup delay"; + doLock(true); + } setBlackScreenActive(false); }); setDPMSModeOn(); - if (m_powerSavePlan) m_powerSavePlan->HandleIdleOff(); - if (m_scheduledShutdownState) scheduledShutdown(SchedInit); + if (m_powerSavePlan) + m_powerSavePlan->HandleIdleOff(); + + if (m_scheduledShutdownState) + scheduledShutdown(SchedInit); } void PowerManager::Reset() diff --git a/src/plugin-qt/power/session/powersaveplan.cpp b/src/plugin-qt/power/session/powersaveplan.cpp index 96d0606..dc08621 100644 --- a/src/plugin-qt/power/session/powersaveplan.cpp +++ b/src/plugin-qt/power/session/powersaveplan.cpp @@ -165,6 +165,7 @@ void PowerSavePlan::HandleIdleOff() m_isIdle = false; interruptTasks(); if (!m_powerManager) return; + m_powerManager->SetPrepareSuspend(static_cast(PS_Normal)); if (m_powerManager->screenController()) { m_powerManager->screenController()->setAllModes(ScreenController::On); } diff --git a/src/plugin-qt/power/session/screen/screencontroller_wl.cpp b/src/plugin-qt/power/session/screen/screencontroller_wl.cpp index c6ae9ec..3a7e601 100644 --- a/src/plugin-qt/power/session/screen/screencontroller_wl.cpp +++ b/src/plugin-qt/power/session/screen/screencontroller_wl.cpp @@ -170,6 +170,8 @@ WaylandScreenController::~WaylandScreenController() m_outputs.clear(); m_treeLandMgr.reset(); m_manager.reset(); + if (m_registry) + wl_registry_destroy(m_registry); } static void scOutputGlobal(void *data, wl_registry *r, uint32_t name, @@ -184,21 +186,32 @@ static void scOutputGlobal(void *data, wl_registry *r, uint32_t name, out.wlOutput = wlo; out.power = sc->m_manager->getOutputPower(wlo); if (out.power) { - QObject::connect(out.power.get(), &OutputPower::modeChanged, - sc, [sc, idx = int(sc->m_outputs.size())](uint32_t m) { - if (idx < int(sc->m_outputs.size())) { - sc->m_outputs[idx].currentMode = m; - Q_EMIT sc->modeChanged(idx, m == 0 ? ScreenController::Off : ScreenController::On); + auto *pwr = out.power.get(); + QObject::connect(pwr, &OutputPower::modeChanged, + sc, [sc, pwr](uint32_t m) { + auto &outs = sc->m_outputs; + for (int i = 0; i < int(outs.size()); ++i) { + if (outs[i].power.get() == pwr) { + outs[i].currentMode = m; + Q_EMIT sc->modeChanged(i, m == 0 ? ScreenController::Off : ScreenController::On); + return; + } } }); } if (sc->m_brightnessAvailable) { out.colorControl.reset(sc->m_treeLandMgr->getColorControl(wlo)); if (out.colorControl) { - QObject::connect(out.colorControl.get(), &OutputColorControl::brightnessChanged, - sc, [sc, idx = int(sc->m_outputs.size())](double v) { - if (idx < int(sc->m_outputs.size())) - Q_EMIT sc->brightnessChanged(idx, v); + auto *cc = out.colorControl.get(); + QObject::connect(cc, &OutputColorControl::brightnessChanged, + sc, [sc, cc](double v) { + auto &outs = sc->m_outputs; + for (int i = 0; i < int(outs.size()); ++i) { + if (outs[i].colorControl.get() == cc) { + Q_EMIT sc->brightnessChanged(i, v); + return; + } + } }); } } @@ -212,8 +225,13 @@ static void scOutputRemove(void *data, wl_registry *, uint32_t name) auto &outs = sc->m_outputs; for (auto it = outs.begin(); it != outs.end(); ++it) { if (it->registryName == name) { - int idx = int(it - outs.begin()); - if (auto *anim = sc->m_brightnessAnims.take(idx)) { + if (it->power) { + QObject::disconnect(it->power.get(), nullptr, sc, nullptr); + } + if (it->colorControl) { + QObject::disconnect(it->colorControl.get(), nullptr, sc, nullptr); + } + if (auto *anim = sc->m_brightnessAnims.take(it->registryName)) { anim->stop(); anim->deleteLater(); } @@ -229,11 +247,12 @@ static const wl_registry_listener kOutputListener = {scOutputGlobal, scOutputRem void WaylandScreenController::discoverOutputs() { - auto *reg = wl_display_get_registry(m_display); - wl_registry_add_listener(reg, &kOutputListener, this); + if (m_registry) + wl_registry_destroy(m_registry); + m_registry = wl_display_get_registry(m_display); + wl_registry_add_listener(m_registry, &kOutputListener, this); wl_display_roundtrip(m_display); wl_display_roundtrip(m_display); - wl_registry_destroy(reg); } ScreenController::Mode WaylandScreenController::mode(int index) const @@ -291,7 +310,7 @@ void WaylandScreenController::setBrightness(int index, double value) return; } - if (auto *old = m_brightnessAnims.take(index)) { + if (auto *old = m_brightnessAnims.take(out.registryName)) { old->disconnect(this); old->stop(); old->deleteLater(); @@ -303,17 +322,22 @@ void WaylandScreenController::setBrightness(int index, double value) anim->setEndValue(value); anim->setEasingCurve(QEasingCurve::InOutCubic); + auto regName = out.registryName; connect(anim, &QVariantAnimation::valueChanged, this, - [this, index](const QVariant &v) { - if (index < 0 || size_t(index) >= m_outputs.size()) return; - auto &o = m_outputs[size_t(index)]; - if (o.colorControl) { - o.colorControl->set_brightness(wl_fixed_from_double(v.toDouble())); - o.colorControl->commit(); - wl_display_flush(m_display); + [this, regName](const QVariant &v) { + auto &outs = m_outputs; + for (int i = 0; i < int(outs.size()); ++i) { + if (outs[i].registryName == regName) { + if (outs[i].colorControl) { + outs[i].colorControl->set_brightness(wl_fixed_from_double(v.toDouble())); + outs[i].colorControl->commit(); + wl_display_flush(m_display); + } + return; + } } }); - m_brightnessAnims[index] = anim; + m_brightnessAnims[regName] = anim; anim->start(); } diff --git a/src/plugin-qt/power/session/screen/screencontroller_wl.h b/src/plugin-qt/power/session/screen/screencontroller_wl.h index 9cef395..3f6b884 100644 --- a/src/plugin-qt/power/session/screen/screencontroller_wl.h +++ b/src/plugin-qt/power/session/screen/screencontroller_wl.h @@ -101,10 +101,11 @@ class WaylandScreenController : public ScreenController void setBrightness(int index, double value) override; wl_display *m_display = nullptr; + wl_registry *m_registry = nullptr; std::unique_ptr m_manager; std::unique_ptr m_treeLandMgr; std::vector m_outputs; - QHash m_brightnessAnims; + QHash m_brightnessAnims; bool m_brightnessAvailable = false; private: