diff --git a/lid-guard/README.md b/lid-guard/README.md index 8abf966e..0387bcc8 100644 --- a/lid-guard/README.md +++ b/lid-guard/README.md @@ -13,9 +13,15 @@ system-wide lid policy. ## Requirements -Install `systemctl`, `systemd-run`, and `systemd-inhibit` from systemd, plus -`sleep` from coreutils, on `PATH`. The active user session must use -`systemd-logind` and have a working user service manager. +One of these backends must be available: + +- **Dinit:** `dinitctl`, `elogind-inhibit`, and `sleep`. The active user session + must have a working user Dinit manager and `elogind`. +- **systemd:** `systemctl`, `systemd-run`, `systemd-inhibit`, and `sleep`. The + active user session must use `systemd-logind` and have a working user service + manager. + +Dinit is preferred automatically when both backends are installed. ## Usage @@ -42,12 +48,26 @@ The `enable`, `disable`, and `toggle` events change the inhibitor state. `refresh` and `status` re-check the transient user service without changing it. IPC events take no payload. +## Dinit setup + +For Dinit, install the included service description into the user service + directory: + +```sh +mkdir -p "$XDG_CONFIG_HOME/dinit.d" +cp dinit/noctalia-lid-guard "$XDG_CONFIG_HOME/dinit.d/" +``` + +When installed from the Noctalia plugin store, copy the file from the plugin's +local directory. The service is not enabled at boot; the plugin starts and +stops it on demand. + ## Notes -Lid Guard makes no network requests and writes no files. It spawns -`systemctl`, `systemd-run`, `systemd-inhibit`, and `sleep` as the current user. -When enabled, it creates the transient user service -`noctalia-lid-guard.service`; disabling the mode stops that service. +Lid Guard makes no network requests. It starts the inhibitor as the current +user. With Dinit it controls the persistent user service +`noctalia-lid-guard`; with systemd it creates the transient user service +`noctalia-lid-guard.service`; disabling the mode stops the selected service. The inhibitor covers only `handle-lid-switch`. It does not prevent suspension requested by an idle daemon, a power menu, or another explicit command, and it @@ -56,5 +76,6 @@ service manager stops. If Noctalia is unavailable, restore the normal lid behavior with: ```sh -systemctl --user stop noctalia-lid-guard.service +dinitctl --user stop noctalia-lid-guard # Dinit +systemctl --user stop noctalia-lid-guard.service # systemd ``` diff --git a/lid-guard/dinit/noctalia-lid-guard b/lid-guard/dinit/noctalia-lid-guard new file mode 100644 index 00000000..5ffcb11f --- /dev/null +++ b/lid-guard/dinit/noctalia-lid-guard @@ -0,0 +1,4 @@ +# Dinit backend for Noctalia Lid Guard. +type = process +command = /usr/bin/elogind-inhibit --what=handle-lid-switch --who="Noctalia Lid Guard" --why="Keep background jobs running while the laptop lid is closed" --mode=block /usr/bin/sleep infinity +restart = false diff --git a/lid-guard/plugin.toml b/lid-guard/plugin.toml index d0542294..6884ca8a 100644 --- a/lid-guard/plugin.toml +++ b/lid-guard/plugin.toml @@ -1,13 +1,14 @@ id = "8bury/lid-guard" name = "Lid Guard" -version = "1.0.0" +version = "1.0.1" plugin_api = 3 author = "8bury" license = "MIT" icon = "shield-lock" description = "Keep the laptop awake when its lid is closed, so background jobs can continue running." tags = ["bar", "indicator", "productivity", "service", "shortcut", "system", "utility"] -dependencies = ["systemctl", "systemd-run", "systemd-inhibit", "sleep"] +# The plugin supports either Dinit + elogind or systemd + logind. +dependencies = [] [[service]] id = "lid-guard-service" diff --git a/lid-guard/service.luau b/lid-guard/service.luau index b0618bef..df9d86e5 100644 --- a/lid-guard/service.luau +++ b/lid-guard/service.luau @@ -1,10 +1,24 @@ --!nonstrict --- Owns the systemd inhibitor. Widgets and shortcuts communicate with this +-- Owns the lid inhibitor. Widgets and shortcuts communicate with this -- singleton through noctalia.state. -local UNIT = "noctalia-lid-guard.service" -local CHECK_COMMAND = `systemctl --user is-active --quiet {UNIT}` -local START_COMMAND = `systemctl --user reset-failed {UNIT} >/dev/null 2>&1 || true; ` .. table.concat({ +local SYSTEMD_UNIT = "noctalia-lid-guard.service" +local DINIT_UNIT = "noctalia-lid-guard" +local hasDinit = noctalia.commandExists("dinitctl") + and noctalia.commandExists("elogind-inhibit") + and noctalia.commandExists("sleep") +local hasSystemd = noctalia.commandExists("systemctl") + and noctalia.commandExists("systemd-run") + and noctalia.commandExists("systemd-inhibit") + and noctalia.commandExists("sleep") +local backend = if hasDinit then "dinit" elseif hasSystemd then "systemd" else "" +local UNIT = if backend == "dinit" then DINIT_UNIT else SYSTEMD_UNIT +local CHECK_COMMAND = if backend == "dinit" + then `dinitctl --user is-started {UNIT}` + else `systemctl --user is-active --quiet {UNIT}` +local START_COMMAND = if backend == "dinit" + then `dinitctl --user start {UNIT}` + else `systemctl --user reset-failed {UNIT} >/dev/null 2>&1 || true; ` .. table.concat({ `systemd-run --user --quiet --collect --unit={UNIT}`, `--description='Noctalia Lid Guard'`, `systemd-inhibit --what=handle-lid-switch`, @@ -12,14 +26,13 @@ local START_COMMAND = `systemctl --user reset-failed {UNIT} >/dev/null 2>&1 || t `--why='Keep background jobs running while the laptop lid is closed'`, `--mode=block sleep infinity`, }, " ") -local STOP_COMMAND = `systemctl --user stop {UNIT}` +local STOP_COMMAND = if backend == "dinit" + then `dinitctl --user stop {UNIT}` + else `systemctl --user stop {UNIT}` local active = false local busy = false -local available = noctalia.commandExists("systemctl") - and noctalia.commandExists("systemd-run") - and noctalia.commandExists("systemd-inhibit") - and noctalia.commandExists("sleep") +local available = backend ~= "" local revision = 0 local function publish(errorMessage) diff --git a/lid-guard/translations/en.json b/lid-guard/translations/en.json index 53ebde39..0b58a516 100644 --- a/lid-guard/translations/en.json +++ b/lid-guard/translations/en.json @@ -1,7 +1,7 @@ { "error": { "command_failed": "The systemd command failed.", - "missing_dependencies": "systemctl, systemd-run, systemd-inhibit, and sleep are required.", + "missing_dependencies": "Dinit with elogind, or systemd with logind, is required.", "state_mismatch": "The requested state could not be confirmed." }, "notification": { @@ -23,6 +23,6 @@ "active": "Lid Guard is on — closing the lid will not suspend the laptop", "changing": "Changing Lid Guard state…", "inactive": "Lid Guard is off — click to keep the laptop awake with the lid closed", - "unavailable": "Lid Guard requires systemd" + "unavailable": "Lid Guard requires Dinit + elogind or systemd" } }