From 71e35b1ea9a2d0abd48efa661eff759c2cc20324 Mon Sep 17 00:00:00 2001 From: zhangkun Date: Tue, 8 Sep 2026 22:16:44 +0800 Subject: [PATCH] fix(power): unify screen-off handling in session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. Move the X11 lock-before-DPMS screen-off sequence out of dde-shortcut-tool and into the power session service's TurnOffScreen. 2. Turn the screen back on when the power button is pressed while the screen is already off, and skip the request when no screen controller is available. 3. Delegate dde-shortcut-tool's turn-off-screen action to Power1.TurnOffScreen instead of duplicating the sequence. Log: Screen-off logic now lives in the power session service and the shortcut tool only calls Power1.TurnOffScreen. Influence: Power-key screen-off and wake behave consistently. fix(power): 统一屏幕关闭处理到会话服务 1. 将 dde-shortcut-tool 中「先锁屏再 DPMS 关屏」的 X11 处理移入电源会话服务的 TurnOffScreen。 2. 屏幕已关闭时再次按电源键改为重新点亮;屏幕控制器不可用时忽略请求。 3. dde-shortcut-tool 的关屏动作改为调用 Power1.TurnOffScreen,不再重复实现。 Log: 关屏逻辑收敛到电源会话服务,快捷工具只调用 Power1.TurnOffScreen。 PMS: BUG-375787 Influence: 电源键关屏与唤醒行为保持一致。 Change-Id: Ib0f330915ba419603aabb9039bd1fd8e393470c4 --- src/plugin-qt/power/session/powermanager.cpp | 25 ++++- .../dde-shortcut-tool/powercontroller.cpp | 103 ++---------------- .../tools/dde-shortcut-tool/powercontroller.h | 14 +-- 3 files changed, 33 insertions(+), 109 deletions(-) diff --git a/src/plugin-qt/power/session/powermanager.cpp b/src/plugin-qt/power/session/powermanager.cpp index 3a394385..ee81e8a9 100644 --- a/src/plugin-qt/power/session/powermanager.cpp +++ b/src/plugin-qt/power/session/powermanager.cpp @@ -614,7 +614,30 @@ void PowerManager::SetPrepareSuspend(int state) void PowerManager::TurnOffScreen() { - doTurnOffScreen(); + if (!m_screenCtrl || !m_screenCtrl->isValid()) { + qWarning(logPowerSession) << "Ignoring screen-off request: screen controller unavailable"; + return; + } + // The power button toggles the screen: while the screen is off a press + // wakes it instead of blanking it again. + if (m_screenCtrl->isAllOff()) { + qInfo(logPowerSession) << "Screen is off, turning it back on"; + TurnOnScreen(); + return; + } + + if (m_useWayland) { + doTurnOffScreen(); + return; + } + + if (m_screenBlackLock) + doLock(true); + SetPrepareSuspend(PS_ButtonClick); + + setDPMSModeOff(); + + SetPrepareSuspend(PS_Finish); } void PowerManager::TurnOnScreen() diff --git a/src/plugin-qt/shortcut/tools/dde-shortcut-tool/powercontroller.cpp b/src/plugin-qt/shortcut/tools/dde-shortcut-tool/powercontroller.cpp index 3ecce7df..b465409b 100644 --- a/src/plugin-qt/shortcut/tools/dde-shortcut-tool/powercontroller.cpp +++ b/src/plugin-qt/shortcut/tools/dde-shortcut-tool/powercontroller.cpp @@ -23,16 +23,6 @@ DCORE_USE_NAMESPACE DGUI_USE_NAMESPACE -// Power1 SetPrepareSuspend states (match dde-daemon keybinding1/utils.go). -static constexpr int kSuspendStateFinish = 3; -static constexpr int kSuspendStateButtonClick = 7; - -// Delay between switching on the KWin BlackScreen mask and triggering DPMS off. -// bug-209669: on some vendor machines DPMS-off blocks the lock screen Show -// until DPMS is back on, causing a wake-flash-then-lock visual glitch. The -// mask hides the gap; 100ms is enough for the compositor to draw it. -static constexpr int kBlackScreenMaskDelayMs = 100; - namespace { bool isWaylandSession() @@ -160,13 +150,6 @@ int PowerController::getPowerButtonAction(DConfig *config, bool onBattery) return config->value(key, PowerActionShowUI).toInt(); } -bool PowerController::shouldLockOnScreenBlack(DConfig *config) -{ - if (!config) - return true; - return config->value(Config::KEY_SCREEN_BLACK_LOCK, true).toBool(); -} - bool PowerController::shouldLockOnSleep(DConfig *config) { if (!config) @@ -260,45 +243,6 @@ bool PowerController::hasMultipleDisplaySession() return userSessions >= 2; } -void PowerController::doPrepareSuspend() -{ - QDBusInterface power("org.deepin.dde.Power1", "/org/deepin/dde/Power1", "org.deepin.dde.Power1", - QDBusConnection::sessionBus()); - if (!power.isValid()) - return; - power.call("SetPrepareSuspend", kSuspendStateButtonClick); -} - -void PowerController::undoPrepareSuspend() -{ - QDBusInterface power("org.deepin.dde.Power1", "/org/deepin/dde/Power1", "org.deepin.dde.Power1", - QDBusConnection::sessionBus()); - if (!power.isValid()) - return; - power.call("SetPrepareSuspend", kSuspendStateFinish); -} - -bool PowerController::isWmBlackScreenActive() -{ - QDBusInterface kwin("org.kde.KWin", "/BlackScreen", "org.kde.kwin.BlackScreen", - QDBusConnection::sessionBus()); - if (!kwin.isValid()) - return false; - QDBusReply reply = kwin.call("getActive"); - return reply.isValid() && reply.value(); -} - -void PowerController::setWmBlackScreenActive(bool active) -{ - QDBusInterface kwin("org.kde.KWin", "/BlackScreen", "org.kde.kwin.BlackScreen", - QDBusConnection::sessionBus()); - if (!kwin.isValid()) { - qWarning() << "PowerController: KWin BlackScreen not available"; - return; - } - kwin.call("setActive", active); -} - void PowerController::doLock(bool autoStartAuth) { qInfo() << "PowerController: lock screen (autoStartAuth=" << autoStartAuth << ")"; @@ -427,47 +371,16 @@ void PowerController::systemHibernate() void PowerController::systemTurnOffScreen() { - qInfo() << "PowerController: turn off screen"; - - if (isWaylandSession()) { - QDBusInterface power("org.deepin.dde.Power1", "/org/deepin/dde/Power1", - "org.deepin.dde.Power1", QDBusConnection::sessionBus()); - if (power.isValid()) { - power.call("TurnOffScreen"); - } else { - qWarning() << "PowerController: Power1 unavailable for TurnOffScreen"; - } + qInfo() << "PowerController: turn off screen via Power1"; + QDBusInterface power("org.deepin.dde.Power1", "/org/deepin/dde/Power1", + "org.deepin.dde.Power1", QDBusConnection::sessionBus()); + if (!power.isValid()) { + qWarning() << "PowerController: Power1 unavailable for TurnOffScreen"; return; } - - DConfig *config = createPowerConfig(this); - const bool screenBlackLock = shouldLockOnScreenBlack(config); - - // Order matters (bug-209669): - // 1) lock the screen BEFORE DPMS off, otherwise the lock UI's Show - // call blocks until DPMS comes back on, causing a wake-flash - // 2) tell power daemon we're putting the screen down so it stops - // racing us - // 3) cover the gap between "DPMS still on" and "lock UI drawn" with - // the KWin BlackScreen mask - if (screenBlackLock) - doLock(true); - - doPrepareSuspend(); - - const bool needMask = screenBlackLock && !isWmBlackScreenActive(); - if (needMask) { - setWmBlackScreenActive(true); - QThread::msleep(kBlackScreenMaskDelayMs); - } - - QProcess::execute("xset", {"dpms", "force", "off"}); - - if (needMask) - setWmBlackScreenActive(false); - - undoPrepareSuspend(); - + const QDBusReply reply = power.call("TurnOffScreen"); + if (!reply.isValid()) + qWarning() << "PowerController: TurnOffScreen failed:" << reply.error().message(); } void PowerController::showShutdownUI() diff --git a/src/plugin-qt/shortcut/tools/dde-shortcut-tool/powercontroller.h b/src/plugin-qt/shortcut/tools/dde-shortcut-tool/powercontroller.h index ccaf80e6..871585d8 100644 --- a/src/plugin-qt/shortcut/tools/dde-shortcut-tool/powercontroller.h +++ b/src/plugin-qt/shortcut/tools/dde-shortcut-tool/powercontroller.h @@ -20,9 +20,7 @@ class DConfig; * * Invoked as `/usr/bin/dde-shortcut-tool power ` from the keybinding * shortcut for the physical power key (keycode 116) and other power-related - * shortcuts. Ports the dde-daemon keybinding1 power-button logic, including - * the bug-209669 turn-off-screen sequence and the X11 anti-flicker path - * through ShutdownFront1. + * shortcuts. Power transitions are delegated to the owning session services. */ class PowerController : public BaseController { @@ -48,7 +46,6 @@ class PowerController : public BaseController private: bool isOnBattery(); int getPowerButtonAction(Dtk::Core::DConfig *config, bool onBattery); - bool shouldLockOnScreenBlack(Dtk::Core::DConfig *config); bool shouldLockOnSleep(Dtk::Core::DConfig *config); bool callSessionBool(const char *method); @@ -59,15 +56,6 @@ class PowerController : public BaseController bool hasShutdownInhibit(); bool hasMultipleDisplaySession(); - // Power1 (session bus) PrepareSuspend notification, keeps the power - // daemon from racing the screen-off transition. - void doPrepareSuspend(); - void undoPrepareSuspend(); - - // KWin BlackScreen effect (Treeland/X11 visual mask, separate from DPMS). - bool isWmBlackScreenActive(); - void setWmBlackScreenActive(bool active); - void systemShutdown(); void systemSuspend(); void systemHibernate();