extract logind integration into LockService singleton in services/

This commit is contained in:
Damocles 2026-04-18 10:06:22 +02:00
parent 5248261975
commit a1c581e443
3 changed files with 101 additions and 59 deletions

View file

@ -1,15 +1,11 @@
import QtQuick import QtQuick
import Quickshell import Quickshell
import Quickshell.Io
import Quickshell.Wayland import Quickshell.Wayland
import "../services" as S import "../services" as S
Scope { Scope {
id: root id: root
readonly property bool _enabled: S.Modules.lock.enable
property string _sessionPath: ""
WlSessionLock { WlSessionLock {
id: _lock id: _lock
@ -24,73 +20,30 @@ Scope {
lock: _lock lock: _lock
} }
// Resolve the actual logind session object path at startup Connections {
Process { target: S.LockService
id: _sessionResolver
command: ["busctl", "call", "--system", "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "GetSession", "s", "auto"]
running: root._enabled
stdout: SplitParser { function onLockRequested() {
onRead: data => { if (S.LockService.enabled)
// Output: o "/org/freedesktop/login1/session/_32" _lock.locked = true;
const match = data.match(/"([^"]+)"/);
if (match)
root._sessionPath = match[1];
}
} }
onExited: { function onUnlockRequested() {
if (root._sessionPath) { if (_lock.locked)
_logindMonitor.running = true; _lock.locked = false;
_lockStateCheck.running = true;
}
} }
}
// Listen for logind Lock/Unlock signals via gdbus monitor. function onSessionLocked() {
// TODO: replace with native D-Bus integration when nova-stats becomes a quickshell plugin if (S.LockService.enabled && !_lock.locked)
Process { _lock.locked = true;
id: _logindMonitor
command: ["gdbus", "monitor", "--system", "--dest", "org.freedesktop.login1", "--object-path", root._sessionPath]
running: false
stdout: SplitParser {
onRead: data => {
if (data.indexOf(".Lock ()") !== -1 && root._enabled)
_lock.locked = true;
else if (data.indexOf(".Unlock ()") !== -1 && _lock.locked)
_lock.locked = false;
}
} }
} }
// Check if session is already locked on startup (crash recovery)
Process {
id: _lockStateCheck
running: false
command: ["busctl", "get-property", "--system", "org.freedesktop.login1", root._sessionPath, "org.freedesktop.login1.Session", "LockedHint"]
stdout: SplitParser {
onRead: data => {
// Output: b true/false
if (data.indexOf("true") !== -1 && root._enabled && !_lock.locked)
_lock.locked = true;
}
}
}
// Set logind LockedHint when lock state changes
Process {
id: _lockedHint
command: ["busctl", "call", "--system", "org.freedesktop.login1", root._sessionPath || "/org/freedesktop/login1/session/auto", "org.freedesktop.login1.Session", "SetLockedHint", "b", _lock.locked ? "true" : "false"]
}
Connections { Connections {
target: _lock target: _lock
function onLockStateChanged() { function onLockStateChanged() {
if (root._sessionPath) S.LockService.setLockedHint(_lock.locked);
_lockedHint.running = true;
} }
} }
} }

View file

@ -0,0 +1,88 @@
pragma Singleton
import QtQuick
import Quickshell.Io
import "." as S
QtObject {
id: root
readonly property bool enabled: S.Modules.lock.enable
property string sessionPath: ""
// Lock/unlock requests from logind
signal lockRequested
signal unlockRequested
// Set logind LockedHint
function setLockedHint(locked) {
if (!sessionPath)
return;
_lockedHint._locked = locked;
_lockedHint.running = true;
}
// Check if session is currently locked (crash recovery)
function checkLockState() {
if (sessionPath)
_lockStateCheck.running = true;
}
signal sessionLocked // fired if LockedHint is true on startup
// Resolve the actual logind session object path at startup
property Process _sessionResolver: Process {
command: ["busctl", "call", "--system", "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", "GetSession", "s", "auto"]
running: root.enabled
stdout: SplitParser {
onRead: data => {
const match = data.match(/"([^"]+)"/);
if (match)
root.sessionPath = match[1];
}
}
onExited: {
if (root.sessionPath) {
_logindMonitor.running = true;
root.checkLockState();
}
}
}
// Listen for logind Lock/Unlock signals via gdbus monitor.
// TODO: replace with native D-Bus integration when nova-stats becomes a quickshell plugin
property Process _logindMonitor: Process {
command: ["gdbus", "monitor", "--system", "--dest", "org.freedesktop.login1", "--object-path", root.sessionPath]
running: false
stdout: SplitParser {
onRead: data => {
if (data.indexOf(".Lock ()") !== -1)
root.lockRequested();
else if (data.indexOf(".Unlock ()") !== -1)
root.unlockRequested();
}
}
}
// Check if session is already locked on startup (crash recovery)
property Process _lockStateCheck: Process {
running: false
command: ["busctl", "get-property", "--system", "org.freedesktop.login1", root.sessionPath, "org.freedesktop.login1.Session", "LockedHint"]
stdout: SplitParser {
onRead: data => {
if (data.indexOf("true") !== -1)
root.sessionLocked();
}
}
}
// Set logind LockedHint
property Process _lockedHint: Process {
property bool _locked: false
command: ["busctl", "call", "--system", "org.freedesktop.login1", root.sessionPath || "/org/freedesktop/login1/session/auto", "org.freedesktop.login1.Session", "SetLockedHint", "b", _locked ? "true" : "false"]
}
}

View file

@ -6,3 +6,4 @@ singleton NiriIpc 1.0 NiriIpc.qml
singleton PowerProfileService 1.0 PowerProfileService.qml singleton PowerProfileService 1.0 PowerProfileService.qml
singleton NotifService 1.0 NotifService.qml singleton NotifService 1.0 NotifService.qml
NotifItem 1.0 NotifItem.qml NotifItem 1.0 NotifItem.qml
singleton LockService 1.0 LockService.qml