6 name = "ayatana-indicators";
9 maintainers = lib.teams.lomiri.members;
17 ./common/user-account.nix
20 test-support.displayManager.auto = {
27 desktopManager.mate.enable = true;
29 services.displayManager.defaultSession = lib.mkForce "mate";
31 services.ayatana-indicators = {
36 ayatana-indicator-bluetooth
37 ayatana-indicator-datetime
38 ayatana-indicator-display
39 ayatana-indicator-messages
40 ayatana-indicator-power
41 ayatana-indicator-session
42 ayatana-indicator-sound
44 ++ (with pkgs.lomiri; [
45 lomiri-indicator-network
50 # Setup needed by some indicators
52 services.accounts-daemon.enable = true; # messages
54 # Lomiri-ish setup for Lomiri indicators
55 # TODO move into a Lomiri module, once the package set is far enough for the DE to start
57 networking.networkmanager.enable = true; # lomiri-network-indicator
58 # TODO potentially urfkill for lomiri-network-indicator?
60 services.dbus.packages = with pkgs.lomiri; [ libusermetrics ];
62 environment.systemPackages = with pkgs.lomiri; [ lomiri-schemas ];
64 services.telepathy.enable = true;
66 users.users.usermetrics = {
67 group = "usermetrics";
68 home = "/var/lib/usermetrics";
73 users.groups.usermetrics = { };
76 # TODO session indicator starts up in a semi-broken state, but works fine after a restart. maybe being started before graphical session is truly up & ready?
80 runCommandOverServiceList = list: command: lib.strings.concatMapStringsSep "\n" command list;
82 runCommandOverAyatanaIndicators = runCommandOverServiceList
83 nodes.machine.systemd.user.targets.ayatana-indicators.wants;
85 runCommandOverLomiriIndicators = runCommandOverServiceList nodes.machine.systemd.user.targets.lomiri-indicators.wants;
91 # Desktop environment should reach graphical-session.target
92 machine.wait_for_unit("graphical-session.target", "${user}")
94 # MATE relies on XDG autostart to bring up the indicators.
95 # Not sure *when* XDG autostart fires them up, and awaiting pgrep success seems to misbehave?
98 # Now check if all indicators were brought up successfully, and kill them for later
100 + (runCommandOverAyatanaIndicators (
103 serviceExec = builtins.replaceStrings [ "." ] [ "-" ] service;
106 machine.wait_until_succeeds("pgrep -u ${user} -f ${serviceExec}")
107 machine.succeed("pkill -f ${serviceExec}")
112 # Ayatana target is the preferred way of starting up indicators on SystemD session, the graphical session is responsible for starting this if it supports them.
113 # Mate currently doesn't do this, so start it manually for checking (https://github.com/mate-desktop/mate-indicator-applet/issues/63)
114 machine.systemctl("start ayatana-indicators.target", "${user}")
115 machine.wait_for_unit("ayatana-indicators.target", "${user}")
117 # Let all indicator services do their startups, potential post-launch crash & restart cycles so we can properly check for failures
118 # Not sure if there's a better way of awaiting this without false-positive potential
121 # Now check if all indicator services were brought up successfully
123 + runCommandOverAyatanaIndicators (service: ''
124 machine.wait_for_unit("${service}", "${user}")
128 machine.systemctl("stop ayatana-indicators.target", "${user}")
130 # Let all indicator services do their shutdowns
131 # Not sure if there's a better way of awaiting this without false-positive potential
134 # Lomiri uses a different target, which launches a slightly different set of indicators
135 machine.systemctl("start lomiri-indicators.target", "${user}")
136 machine.wait_for_unit("lomiri-indicators.target", "${user}")
138 # Let all indicator services do their startups, potential post-launch crash & restart cycles so we can properly check for failures
139 # Not sure if there's a better way of awaiting this without false-positive potential
142 # Now check if all indicator services were brought up successfully
144 + runCommandOverLomiriIndicators (service: ''
145 machine.wait_for_unit("${service}", "${user}")