1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-08 06:25:37 -05:00
Files
DankMaterialShell/Services/IdleService.qml

211 lines
6.2 KiB
QML

pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Wayland
import qs.Common
import qs.Services
Singleton {
id: root
readonly property bool idleMonitorAvailable: {
try {
return typeof IdleMonitor !== "undefined"
} catch (e) {
return false
}
}
property bool enabled: true
property bool respectInhibitors: true
property bool _enableGate: true
readonly property bool isOnBattery: BatteryService.batteryAvailable && !BatteryService.isPluggedIn
readonly property int monitorTimeout: isOnBattery ? SessionData.batteryMonitorTimeout : SessionData.acMonitorTimeout
readonly property int lockTimeout: isOnBattery ? SessionData.batteryLockTimeout : SessionData.acLockTimeout
readonly property int suspendTimeout: isOnBattery ? SessionData.batterySuspendTimeout : SessionData.acSuspendTimeout
readonly property int hibernateTimeout: isOnBattery ? SessionData.batteryHibernateTimeout : SessionData.acHibernateTimeout
readonly property int firstTimeout: {
const timeouts = []
if (monitorTimeout > 0) timeouts.push(monitorTimeout)
if (lockTimeout > 0) timeouts.push(lockTimeout)
if (suspendTimeout > 0) timeouts.push(suspendTimeout)
if (hibernateTimeout > 0) timeouts.push(hibernateTimeout)
return timeouts.length > 0 ? Math.min(...timeouts) : 0
}
property int currentStepIndex: -1
property var steps: []
signal lockRequested()
signal requestMonitorOff()
signal requestMonitorOn()
signal requestSuspend()
signal requestHibernate()
signal stageFired(string name)
onFirstTimeoutChanged: {
if (idleMonitor) _rearmIdleMonitor()
}
function _rearmIdleMonitor() {
cancel()
_enableGate = false
Qt.callLater(() => { _enableGate = true })
}
function makeSteps() {
const steps = []
if (lockTimeout > 0) {
steps.push({name: "lock", delaySec: lockTimeout})
}
if (monitorTimeout > 0) {
steps.push({name: "monitor-off", delaySec: monitorTimeout})
}
if (suspendTimeout > 0) {
steps.push({name: "suspend", delaySec: suspendTimeout})
}
if (hibernateTimeout > 0) {
steps.push({name: "hibernate", delaySec: hibernateTimeout})
}
return steps.sort((a, b) => a.delaySec - b.delaySec)
}
function start() {
if (!enabled || !idleMonitorAvailable) return
if (currentStepIndex !== -1) return
steps = makeSteps()
currentStepIndex = -1
next()
}
function next() {
if (++currentStepIndex >= steps.length) return
const currentStep = steps[currentStepIndex]
const firstStepDelay = steps[0].delaySec
const relativeDelay = currentStep.delaySec - firstStepDelay
const ms = (relativeDelay * 1000) | 0
if (ms > 0) {
stepTimer.interval = ms
stepTimer.restart()
} else {
Qt.callLater(run)
}
}
function run() {
const currentStep = steps[currentStepIndex]
if (!currentStep) return
console.log("IdleService: Executing step:", currentStep.name)
if (currentStep.name === "lock") {
lockRequested()
} else if (currentStep.name === "monitor-off") {
requestMonitorOff()
} else if (currentStep.name === "suspend") {
requestSuspend()
} else if (currentStep.name === "hibernate") {
requestHibernate()
}
stageFired(currentStep.name)
next()
}
function cancel() {
stepTimer.stop()
currentStepIndex = -1
}
function wake() {
cancel()
requestMonitorOn()
}
Timer {
id: stepTimer
repeat: false
onTriggered: root.run()
}
property var idleMonitor: null
function createIdleMonitor() {
if (!idleMonitorAvailable) {
console.log("IdleService: IdleMonitor not available, skipping creation")
return
}
try {
const qmlString = `
import QtQuick
import Quickshell.Wayland
IdleMonitor {
enabled: false
respectInhibitors: true
timeout: 0
}
`
idleMonitor = Qt.createQmlObject(qmlString, root, "IdleService.IdleMonitor")
if (idleMonitor) {
idleMonitor.enabled = Qt.binding(
() => root._enableGate && root.enabled && root.idleMonitorAvailable && root.firstTimeout > 0
)
idleMonitor.respectInhibitors = Qt.binding(() => root.respectInhibitors)
idleMonitor.timeout = Qt.binding(() => root.firstTimeout)
idleMonitor.isIdleChanged.connect(function() {
if (idleMonitor.isIdle) {
console.log("IdleService: User is idle, starting power management")
Qt.callLater(root.start)
} else {
console.log("IdleService: User is active, canceling power management")
Qt.callLater(root.cancel)
}
})
}
} catch (e) {
console.warn("IdleService: Error creating IdleMonitor:", e)
}
}
Connections {
target: root
function onRequestMonitorOff() {
CompositorService.powerOffMonitors()
}
function onRequestMonitorOn() {
CompositorService.powerOnMonitors()
}
function onRequestSuspend() {
SessionService.suspend()
}
function onRequestHibernate() {
SessionService.hibernate()
}
}
Component.onCompleted: {
if (!idleMonitorAvailable) {
console.warn("IdleService: IdleMonitor not available - power management disabled. This requires a newer version of Quickshell.")
} else {
console.log("IdleService: Initialized with idle monitoring support")
createIdleMonitor()
}
}
}