Watch
1
0
Fork
You've already forked souveraine
0
souveraine/surfaces/quickshell/services/Idle.qml
Fimeg 72b01457d2 quickshell: restore ii-stock config keys the fork dropped
Config.qml regained sidebar.width/widthExtended (their absence collapsed
the right sidebar PanelWindow to 1px — 'unclickable' on the laptop), plus
lock.dpmsTimeout, lock.unlockHook, and autoIdleInhibit with its Idle.qml
property. Audio.qml's absent capture source is now a zero-volume stub so
stock consumers stop dereferencing null, and the pactl status parse runs
under LC_ALL=C. volumeMixer dialog content comes along for the sidebar.
Findings logged in SouveraineOS/docs/DUMP-power-idle-lock-2026-07-15.md.
2026-07-16 08:06:11 -04:00

95 lines
3.3 KiB
QML

pragma Singleton
import qs.modules.common
import QtQuick
import Quickshell
import Quickshell.Io
import Quickshell.Wayland
/**
* A nice wrapper for date and time strings.
*/
Singleton {
id: root
property alias inhibit: idleInhibitor.enabled
inhibit: false
// ii-stock consumers (IdleInhibitorToggle.qml) read Idle.autoIdleInhibit to
// label the "Keep awake" toggle. Souveraine's idle path routes through
// hypridle, not a Wayland idle-inhibitor, so there's no separate "auto"
// mode — but the stock toggle expects the property to exist. Expose it as
// a plain bool so the toggle binds cleanly instead of throwing
// [undefined] -> bool at startup.
property bool autoIdleInhibit: false
// Pixel 3: the Wayland idle-inhibitor on an invisible 0x0 surface is
// not honored by our compositor build, and screen-off is driven by
// hypridle scripts anyway — so Keep System Awake stops/starts hypridle.
onInhibitChanged: {
// Keep System Awake toggles the systemd-managed hypridle unit.
// (Was pkill/setsid, which orphaned hypridle across Hyprland restarts
// and wedged wake — see hyprland.lua hyprland.start.)
//
// Runs through a Process, not execDetached, because this is the
// mechanism that decides whether the phone sleeps: if the unit fails
// to come back we need to know, not discover it via a flat battery.
// reset-failed is expected to be a no-op when the unit is healthy, so
// its failure is not interesting — but the restart's is, so the two
// are separated rather than hidden behind one silencing redirect.
hypridleProc.action = root.inhibit ? "stop" : "restart";
hypridleProc.command = ["sh", "-c", root.inhibit
? "systemctl --user stop hypridle.service"
: "systemctl --user reset-failed hypridle.service || true; systemctl --user restart hypridle.service"];
hypridleProc.running = true;
}
Process {
id: hypridleProc
property string action: ""
onExited: (exitCode, exitStatus) => {
if (exitCode !== 0)
console.log(`[idle] hypridle ${hypridleProc.action} failed (exit ${exitCode}); `
+ `idle handling may be wedged inhibit=${root.inhibit}`);
}
}
Connections {
target: Persistent
function onReadyChanged() {
if (!Persistent.isNewHyprlandInstance) {
root.inhibit = Persistent.states.idle.inhibit;
} else {
Persistent.states.idle.inhibit = root.inhibit;
}
}
}
function toggleInhibit(active = null) {
if (active !== null) {
root.inhibit = active;
} else {
root.inhibit = !root.inhibit;
}
Persistent.states.idle.inhibit = root.inhibit;
}
IdleInhibitor {
id: idleInhibitor
window: PanelWindow {
// Inhibitor requires a "visible" surface
// Actually not lol
implicitWidth: 0
implicitHeight: 0
color: "transparent"
// Just in case...
anchors {
right: true
bottom: true
}
// Make it not interactable
mask: Region {
item: null
}
}
}
}