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:
@@ -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"`
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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": {
|
||||
|
||||
Reference in New Issue
Block a user