From 5cd2bf5153a878342c0e6df16d739ba201f750e6 Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Wed, 3 Sep 2025 16:44:02 +0200 Subject: [PATCH 1/4] dunst: support reload on configuration change --- modules/services/dunst.nix | 181 ++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 93 deletions(-) diff --git a/modules/services/dunst.nix b/modules/services/dunst.nix index 69813fe07..c7173e6d1 100644 --- a/modules/services/dunst.nix +++ b/modules/services/dunst.nix @@ -131,102 +131,97 @@ in }; }; - config = lib.mkIf cfg.enable ( - lib.mkMerge [ - { - assertions = [ - (lib.hm.assertions.assertPlatform "services.dunst" pkgs lib.platforms.linux) + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.dunst" pkgs lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.dataFile."dbus-1/services/org.knopwob.dunst.service".source = + "${pkgs.dunst}/share/dbus-1/services/org.knopwob.dunst.service"; + + xdg.configFile."dunst/dunstrc" = lib.mkIf (cfg.settings != { }) { + text = toDunstIni cfg.settings; + }; + + services.dunst.settings.global.icon_path = + let + useCustomTheme = + cfg.iconTheme.package != hicolorTheme.package + || cfg.iconTheme.name != hicolorTheme.name + || cfg.iconTheme.size != hicolorTheme.size; + + basePaths = [ + "/run/current-system/sw" + config.home.profileDirectory + cfg.iconTheme.package + ] + ++ optional useCustomTheme hicolorTheme.package; + + themes = [ + cfg.iconTheme + ] + ++ optional useCustomTheme (hicolorTheme // { size = cfg.iconTheme.size; }); + + categories = [ + "actions" + "animations" + "apps" + "categories" + "devices" + "emblems" + "emotes" + "filesystem" + "intl" + "legacy" + "mimetypes" + "places" + "status" + "stock" ]; - home.packages = [ cfg.package ]; + mkPath = + { + basePath, + theme, + category, + }: + "${basePath}/share/icons/${theme.name}/${theme.size}/${category}"; + in + lib.concatMapStringsSep ":" mkPath ( + lib.cartesianProduct { + basePath = basePaths; + theme = themes; + category = categories; + } + ); - xdg.dataFile."dbus-1/services/org.knopwob.dunst.service".source = - "${pkgs.dunst}/share/dbus-1/services/org.knopwob.dunst.service"; + systemd.user.services.dunst = { + Unit = { + Description = "Dunst notification daemon"; + After = [ config.wayland.systemd.target ]; + PartOf = [ config.wayland.systemd.target ]; + X-Reload-Triggers = lib.mkIf (cfg.settings != { }) [ + "${config.xdg.configFile."dunst/dunstrc".source}" + ]; + }; - services.dunst.settings.global.icon_path = - let - useCustomTheme = - cfg.iconTheme.package != hicolorTheme.package - || cfg.iconTheme.name != hicolorTheme.name - || cfg.iconTheme.size != hicolorTheme.size; - - basePaths = [ - "/run/current-system/sw" - config.home.profileDirectory - cfg.iconTheme.package + Service = { + Type = "dbus"; + BusName = "org.freedesktop.Notifications"; + ExecStart = lib.escapeShellArgs ( + [ "${cfg.package}/bin/dunst" ] + ++ + # Using `-config` breaks dunst's drop-ins, so only use it when an alternative path is set + lib.optionals (cfg.configFile != null) [ + "-config" + cfg.configFile ] - ++ optional useCustomTheme hicolorTheme.package; - - themes = [ - cfg.iconTheme - ] - ++ optional useCustomTheme (hicolorTheme // { size = cfg.iconTheme.size; }); - - categories = [ - "actions" - "animations" - "apps" - "categories" - "devices" - "emblems" - "emotes" - "filesystem" - "intl" - "legacy" - "mimetypes" - "places" - "status" - "stock" - ]; - - mkPath = - { - basePath, - theme, - category, - }: - "${basePath}/share/icons/${theme.name}/${theme.size}/${category}"; - in - lib.concatMapStringsSep ":" mkPath ( - lib.cartesianProduct { - basePath = basePaths; - theme = themes; - category = categories; - } - ); - - systemd.user.services.dunst = { - Unit = { - Description = "Dunst notification daemon"; - After = [ config.wayland.systemd.target ]; - PartOf = [ config.wayland.systemd.target ]; - }; - - Service = { - Type = "dbus"; - BusName = "org.freedesktop.Notifications"; - ExecStart = lib.escapeShellArgs ( - [ "${cfg.package}/bin/dunst" ] - ++ - # Using `-config` breaks dunst's drop-ins, so only use it when an alternative path is set - lib.optionals (cfg.configFile != null) [ - "-config" - cfg.configFile - ] - ); - Environment = lib.optionalString (cfg.waylandDisplay != "") "WAYLAND_DISPLAY=${cfg.waylandDisplay}"; - }; - }; - } - - (lib.mkIf (cfg.settings != { }) { - xdg.configFile."dunst/dunstrc" = { - text = toDunstIni cfg.settings; - onChange = '' - ${pkgs.procps}/bin/pkill -u "$USER" ''${VERBOSE+-e} dunst || true - ''; - }; - }) - ] - ); + ); + ExecReload = "${cfg.package}/bin/dunstctl reload"; + Environment = lib.optionalString (cfg.waylandDisplay != "") "WAYLAND_DISPLAY=${cfg.waylandDisplay}"; + }; + }; + }; } From 174ba89ccbbfd9fbae185cf6e8ae6ca88ba3e51d Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Thu, 4 Sep 2025 09:52:50 +0200 Subject: [PATCH 2/4] dunst: use dbus service file from configured package --- modules/services/dunst.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/services/dunst.nix b/modules/services/dunst.nix index c7173e6d1..ef6a07d59 100644 --- a/modules/services/dunst.nix +++ b/modules/services/dunst.nix @@ -139,7 +139,7 @@ in home.packages = [ cfg.package ]; xdg.dataFile."dbus-1/services/org.knopwob.dunst.service".source = - "${pkgs.dunst}/share/dbus-1/services/org.knopwob.dunst.service"; + "${cfg.package}/share/dbus-1/services/org.knopwob.dunst.service"; xdg.configFile."dunst/dunstrc" = lib.mkIf (cfg.settings != { }) { text = toDunstIni cfg.settings; From 584fccfdfa32e720295ec456146b1a18567eda8e Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Thu, 4 Sep 2025 09:26:14 +0200 Subject: [PATCH 3/4] dunst: add tests --- tests/modules/services/dunst/default.nix | 6 ++ .../services/dunst/with-settings-expected.ini | 14 +++++ .../modules/services/dunst/with-settings.nix | 59 +++++++++++++++++++ .../dunst/without-settings-expected.ini | 2 + .../services/dunst/without-settings.nix | 42 +++++++++++++ 5 files changed, 123 insertions(+) create mode 100644 tests/modules/services/dunst/default.nix create mode 100644 tests/modules/services/dunst/with-settings-expected.ini create mode 100644 tests/modules/services/dunst/with-settings.nix create mode 100644 tests/modules/services/dunst/without-settings-expected.ini create mode 100644 tests/modules/services/dunst/without-settings.nix diff --git a/tests/modules/services/dunst/default.nix b/tests/modules/services/dunst/default.nix new file mode 100644 index 000000000..c5c42c08b --- /dev/null +++ b/tests/modules/services/dunst/default.nix @@ -0,0 +1,6 @@ +{ lib, pkgs, ... }: + +lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux { + dunst-with-settings = ./with-settings.nix; + dunst-without-settings = ./without-settings.nix; +} diff --git a/tests/modules/services/dunst/with-settings-expected.ini b/tests/modules/services/dunst/with-settings-expected.ini new file mode 100644 index 000000000..73a50ecca --- /dev/null +++ b/tests/modules/services/dunst/with-settings-expected.ini @@ -0,0 +1,14 @@ +[global] +font="Droid Sans 9" +frame_color="#eceff1" +height=300 +icon_path="/run/current-system/sw/share/icons/hicolor/32x32/actions:/run/current-system/sw/share/icons/hicolor/32x32/animations:/run/current-system/sw/share/icons/hicolor/32x32/apps:/run/current-system/sw/share/icons/hicolor/32x32/categories:/run/current-system/sw/share/icons/hicolor/32x32/devices:/run/current-system/sw/share/icons/hicolor/32x32/emblems:/run/current-system/sw/share/icons/hicolor/32x32/emotes:/run/current-system/sw/share/icons/hicolor/32x32/filesystem:/run/current-system/sw/share/icons/hicolor/32x32/intl:/run/current-system/sw/share/icons/hicolor/32x32/legacy:/run/current-system/sw/share/icons/hicolor/32x32/mimetypes:/run/current-system/sw/share/icons/hicolor/32x32/places:/run/current-system/sw/share/icons/hicolor/32x32/status:/run/current-system/sw/share/icons/hicolor/32x32/stock:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/actions:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/animations:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/apps:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/categories:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/devices:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/emblems:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/emotes:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/filesystem:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/intl:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/legacy:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/mimetypes:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/places:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/status:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/stock:@hicolor-icon-theme@/share/icons/hicolor/32x32/actions:@hicolor-icon-theme@/share/icons/hicolor/32x32/animations:@hicolor-icon-theme@/share/icons/hicolor/32x32/apps:@hicolor-icon-theme@/share/icons/hicolor/32x32/categories:@hicolor-icon-theme@/share/icons/hicolor/32x32/devices:@hicolor-icon-theme@/share/icons/hicolor/32x32/emblems:@hicolor-icon-theme@/share/icons/hicolor/32x32/emotes:@hicolor-icon-theme@/share/icons/hicolor/32x32/filesystem:@hicolor-icon-theme@/share/icons/hicolor/32x32/intl:@hicolor-icon-theme@/share/icons/hicolor/32x32/legacy:@hicolor-icon-theme@/share/icons/hicolor/32x32/mimetypes:@hicolor-icon-theme@/share/icons/hicolor/32x32/places:@hicolor-icon-theme@/share/icons/hicolor/32x32/status:@hicolor-icon-theme@/share/icons/hicolor/32x32/stock" +offset="30x50" +origin="top-right" +transparency=10 +width=300 + +[urgency_normal] +background="#37474f" +foreground="#eceff1" +timeout=10 diff --git a/tests/modules/services/dunst/with-settings.nix b/tests/modules/services/dunst/with-settings.nix new file mode 100644 index 000000000..7c853be2a --- /dev/null +++ b/tests/modules/services/dunst/with-settings.nix @@ -0,0 +1,59 @@ +{ config, ... }: +let + inherit (config.lib.test) mkStubPackage; +in +{ + services.dunst = { + enable = true; + package = mkStubPackage { + name = "dunst"; + buildScript = '' + mkdir -p $out/share/dbus-1/services + echo test > $out/share/dbus-1/services/org.knopwob.dunst.service + ''; + }; + settings = { + global = { + width = 300; + height = 300; + offset = "30x50"; + origin = "top-right"; + transparency = 10; + frame_color = "#eceff1"; + font = "Droid Sans 9"; + }; + + urgency_normal = { + background = "#37474f"; + foreground = "#eceff1"; + timeout = 10; + }; + }; + }; + + nmt.script = '' + configFile=home-files/.config/dunst/dunstrc + serviceFile=home-files/.config/systemd/user/dunst.service + + assertFileExists $configFile + assertFileContent $configFile ${./with-settings-expected.ini} + + assertFileExists $serviceFile + assertFileContent \ + $(normalizeStorePaths $serviceFile) \ + ${builtins.toFile "expected.service" '' + [Service] + BusName=org.freedesktop.Notifications + Environment= + ExecReload=/nix/store/00000000000000000000000000000000-dunst/bin/dunstctl reload + ExecStart=/nix/store/00000000000000000000000000000000-dunst/bin/dunst + Type=dbus + + [Unit] + After=graphical-session.target + Description=Dunst notification daemon + PartOf=graphical-session.target + X-Reload-Triggers=/nix/store/00000000000000000000000000000000-hm_dunstdunstrc + ''} + ''; +} diff --git a/tests/modules/services/dunst/without-settings-expected.ini b/tests/modules/services/dunst/without-settings-expected.ini new file mode 100644 index 000000000..d3ee2d574 --- /dev/null +++ b/tests/modules/services/dunst/without-settings-expected.ini @@ -0,0 +1,2 @@ +[global] +icon_path="/run/current-system/sw/share/icons/hicolor/32x32/actions:/run/current-system/sw/share/icons/hicolor/32x32/animations:/run/current-system/sw/share/icons/hicolor/32x32/apps:/run/current-system/sw/share/icons/hicolor/32x32/categories:/run/current-system/sw/share/icons/hicolor/32x32/devices:/run/current-system/sw/share/icons/hicolor/32x32/emblems:/run/current-system/sw/share/icons/hicolor/32x32/emotes:/run/current-system/sw/share/icons/hicolor/32x32/filesystem:/run/current-system/sw/share/icons/hicolor/32x32/intl:/run/current-system/sw/share/icons/hicolor/32x32/legacy:/run/current-system/sw/share/icons/hicolor/32x32/mimetypes:/run/current-system/sw/share/icons/hicolor/32x32/places:/run/current-system/sw/share/icons/hicolor/32x32/status:/run/current-system/sw/share/icons/hicolor/32x32/stock:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/actions:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/animations:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/apps:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/categories:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/devices:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/emblems:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/emotes:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/filesystem:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/intl:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/legacy:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/mimetypes:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/places:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/status:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/stock:@hicolor-icon-theme@/share/icons/hicolor/32x32/actions:@hicolor-icon-theme@/share/icons/hicolor/32x32/animations:@hicolor-icon-theme@/share/icons/hicolor/32x32/apps:@hicolor-icon-theme@/share/icons/hicolor/32x32/categories:@hicolor-icon-theme@/share/icons/hicolor/32x32/devices:@hicolor-icon-theme@/share/icons/hicolor/32x32/emblems:@hicolor-icon-theme@/share/icons/hicolor/32x32/emotes:@hicolor-icon-theme@/share/icons/hicolor/32x32/filesystem:@hicolor-icon-theme@/share/icons/hicolor/32x32/intl:@hicolor-icon-theme@/share/icons/hicolor/32x32/legacy:@hicolor-icon-theme@/share/icons/hicolor/32x32/mimetypes:@hicolor-icon-theme@/share/icons/hicolor/32x32/places:@hicolor-icon-theme@/share/icons/hicolor/32x32/status:@hicolor-icon-theme@/share/icons/hicolor/32x32/stock" diff --git a/tests/modules/services/dunst/without-settings.nix b/tests/modules/services/dunst/without-settings.nix new file mode 100644 index 000000000..b4b0ce97e --- /dev/null +++ b/tests/modules/services/dunst/without-settings.nix @@ -0,0 +1,42 @@ +{ config, ... }: +let + inherit (config.lib.test) mkStubPackage; +in +{ + services.dunst = { + enable = true; + package = mkStubPackage { + name = "dunst"; + buildScript = '' + mkdir -p $out/share/dbus-1/services + echo test > $out/share/dbus-1/services/org.knopwob.dunst.service + ''; + }; + }; + + nmt.script = '' + configFile=home-files/.config/dunst/dunstrc + serviceFile=home-files/.config/systemd/user/dunst.service + + assertFileExists $configFile + assertFileContent $configFile ${./without-settings-expected.ini} + + assertFileExists $serviceFile + assertFileContent \ + $(normalizeStorePaths $serviceFile) \ + ${builtins.toFile "expected.service" '' + [Service] + BusName=org.freedesktop.Notifications + Environment= + ExecReload=/nix/store/00000000000000000000000000000000-dunst/bin/dunstctl reload + ExecStart=/nix/store/00000000000000000000000000000000-dunst/bin/dunst + Type=dbus + + [Unit] + After=graphical-session.target + Description=Dunst notification daemon + PartOf=graphical-session.target + X-Reload-Triggers=/nix/store/00000000000000000000000000000000-hm_dunstdunstrc + ''} + ''; +} From 61124583121108b5927d73247df663a7ddc4fdf6 Mon Sep 17 00:00:00 2001 From: Robert Helgesson Date: Thu, 4 Sep 2025 10:49:32 +0200 Subject: [PATCH 4/4] dunst: fix deprecated configuration in example --- modules/services/dunst.nix | 6 +++--- tests/modules/services/dunst/with-settings-expected.ini | 6 +++--- tests/modules/services/dunst/with-settings.nix | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/services/dunst.nix b/modules/services/dunst.nix index ef6a07d59..fe8cfb1fc 100644 --- a/modules/services/dunst.nix +++ b/modules/services/dunst.nix @@ -111,9 +111,9 @@ in example = literalExpression '' { global = { - width = 300; - height = 300; - offset = "30x50"; + width = "(200,300)"; + height = "(0,150)"; + offset = "(30,50)"; origin = "top-right"; transparency = 10; frame_color = "#eceff1"; diff --git a/tests/modules/services/dunst/with-settings-expected.ini b/tests/modules/services/dunst/with-settings-expected.ini index 73a50ecca..041a48482 100644 --- a/tests/modules/services/dunst/with-settings-expected.ini +++ b/tests/modules/services/dunst/with-settings-expected.ini @@ -1,12 +1,12 @@ [global] font="Droid Sans 9" frame_color="#eceff1" -height=300 +height="(0,150)" icon_path="/run/current-system/sw/share/icons/hicolor/32x32/actions:/run/current-system/sw/share/icons/hicolor/32x32/animations:/run/current-system/sw/share/icons/hicolor/32x32/apps:/run/current-system/sw/share/icons/hicolor/32x32/categories:/run/current-system/sw/share/icons/hicolor/32x32/devices:/run/current-system/sw/share/icons/hicolor/32x32/emblems:/run/current-system/sw/share/icons/hicolor/32x32/emotes:/run/current-system/sw/share/icons/hicolor/32x32/filesystem:/run/current-system/sw/share/icons/hicolor/32x32/intl:/run/current-system/sw/share/icons/hicolor/32x32/legacy:/run/current-system/sw/share/icons/hicolor/32x32/mimetypes:/run/current-system/sw/share/icons/hicolor/32x32/places:/run/current-system/sw/share/icons/hicolor/32x32/status:/run/current-system/sw/share/icons/hicolor/32x32/stock:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/actions:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/animations:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/apps:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/categories:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/devices:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/emblems:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/emotes:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/filesystem:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/intl:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/legacy:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/mimetypes:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/places:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/status:/home/hm-user/.nix-profile/share/icons/hicolor/32x32/stock:@hicolor-icon-theme@/share/icons/hicolor/32x32/actions:@hicolor-icon-theme@/share/icons/hicolor/32x32/animations:@hicolor-icon-theme@/share/icons/hicolor/32x32/apps:@hicolor-icon-theme@/share/icons/hicolor/32x32/categories:@hicolor-icon-theme@/share/icons/hicolor/32x32/devices:@hicolor-icon-theme@/share/icons/hicolor/32x32/emblems:@hicolor-icon-theme@/share/icons/hicolor/32x32/emotes:@hicolor-icon-theme@/share/icons/hicolor/32x32/filesystem:@hicolor-icon-theme@/share/icons/hicolor/32x32/intl:@hicolor-icon-theme@/share/icons/hicolor/32x32/legacy:@hicolor-icon-theme@/share/icons/hicolor/32x32/mimetypes:@hicolor-icon-theme@/share/icons/hicolor/32x32/places:@hicolor-icon-theme@/share/icons/hicolor/32x32/status:@hicolor-icon-theme@/share/icons/hicolor/32x32/stock" -offset="30x50" +offset="(30,50)" origin="top-right" transparency=10 -width=300 +width="(200,300)" [urgency_normal] background="#37474f" diff --git a/tests/modules/services/dunst/with-settings.nix b/tests/modules/services/dunst/with-settings.nix index 7c853be2a..cee5b7ea3 100644 --- a/tests/modules/services/dunst/with-settings.nix +++ b/tests/modules/services/dunst/with-settings.nix @@ -14,9 +14,9 @@ in }; settings = { global = { - width = 300; - height = 300; - offset = "30x50"; + width = "(200,300)"; + height = "(0,150)"; + offset = "(30,50)"; origin = "top-right"; transparency = 10; frame_color = "#eceff1";