1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2026-01-24 13:32:50 -05:00

feat: power off monitors when lock screen activates (#1402)

Add ability to immediately power off monitors when the lock screen
activates, controlled by a new setting "Power off monitors on lock".
Uses a 100ms polling timer to detect when the session lock actually
becomes active, then invokes compositor-specific DPMS commands.

For niri, uses the new power-off-monitors action via niri msg CLI
with socket fallback.

Wake on input: first input after lock arms wake, second input
actually powers monitors back on while keeping the lock screen visible.

Closes #1157
This commit is contained in:
Kamil Chmielewski
2026-01-18 19:08:58 +01:00
committed by GitHub
parent 13dededcc9
commit a685d9da52
4 changed files with 109 additions and 7 deletions

View File

@@ -394,6 +394,7 @@ Singleton {
property bool lockScreenShowDate: true
property bool lockScreenShowProfileImage: true
property bool lockScreenShowPasswordField: true
property bool lockScreenPowerOffMonitorsOnLock: false
property bool enableFprint: false
property int maxFprintTries: 15

View File

@@ -259,6 +259,7 @@ var SPEC = {
lockScreenShowDate: { def: true },
lockScreenShowProfileImage: { def: true },
lockScreenShowPasswordField: { def: true },
lockScreenPowerOffMonitorsOnLock: { def: false },
enableFprint: { def: false },
maxFprintTries: { def: 15 },
fprintdAvailable: { def: false, persist: false },

View File

@@ -12,8 +12,34 @@ Scope {
property string sharedPasswordBuffer: ""
property bool shouldLock: false
onShouldLockChanged: {
if (shouldLock && lockPowerOffArmed) {
lockStateCheck.restart();
}
}
Timer {
id: lockStateCheck
interval: 100
repeat: false
onTriggered: {
if (sessionLock.locked && lockPowerOffArmed) {
pendingLock = false;
IdleService.monitorsOff = true;
CompositorService.powerOffMonitors();
lockWakeAllowed = false;
lockWakeDebounce.restart();
lockPowerOffArmed = false;
dpmsReapplyTimer.start();
}
}
}
property bool lockInitiatedLocally: false
property bool pendingLock: false
property bool lockPowerOffArmed: false
property bool lockWakeAllowed: false
Component.onCompleted: {
IdleService.lockComponent = this;
@@ -37,6 +63,7 @@ Scope {
return;
lockInitiatedLocally = true;
lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock;
if (!SessionService.active && SessionService.loginctlAvailable) {
pendingLock = true;
@@ -78,6 +105,7 @@ Scope {
return;
}
lockInitiatedLocally = false;
lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock;
shouldLock = true;
}
@@ -96,11 +124,13 @@ Scope {
if (SessionService.active && pendingLock) {
pendingLock = false;
lockInitiatedLocally = true;
lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock;
shouldLock = true;
return;
}
if (SessionService.locked && !shouldLock && !pendingLock) {
lockInitiatedLocally = false;
lockPowerOffArmed = SettingsData.lockScreenPowerOffMonitorsOnLock;
shouldLock = true;
}
}
@@ -119,13 +149,6 @@ Scope {
locked: shouldLock
onLockedChanged: {
if (locked) {
pendingLock = false;
dpmsReapplyTimer.start();
}
}
WlSessionLockSurface {
id: lockSurface
@@ -155,7 +178,33 @@ Scope {
}
}
Connections {
target: sessionLock
function onLockedChanged() {
if (sessionLock.locked) {
pendingLock = false;
if (lockPowerOffArmed && SettingsData.lockScreenPowerOffMonitorsOnLock) {
IdleService.monitorsOff = true;
CompositorService.powerOffMonitors();
lockWakeAllowed = false;
lockWakeDebounce.restart();
}
lockPowerOffArmed = false;
dpmsReapplyTimer.start();
return;
}
lockWakeAllowed = false;
if (IdleService.monitorsOff && SettingsData.lockScreenPowerOffMonitorsOnLock) {
IdleService.monitorsOff = false;
CompositorService.powerOnMonitors();
}
}
}
LockScreenDemo {
id: demoWindow
}
@@ -200,4 +249,46 @@ Scope {
repeat: false
onTriggered: IdleService.reapplyDpmsIfNeeded()
}
Timer {
id: lockWakeDebounce
interval: 200
repeat: false
onTriggered: {
if (!sessionLock.locked)
return;
if (!SettingsData.lockScreenPowerOffMonitorsOnLock)
return;
if (!IdleService.monitorsOff) {
lockWakeAllowed = true;
return;
}
if (lockWakeAllowed) {
IdleService.monitorsOff = false;
CompositorService.powerOnMonitors();
} else {
lockWakeAllowed = true;
}
}
}
MouseArea {
anchors.fill: parent
enabled: sessionLock.locked
hoverEnabled: enabled
onPressed: lockWakeDebounce.restart()
onPositionChanged: lockWakeDebounce.restart()
onWheel: lockWakeDebounce.restart()
}
FocusScope {
anchors.fill: parent
focus: sessionLock.locked
Keys.onPressed: event => {
if (!sessionLock.locked)
return;
lockWakeDebounce.restart();
}
}
}

View File

@@ -131,6 +131,15 @@ Item {
onToggled: checked => SettingsData.set("lockBeforeSuspend", checked)
}
SettingsToggleRow {
settingKey: "lockScreenPowerOffMonitorsOnLock"
tags: ["lock", "screen", "monitor", "display", "dpms", "power"]
text: I18n.tr("Power off monitors on lock")
description: I18n.tr("Turn off all displays immediately when the lock screen activates")
checked: SettingsData.lockScreenPowerOffMonitorsOnLock
onToggled: checked => SettingsData.set("lockScreenPowerOffMonitorsOnLock", checked)
}
SettingsToggleRow {
settingKey: "enableFprint"
tags: ["lock", "screen", "fingerprint", "authentication", "biometric", "fprint"]