1
0
mirror of https://github.com/AvengeMedia/DankMaterialShell.git synced 2025-12-05 21:15:38 -05:00
Files
DankMaterialShell/Services/SessionService.qml
2025-09-21 22:06:12 -04:00

224 lines
5.4 KiB
QML

pragma Singleton
pragma ComponentBehavior: Bound
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Hyprland
import qs.Common
Singleton {
id: root
property bool hasUwsm: false
property bool isElogind: false
property bool hibernateSupported: false
property bool inhibitorAvailable: true
property bool idleInhibited: false
property string inhibitReason: "Keep system awake"
Component.onCompleted: {
detectElogindProcess.running = true
detectHibernateProcess.running = true
}
Process {
id: detectUwsmProcess
running: false
command: ["which", "uwsm"]
onExited: function (exitCode) {
hasUwsm = (exitCode === 0)
}
}
Process {
id: detectElogindProcess
running: false
command: ["sh", "-c", "ps -eo comm= | grep -E '^(elogind|elogind-daemon)$'"]
onExited: function (exitCode) {
console.log("SessionService: Elogind detection exited with code", exitCode)
isElogind = (exitCode === 0)
}
}
Process {
id: detectHibernateProcess
running: false
command: ["grep", "-q", "disk", "/sys/power/state"]
onExited: function (exitCode) {
hibernateSupported = (exitCode === 0)
}
}
Process {
id: uwsmLogout
command: ["uwsm", "stop"]
running: false
stdout: SplitParser {
splitMarker: "\n"
onRead: data => {
if (data.trim().toLowerCase().includes("not running")) {
_logout()
}
}
}
onExited: function (exitCode) {
if (exitCode === 0) {
return
}
_logout()
}
}
// * Apps
function launchDesktopEntry(desktopEntry) {
let cmd = desktopEntry.command
if (SessionData.launchPrefix && SessionData.launchPrefix.length > 0) {
const launchPrefix = SessionData.launchPrefix.trim().split(" ")
cmd = launchPrefix.concat(cmd)
}
Quickshell.execDetached({
command: cmd,
workingDirectory: desktopEntry.workingDirectory,
});
}
// * Session management
function logout() {
if (hasUwsm) {
uwsmLogout.running = true
}
_logout()
}
function _logout() {
if (CompositorService.isNiri) {
NiriService.quit()
return
}
// Hyprland fallback
Hyprland.dispatch("exit")
}
function suspend() {
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "suspend"])
}
function hibernate() {
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "hibernate"])
}
function reboot() {
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "reboot"])
}
function poweroff() {
Quickshell.execDetached([isElogind ? "loginctl" : "systemctl", "poweroff"])
}
// * Idle Inhibitor
signal inhibitorChanged
function enableIdleInhibit() {
if (idleInhibited) {
return
}
idleInhibited = true
inhibitorChanged()
}
function disableIdleInhibit() {
if (!idleInhibited) {
return
}
idleInhibited = false
inhibitorChanged()
}
function toggleIdleInhibit() {
if (idleInhibited) {
disableIdleInhibit()
} else {
enableIdleInhibit()
}
}
function setInhibitReason(reason) {
inhibitReason = reason
if (idleInhibited) {
const wasActive = idleInhibited
idleInhibited = false
Qt.callLater(() => {
if (wasActive) {
idleInhibited = true
}
})
}
}
Process {
id: idleInhibitProcess
command: {
if (!idleInhibited) {
return ["true"]
}
return [isElogind ? "elogind-inhibit" : "systemd-inhibit", "--what=idle", "--who=quickshell", `--why=${inhibitReason}`, "--mode=block", "sleep", "infinity"]
}
running: idleInhibited
onExited: function (exitCode) {
if (idleInhibited && exitCode !== 0) {
console.warn("SessionService: Inhibitor process crashed with exit code:", exitCode)
idleInhibited = false
ToastService.showWarning("Idle inhibitor failed")
}
}
}
IpcHandler {
function toggle(): string {
root.toggleIdleInhibit()
return root.idleInhibited ? "Idle inhibit enabled" : "Idle inhibit disabled"
}
function enable(): string {
root.enableIdleInhibit()
return "Idle inhibit enabled"
}
function disable(): string {
root.disableIdleInhibit()
return "Idle inhibit disabled"
}
function status(): string {
return root.idleInhibited ? "Idle inhibit is enabled" : "Idle inhibit is disabled"
}
function reason(newReason: string): string {
if (!newReason) {
return `Current reason: ${root.inhibitReason}`
}
root.setInhibitReason(newReason)
return `Inhibit reason set to: ${newReason}`
}
target: "inhibit"
}
}