A setting changed through mesh-controller.settings rewrote dunstrc, but the running dunst kept the old font and width until the next login. Declare the package's dunst.service in the account's manager, without a state, with reload-on the configuration, so the node-engine runs its ExecReload (dunstctl reload) and what is on screen stays. Add dunst_reload to do the same on demand and say the font and width the files set.
99 lines
3.1 KiB
Go
99 lines
3.1 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
// Reading the configuration again (novox/hq ADR 0262). A running dunst reads its files only when it
|
|
// starts or is told to reload; the node-engine tells it through the account's dunst.service (its
|
|
// ExecReload is `dunstctl reload`) whenever the mesh rewrites dunstrc, and dunst_reload tells it now.
|
|
// A reload keeps the notifications on screen and in the history; a restart would lose them.
|
|
|
|
// Globals are the [global] font and width the configuration files set, and which file set each.
|
|
type Globals struct {
|
|
Font string `json:"font,omitempty"`
|
|
FontSize int `json:"font_size,omitempty"`
|
|
FontFrom string `json:"font_from,omitempty"`
|
|
Width string `json:"width,omitempty"`
|
|
WidthFrom string `json:"width_from,omitempty"`
|
|
}
|
|
|
|
// ReloadResult is what dunst_reload answers.
|
|
type ReloadResult struct {
|
|
Reloaded bool `json:"reloaded"`
|
|
Files []string `json:"files"`
|
|
Globals
|
|
Displayed int `json:"displayed"`
|
|
Note string `json:"note"`
|
|
}
|
|
|
|
// Reload tells the running dunst to read its configuration again, shows it still answers, and says
|
|
// the font and width the files it read set.
|
|
func Reload() (ReloadResult, error) {
|
|
// No files named: dunst reads its own search path, dunstrc and then dunstrc.d, as at its start.
|
|
if _, err := dunstctl("reload"); err != nil {
|
|
return ReloadResult{}, err
|
|
}
|
|
shown, err := dunstctl("count", "displayed")
|
|
if err != nil {
|
|
return ReloadResult{}, err
|
|
}
|
|
displayed, _ := strconv.Atoi(strings.TrimSpace(shown))
|
|
files := configFiles(filepath.Join(operatorHome(), ".config", "dunst"))
|
|
return ReloadResult{
|
|
Reloaded: true,
|
|
Files: files,
|
|
Globals: globalsOf(files),
|
|
Displayed: displayed,
|
|
Note: "dunst read these files again and still answers. dunst does not answer its settings over " +
|
|
"the bus, so font and width are what the files it read set (the last file that sets one wins); " +
|
|
"the next notification is drawn with them",
|
|
}, nil
|
|
}
|
|
|
|
// globalsOf reads the [global] font and width from the files in the order dunst reads them; a later
|
|
// file outranks an earlier one, and a rule's own font is the rule's, not the global one.
|
|
func globalsOf(files []string) Globals {
|
|
var g Globals
|
|
for _, path := range files {
|
|
f, err := os.Open(path)
|
|
if err != nil {
|
|
continue
|
|
}
|
|
section := ""
|
|
lines := bufio.NewScanner(f)
|
|
for lines.Scan() {
|
|
line := strings.TrimSpace(lines.Text())
|
|
if line == "" || strings.HasPrefix(line, "#") || strings.HasPrefix(line, ";") {
|
|
continue
|
|
}
|
|
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
|
section = strings.TrimSpace(line[1 : len(line)-1])
|
|
continue
|
|
}
|
|
key, value, ok := strings.Cut(line, "=")
|
|
if !ok || section != "global" {
|
|
continue
|
|
}
|
|
value = strings.Trim(strings.TrimSpace(value), `"`)
|
|
switch strings.TrimSpace(key) {
|
|
case "font":
|
|
g.Font, g.FontFrom, g.FontSize = value, path, 0
|
|
if fields := strings.Fields(value); len(fields) > 0 {
|
|
if n, err := strconv.Atoi(fields[len(fields)-1]); err == nil {
|
|
g.FontSize = n
|
|
}
|
|
}
|
|
case "width":
|
|
g.Width, g.WidthFrom = value, path
|
|
}
|
|
}
|
|
f.Close()
|
|
}
|
|
return g
|
|
}
|