Az xidlehook egy Rust nyelven írt, önálló démon, ami az xautolock szerepét váltja ki: figyeli a felhasználó tétlenségét, és egy megadott idő elteltével tetszőleges parancsot futtat le. Amíg egy DE-be épített energiakezelő (pl. az XFCE-é) a képernyővédő-inhibit D-Bus API-ra (org.freedesktop.ScreenSaver) hagyatkozik – vagyis abban bízik, hogy minden alkalmazás korrekten szól, ha nem szabad aludni mennie a gépnek –, addig az xidlehook ezt megkerüli: a fullscreen-állapotot közvetlenül az X szerver ablaklistájából, a hanglejátszást pedig közvetlenül a PulseAudio-tól kérdezi le. Ez a különbség teszi megbízhatóvá olyan környezetben is, mint egy csupasz dwm/chadwm, ahol nincs teljes DE, ami az inhibit-hívásokat kezelné.
Az alapfogalom: timer és canceller
Az xidlehook nem "egy időzítő" – hanem timerek láncolatát kezeli. Minden timer három részből áll:
- duration – hány másodperc tétlenség után lépjen működésbe
- command – milyen parancsot futtasson le ekkor (/bin/sh -c alatt fut)
- canceller – milyen parancsot futtasson, ha a felhasználó a következő timer aktiválódása előtt újra aktívvá válik (üres string, ha nincs rá szükség)
Ez a hármas a --timer kapcsoló három argumentuma, és a --timer kapcsoló többször is megadható egyetlen parancssorban – ez adja a "lánc" jelleget (erről lentebb egy konkrét példa is jön).
A démon (xidlehook) összes kapcsolója
| Kapcsoló | Típus | Mit csinál |
|---|---|---|
| --timer <mp> <parancs> <megszakító> | ismételhető | A lánc egy eleme. Legalább egy kötelező (vagy a --print móddal helyettesíthető). |
| --not-when-fullscreen | be/ki kapcsoló | Ha az aktuális fókuszált ablak fullscreen állapotban van, a timer nem kerül végrehajtásra. Videólejátszásnál, játékoknál, prezentációknál hasznos. |
| --not-when-audio | be/ki kapcsoló | Ha a PulseAudio szerint bármelyik alkalmazás hangot ad ki, a timer nem kerül végrehajtásra. (Csak akkor elérhető, ha a pulse cargo-feature-rel épült a bináris – az AUR csomag alapból ezzel épül.) |
| --detect-sleep | be/ki kapcsoló | Ha a rendszer felébred egy suspend-ből, az idle-számláló nullázódik. Enélkül előfordulhat, hogy felébredés után szinte azonnal újra lefut a timer, mert az "idle idő" a suspend alatt eltelt időt is beleszámolta. |
| --once | be/ki kapcsoló | A teljes láncot csak egyszer futtatja végig, utána a démon kilép. Enélkül az xidlehook folyamatosan fut, és minden újabb tétlenségi ciklusnál újra elindítja a láncot. |
| be/ki kapcsoló | Nem indít démont, csak kiírja az aktuális tétlenségi időt (ezredmásodpercben) és kilép – az xprintidle kiváltására. Minden más kapcsolóval kizárja egymást. | |
| --socket <útvonal> | érték | Unix socketet nyit ezen az útvonalon, amin keresztül a xidlehook-client (vagy bármi más, ami JSON-sorokat tud küldeni) vezérelheti futás közben a démont. |
| -h, --help / -V, --version | be/ki kapcsoló | Súgó, illetve verziószám. |
Fontos, hogy a --not-when-fullscreen és a --not-when-audio minden timerre egyszerre vonatkozik egy adott démonpéldányon belül – nincs lehetőség arra, hogy csak a lánc egyik elemére alkalmazd, a másikra nem. Ha ilyen finomhangolás kell, külön démonpéldányt kell indítani külön socketekkel (az xidlehook ezt is támogatja: több példány futtatható párhuzamosan).
Timerek láncolása – gyakorlati példa
A klasszikus felhasználási eset: a képernyő előbb elhalványul, aztán zárolódik, végül a gép alvó módba megy – de csak akkor, ha közben tényleg nem történik semmi, és nem megy videó vagy fullscreen alkalmazás:
xidlehook \ --not-when-audio --not-when-fullscreen --detect-sleep \ --timer 300 'xrandr --output eDP-1 --brightness 0.3' 'xrandr --output eDP-1 --brightness 1.0' \ --timer 480 'i3lock' '' \ --timer 600 'systemctl suspend' ''
Ami itt történik:
- 5 perc (300 mp) tétlenség után elhalványítja a kijelzőt; ha időközben megmozdul az egér, a canceller visszaállítja a fényerőt
- 8 percnél (480 mp – a lánc előző eleméhez képest számít az idő, tehát ez 3 perccel az elhalványítás után) zárolja a képernyőt; itt nincs canceller, mert a zárolást felesleges "visszavonni"
- 10 percnél (600 mp, azaz 2 perccel a zárolás után) alvó módba küldi a gépet
A --detect-sleep azért fontos itt, mert enélkül a suspendből ébredés után a démon úgy vélné, hogy még mindig tart a régi tétlenségi periódus, és akár azonnal újra lezárolná/elhalványítaná a képernyőt.
A socket API és a xidlehook-client
Önmagában a démon nem tud külső parancsokra reagálni – ha meg akarod szakítani, szüneteltetni vagy lekérdezni futás közben, kell hozzá a --socket <útvonal> kapcsoló, és egy kliens, ami ír erre a socketre. Erre való a xidlehook-client segédprogram.
xidlehook --socket /tmp/xidlehook.sock --timer 600 'systemctl suspend' ''
A kliens minden hívásnál kötelezően megkapja ugyanazt a --socket útvonalat, utána egy alparancsot:
| Alparancs | Kapcsolók | Mit csinál |
|---|---|---|
| query | --timer <id>... (opcionális, üresen: mind) | Kilistázza a timerek aktuális állapotát (engedélyezett-e, mennyi van hátra stb.), JSON formában. |
| control | --action <Enable\|Disable\|Trigger\|Delete>, --timer <id>... | Egy vagy több timer be-/kikapcsolása, azonnali kiváltása, vagy törlése. Az id a --timer kapcsolók sorrendi indexe (0-tól számolva). |
| add | --time <mp>, --activation <parancs>..., --abortion <parancs>..., --deactivation <parancs>..., --index <n> | Futás közben ad hozzá egy új timert a lánchoz. Fontos: az --activation parancsa itt nem megy át a /bin/sh -c-n, ellentétben a démon indításkori --timer parancsával – összetettebb shell-szintaxishoz (&&, pipe-ok) explicit sh -c '...'-t kell köréírni. |
| reset-idle | – | Úgy tesz, mintha a felhasználó éppen mozdult volna – nullázza a tétlenségi számlálót, mintha valódi input érkezett volna. |
| stop-timers | – | Az összes timert felfüggeszti addig, amíg valódi felhasználói aktivitás nem történik. Ez gyakorlatilag egy "ne aludjon el most" gomb, hasonló funkcióval, mint egy caffeine alkalmazás. |
Kliens-példák
Az összes futó timer lekérdezése:
xidlehook-client --socket /tmp/xidlehook.sock query
A második timer (index 1) azonnali kiváltása – hasznos, ha manuálisan akarod triggerelni a zárolást anélkül, hogy megvárnád a tétlenségi időt:
xidlehook-client --socket /tmp/xidlehook.sock control --action Trigger --timer 1
"Ne aludjon most" gomb (pl. egy chadwm billentyűkombóhoz kötve):
xidlehook-client --socket /tmp/xidlehook.sock stop-timers
Új, futásidőben hozzáadott timer, ami 2 perc után értesítést küld (mivel az --activation nem megy át sh -c-n, ha shell-jellemzőt akarunk – pl. változó-behelyettesítést –, azt explicit meg kell hívni):
xidlehook-client --socket /tmp/xidlehook.sock add \ --time 120 \ --activation sh -c "notify-send 'Mindjárt zárol'"
Automatikus indítás systemd user service-ként
Mivel a démon önállóan fut, nem kell hozzá teljes DE – elég, ha a bejelentkezéskor elindul. Egy ~/.config/systemd/user/xidlehook.service:
[Unit] Description=Idle-alapú automatizálás (xidlehook) After=graphical-session.target [Service] Environment=DISPLAY=:0 ExecStart=/usr/bin/xidlehook --socket %t/xidlehook.sock --not-when-audio --not-when-fullscreen --detect-sleep --timer 600 'systemctl suspend' '' [Install] WantedBy=graphical-session.target
A %t a runtime könyvtárra (/run/user/<uid>) oldódik fel, így a socket a session-hez kötött helyre kerül. Ha startx/.xinitrc-ből indítod a chadwm-et display manager nélkül, egyszerűbb lehet ugyanezt a sort simán az .xinitrc-be tenni a WM indítása elé, háttérbe küldve.
Amire érdemes figyelni
- Csak X11-et támogat. Wayland alatt (pl. ha valaha átállnál) nem működik – ott swayidle/hypridle a megfelelő kategória.
- A --not-when-audio kizárólag PulseAudio-t ismer natívan. PipeWire alatt ez jellemzően működik a pipewire-pulse kompatibilitási réteg miatt, de ha valamiért natív PipeWire session-t futtatsz e nélkül, a hangdetektálás nem fog látni semmit.
- A fejlesztő (jD91mZM2) elhunyt, a projekt jelenleg közösségi fork-okból él tovább. Az Arch AUR csomag ennek ellenére évek óta stabilan build-elhető és karbantartott – ahogy a fenti fordítás is mutatja, a jelenlegi legfrissebb (0.10.0) tag simán lefordul a jelenlegi függőségekkel.
- A --not-when-fullscreen/--not-when-audio globális egy démonpéldányon belül, nem timerenkénti – ha erre szükséged van, külön démont kell indítani külön sockettel.
