Merge pull request 'dunst: make the font size and width settings, defaulting to today's values (hq ADR 0262)' (#132) from feat/setting-defaults into main

This commit was merged in pull request #132.
This commit is contained in:
2026-10-08 16:18:52 +00:00
5 changed files with 82 additions and 15 deletions
+18
View File
@@ -39,6 +39,24 @@ the account is not logged in.
| `dunst_rules` | the rules the running notifier holds, and the files they come from |
| `dunst_count` | shown, waiting, in history, and whether paused |
## Settings
Two preferences have defaults in the definition (novox/hq ADR 0262). The mesh's layer, then a machine's,
overrides them, and the file is written with the value, never with a variable dunst reads.
| setting | default | what it is |
|---|---|---|
| `font-size` | 10 | the points of `font = Inter <size>`; 10 reads well on a screen of about 100 DPI, which is the workstations |
| `width` | 250 | the notification's width in pixels; a larger font needs a wider notification |
A machine with a denser screen sets both for itself, and the next push writes them:
mesh-controller.settings {module: "dunst", node: "<machine>", values: '{"font-size": 16, "width": 400}'}
`mesh-controller.settings {module: "dunst", node: "<machine>"}` shows each value and where it came from:
the default, the mesh, or the machine. dunst reads its file when it starts, and nothing in this module
tells a running dunst that the file changed: a new size shows at the next login, or after `dunstctl reload`.
## What it chose, and what it improves
The workstations' files differed: one had the notifications bottom-right, 15 % transparent and with
@@ -12,22 +12,30 @@ import (
// every desktop module that carries it.
type manifest struct {
Module string `json:"module"`
Version string `json:"version"`
Capabilities []string `json:"capabilities"`
Requires []string `json:"requires"`
Claims []claim `json:"claims"`
Seats []any `json:"seats"`
Tools []string `json:"tools"`
Emits []string `json:"emits"`
Environment *environment `json:"environment"`
Shell []shellCode `json:"shell"`
Resources []map[string]any `json:"resources"`
Module string `json:"module"`
Version string `json:"version"`
Capabilities []string `json:"capabilities"`
Requires []string `json:"requires"`
Claims []claim `json:"claims"`
Seats []any `json:"seats"`
Tools []string `json:"tools"`
Settings map[string]setting `json:"settings"`
Emits []string `json:"emits"`
Environment *environment `json:"environment"`
Shell []shellCode `json:"shell"`
Resources []map[string]any `json:"resources"`
Build struct {
Artifacts []map[string]any `json:"artifacts"`
} `json:"build"`
}
// setting is one key's default, as the definition gives it (novox/hq ADR 0262).
type setting struct {
Kind string `json:"kind"`
Default any `json:"default"`
Why string `json:"why"`
}
type claim struct {
Name string `json:"name"`
Scope string `json:"scope"`
+30 -1
View File
@@ -43,7 +43,8 @@ func TestItOwnsItsFileAndTheDropInDirectory(t *testing.T) {
func TestTheFileIsTheDecidedOneAndCallsTheSeatsMenu(t *testing.T) {
m := readManifest(t)
c := m.resource(t, "configuration")["content"].(string)
for _, want := range []string{"origin = top-right", "transparency = 0", "corner_radius = 0", "font = Inter 10", "dmenu = dmenu -p dunst"} {
for _, want := range []string{"origin = top-right", "transparency = 0", "corner_radius = 0", "font = Inter ${setting:font-size}",
"width = ${setting:width}", "dmenu = dmenu -p dunst"} {
if !strings.Contains(c, " "+want+"\n") {
t.Errorf("lacks %q", want)
}
@@ -55,6 +56,34 @@ func TestTheFileIsTheDecidedOneAndCallsTheSeatsMenu(t *testing.T) {
}
}
// The font size and the width are preferences with today's values as their defaults (novox/hq ADR
// 0262): a machine with a denser screen sets its own, and every other machine's file is unchanged.
func TestTheFontSizeAndWidthAreSettingsWithTodaysDefaults(t *testing.T) {
m := readManifest(t)
want := map[string]float64{"font-size": 10, "width": 250}
if len(m.Settings) != len(want) {
t.Fatalf("settings: %+v", m.Settings)
}
for key, value := range want {
s, ok := m.Settings[key]
if !ok || s.Kind != "preference" || s.Default != value || strings.TrimSpace(s.Why) == "" {
t.Errorf("%s: %+v, want a preference defaulting to %v with why", key, s, value)
}
}
// Filled with the defaults, the file is the one every machine had before it took settings.
c := m.resource(t, "configuration")["content"].(string)
c = strings.ReplaceAll(c, "${setting:font-size}", "10")
c = strings.ReplaceAll(c, "${setting:width}", "250")
for _, want := range []string{"font = Inter 10", "width = 250"} {
if !strings.Contains(c, " "+want+"\n") {
t.Errorf("filled with the defaults, lacks %q", want)
}
}
if strings.Contains(c, "${setting:") {
t.Errorf("asks for a setting it gives no default: %s", c)
}
}
func TestNothingStartsItButTheBus(t *testing.T) {
m := readManifest(t)
if m.Shell != nil {
+2 -2
View File
@@ -11,7 +11,7 @@
follow = none
# Geometry
width = 250
width = ${setting:width}
height = (0, 300)
origin = top-right
offset = (10, 50)
@@ -37,7 +37,7 @@
corner_radius = 0
# Text: the interface face (research 026/04)
font = Inter 10
font = Inter ${setting:font-size}
line_height = 0
markup = full
format = "<b>%s</b>\n%b"
+13 -1
View File
@@ -21,6 +21,18 @@
"dunst_rules",
"dunst_count"
],
"settings": {
"font-size": {
"kind": "preference",
"default": 10,
"why": "10 points of Inter reads well on a screen of about 100 DPI; a denser screen needs a larger size"
},
"width": {
"kind": "preference",
"default": 250,
"why": "250 pixels fits a title of about forty characters at 10 points; a larger font needs a wider notification"
}
},
"resources": [
{
"id": "package",
@@ -52,7 +64,7 @@
"path": "${machine:account-home}/.config/dunst/dunstrc",
"owner": "${machine:account}",
"mode": "0644",
"content": "# dunst, the notifier (module dunst, novox/hq ADR 0208). Owned by the mesh: this file is replaced\n# at every push. Adopted from the laptop's file of 2026-10-04 (the two workstations differed in\n# position, transparency and corner radius; the laptop's square, opaque, top-right one matches the\n# rest of the desktop). Only what differs from dunst's defaults, and what the desktop relies on.\n#\n# Other modules' rules go in ~/.config/dunst/dunstrc.d/*.conf, which dunst reads after this file,\n# so a drop-in outranks it. dunst is started by D-Bus on the first notification: nothing starts it.\n\n[global]\n monitor = 0\n follow = none\n\n # Geometry\n width = 250\n height = (0, 300)\n origin = top-right\n offset = (10, 50)\n notification_limit = 20\n\n progress_bar = true\n progress_bar_height = 10\n progress_bar_frame_width = 1\n progress_bar_min_width = 150\n progress_bar_max_width = 300\n\n indicate_hidden = yes\n transparency = 0\n separator_height = 2\n padding = 8\n horizontal_padding = 8\n text_icon_padding = 0\n frame_width = 3\n frame_color = \"#de5200\"\n gap_size = 0\n separator_color = frame\n sort = yes\n corner_radius = 0\n\n # Text: the interface face (research 026/04)\n font = Inter 10\n line_height = 0\n markup = full\n format = \"<b>%s</b>\\n%b\"\n alignment = left\n vertical_alignment = center\n show_age_threshold = 60\n ellipsize = middle\n ignore_newline = no\n stack_duplicates = true\n hide_duplicate_count = false\n show_indicators = yes\n\n # Icons, from the desktop's icon theme\n enable_recursive_icon_lookup = true\n icon_theme = Adwaita\n icon_position = left\n min_icon_size = 32\n max_icon_size = 128\n\n # History\n sticky_history = yes\n history_length = 20\n\n # The context menu is the node's dmenu-compatible command, which the holder of node-launcher\n # answers (rofi on the workstations). Links open in the desktop's default browser.\n dmenu = dmenu -p dunst\n browser = /usr/bin/xdg-open\n always_run_script = true\n\n title = Dunst\n class = Dunst\n ignore_dbusclose = false\n\n mouse_left_click = close_current\n mouse_middle_click = do_action, close_current\n mouse_right_click = close_all\n\n[urgency_low]\n background = \"#000000\"\n foreground = \"#ffffff\"\n timeout = 10\n\n[urgency_normal]\n background = \"#000000\"\n foreground = \"#ffffff\"\n timeout = 10\n\n[urgency_critical]\n background = \"#000000\"\n foreground = \"#ffffff\"\n frame_color = \"#ff0000\"\n timeout = 0\n"
"content": "# dunst, the notifier (module dunst, novox/hq ADR 0208). Owned by the mesh: this file is replaced\n# at every push. Adopted from the laptop's file of 2026-10-04 (the two workstations differed in\n# position, transparency and corner radius; the laptop's square, opaque, top-right one matches the\n# rest of the desktop). Only what differs from dunst's defaults, and what the desktop relies on.\n#\n# Other modules' rules go in ~/.config/dunst/dunstrc.d/*.conf, which dunst reads after this file,\n# so a drop-in outranks it. dunst is started by D-Bus on the first notification: nothing starts it.\n\n[global]\n monitor = 0\n follow = none\n\n # Geometry\n width = ${setting:width}\n height = (0, 300)\n origin = top-right\n offset = (10, 50)\n notification_limit = 20\n\n progress_bar = true\n progress_bar_height = 10\n progress_bar_frame_width = 1\n progress_bar_min_width = 150\n progress_bar_max_width = 300\n\n indicate_hidden = yes\n transparency = 0\n separator_height = 2\n padding = 8\n horizontal_padding = 8\n text_icon_padding = 0\n frame_width = 3\n frame_color = \"#de5200\"\n gap_size = 0\n separator_color = frame\n sort = yes\n corner_radius = 0\n\n # Text: the interface face (research 026/04)\n font = Inter ${setting:font-size}\n line_height = 0\n markup = full\n format = \"<b>%s</b>\\n%b\"\n alignment = left\n vertical_alignment = center\n show_age_threshold = 60\n ellipsize = middle\n ignore_newline = no\n stack_duplicates = true\n hide_duplicate_count = false\n show_indicators = yes\n\n # Icons, from the desktop's icon theme\n enable_recursive_icon_lookup = true\n icon_theme = Adwaita\n icon_position = left\n min_icon_size = 32\n max_icon_size = 128\n\n # History\n sticky_history = yes\n history_length = 20\n\n # The context menu is the node's dmenu-compatible command, which the holder of node-launcher\n # answers (rofi on the workstations). Links open in the desktop's default browser.\n dmenu = dmenu -p dunst\n browser = /usr/bin/xdg-open\n always_run_script = true\n\n title = Dunst\n class = Dunst\n ignore_dbusclose = false\n\n mouse_left_click = close_current\n mouse_middle_click = do_action, close_current\n mouse_right_click = close_all\n\n[urgency_low]\n background = \"#000000\"\n foreground = \"#ffffff\"\n timeout = 10\n\n[urgency_normal]\n background = \"#000000\"\n foreground = \"#ffffff\"\n timeout = 10\n\n[urgency_critical]\n background = \"#000000\"\n foreground = \"#ffffff\"\n frame_color = \"#ff0000\"\n timeout = 0\n"
}
],
"build": {