mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-11 07:52:50 -05:00
Implement IdleMonitor to replace swayidle/hypridle functionality
This commit is contained in:
@@ -162,6 +162,26 @@ Singleton {
|
||||
}
|
||||
}
|
||||
|
||||
function powerOffMonitors() {
|
||||
if (isNiri) {
|
||||
return NiriService.powerOffMonitors()
|
||||
}
|
||||
if (isHyprland) {
|
||||
return Hyprland.dispatch("dpms off")
|
||||
}
|
||||
console.warn("CompositorService: Cannot power off monitors, unknown compositor")
|
||||
}
|
||||
|
||||
function powerOnMonitors() {
|
||||
if (isNiri) {
|
||||
return NiriService.powerOnMonitors()
|
||||
}
|
||||
if (isHyprland) {
|
||||
return Hyprland.dispatch("dpms on")
|
||||
}
|
||||
console.warn("CompositorService: Cannot power on monitors, unknown compositor")
|
||||
}
|
||||
|
||||
Process {
|
||||
id: niriSocketCheck
|
||||
command: ["test", "-S", root.niriSocket]
|
||||
|
||||
211
Services/IdleService.qml
Normal file
211
Services/IdleService.qml
Normal file
@@ -0,0 +1,211 @@
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -438,6 +438,22 @@ Singleton {
|
||||
})
|
||||
}
|
||||
|
||||
function powerOffMonitors() {
|
||||
return send({
|
||||
"Action": {
|
||||
"PowerOffMonitors": {}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function powerOnMonitors() {
|
||||
return send({
|
||||
"Action": {
|
||||
"PowerOnMonitors": {}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function getCurrentOutputWorkspaceNumbers() {
|
||||
return currentOutputWorkspaces.map(w => w.idx + 1)
|
||||
}
|
||||
|
||||
@@ -85,6 +85,10 @@ Singleton {
|
||||
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "suspend"])
|
||||
}
|
||||
|
||||
function hibernate() {
|
||||
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "hibernate"])
|
||||
}
|
||||
|
||||
function reboot() {
|
||||
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "reboot"])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user