requirements.go RawHistoryFolder
1package app
2
3import (
4 "fmt"
5 "strings"
6
7 "github.com/bnema/neferafk/internal/ports"
8)
9
10// Requirements derives what the daemon needs from its startup config. Idle
11// notification/input-wake and lock/visual protocols are always required: a
12// daemon that cannot observe activity or lock is unsupported, and manual lock
13// (logind Lock, control socket) needs the lock protocols even with lock.after
14// off. Output power and sleep support are required only when enabled; enabling
15// them later by live reload needs a restart (a warning is logged).
16func Requirements(cfg ports.Config) (ports.WaylandRequirements, ports.SystemRequirements) {
17 return ports.WaylandRequirements{Idle: true, InputWake: true, OutputPower: cfg.OffAfter > 0, Lock: true, Visual: true},
18 ports.SystemRequirements{Session: true, Sleep: cfg.SleepAfter > 0 || cfg.LockAfter > 0}
19}
20
21// UnsupportedError lists every missing capability, one per line.
22type UnsupportedError struct{ Missing []string }
23
24func (e *UnsupportedError) Error() string {
25 return "unsupported environment:\n - " + strings.Join(e.Missing, "\n - ")
26}
27
28const suspendMissing = "non-interactive suspend"
29
30// unsupported merges adapter reports. Missing non-interactive suspend never
31// blocks startup: fade, lock and output-off still run and only the sleep
32// action is skipped (suspendWarning). The sleep delay inhibitor stays required
33// because before-sleep locking depends on it.
34func unsupported(wl *ports.Capabilities, sys *ports.SystemCapabilities) []string {
35 var missing []string
36 if wl != nil {
37 for _, m := range wl.Missing {
38 missing = append(missing, "wayland: "+m)
39 }
40 }
41 if sys != nil {
42 if !sys.Session {
43 missing = append(missing, "logind: current session")
44 }
45 for _, m := range sys.Missing {
46 if strings.HasPrefix(m, suspendMissing) {
47 continue // degrades only the sleep action, see suspendWarning
48 }
49 missing = append(missing, "logind: "+m)
50 }
51 }
52 return missing
53}
54
55// suspendWarning reports why an enabled sleep action cannot suspend, or "".
56func suspendWarning(cfg ports.Config, sys *ports.SystemCapabilities) string {
57 if cfg.SleepAfter == 0 || sys == nil || sys.Suspend {
58 return ""
59 }
60 return fmt.Sprintf("suspend unavailable (%s); sleep.after is skipped", sys.SuspendAuthorization)
61}