1{
2 config,
3 pkgs,
4 lib,
5 ...
6}:
7
8let
9 cfg = config.services.desktopManager.lomiri;
10in
11{
12 options.services.desktopManager.lomiri = {
13 enable = lib.mkEnableOption ''
14 the Lomiri graphical shell (formerly known as Unity8)
15 '';
16
17 basics = lib.mkOption {
18 internal = true;
19 description = ''
20 Enable basic things for getting Lomiri working.
21 '';
22 type = lib.types.bool;
23 default = config.services.xserver.displayManager.lightdm.greeters.lomiri.enable || cfg.enable;
24 };
25 };
26
27 config = lib.mkMerge [
28 # Basics for getting Lomiri to work
29 (lib.mkIf cfg.basics {
30 environment = {
31 # To override the default keyboard layout in Lomiri
32 etc.${pkgs.lomiri.lomiri.passthru.etcLayoutsFile}.text =
33 lib.strings.replaceStrings
34 [ "," ]
35 [
36 "\n"
37 ]
38 config.services.xserver.xkb.layout;
39
40 pathsToLink = [
41 # Data
42 "/share/locale" # TODO LUITK hardcoded default locale path, fix individual apps to not rely on it
43 "/share/wallpapers"
44 ];
45
46 systemPackages = with pkgs.lomiri; [
47 lomiri-wallpapers # default + additional wallpaper
48 suru-icon-theme # basic indicator icons
49 ];
50 };
51
52 fonts.packages = with pkgs; [
53 ubuntu-classic # Ubuntu is default font
54 ];
55
56 # Xwayland is partly hardcoded in Mir so it can't really be fully turned off, and it must be on PATH for X11 apps *and Lomiri's web browser* to work.
57 # Until Mir/Lomiri can be properly used without it, force it on so everything behaves as expected.
58 programs.xwayland.enable = lib.mkForce true;
59
60 services.ayatana-indicators = {
61 enable = true;
62 packages = (
63 with pkgs;
64 [
65 ayatana-indicator-datetime # Clock
66 ayatana-indicator-session # Controls for shutting down etc
67 ]
68 );
69 };
70 })
71
72 # Full Lomiri DE
73 (lib.mkIf cfg.enable {
74 # We need the basic setup as well
75 services.desktopManager.lomiri.basics = true;
76
77 environment = {
78 systemPackages =
79 (with pkgs; [
80 glib # XDG MIME-related tools identify it as GNOME, add gio for MIME identification to work
81 libayatana-common
82 ubports-click
83 ])
84 ++ (with pkgs.lomiri; [
85 hfd-service
86 libusermetrics
87 lomiri
88 lomiri-calculator-app
89 lomiri-calendar-app
90 lomiri-camera-app
91 lomiri-clock-app
92 lomiri-content-hub
93 lomiri-docviewer-app
94 lomiri-download-manager
95 lomiri-filemanager-app
96 lomiri-gallery-app
97 lomiri-history-service
98 lomiri-mediaplayer-app
99 lomiri-music-app
100 lomiri-polkit-agent
101 lomiri-schemas # exposes some required dbus interfaces
102 lomiri-session # wrappers to properly launch the session
103 lomiri-sounds
104 lomiri-system-settings
105 lomiri-telephony-service
106 lomiri-terminal-app
107 lomiri-thumbnailer
108 lomiri-url-dispatcher
109 mediascanner2 # TODO possibly needs to be kicked off by graphical-session.target
110 morph-browser
111 qtmir # not having its desktop file for Xwayland available causes any X11 application to crash the session
112 teleports
113 ]);
114 };
115
116 hardware = {
117 bluetooth.enable = lib.mkDefault true;
118 };
119
120 networking.networkmanager.enable = lib.mkDefault true;
121
122 systemd.packages = with pkgs.lomiri; [
123 hfd-service
124 lomiri-download-manager
125 ];
126
127 services.dbus.packages = with pkgs.lomiri; [
128 hfd-service
129 libusermetrics
130 lomiri-download-manager
131 ];
132
133 # Copy-pasted basic stuff
134 hardware.graphics.enable = lib.mkDefault true;
135 fonts.enableDefaultPackages = lib.mkDefault true;
136 programs.dconf.enable = lib.mkDefault true;
137
138 services.accounts-daemon.enable = true;
139
140 services.ayatana-indicators = {
141 enable = true;
142 packages =
143 (
144 with pkgs;
145 [
146 ayatana-indicator-display
147 ayatana-indicator-messages
148 ayatana-indicator-power
149 ]
150 ++ lib.optionals config.hardware.bluetooth.enable [ ayatana-indicator-bluetooth ]
151 ++ lib.optionals (config.services.pulseaudio.enable || config.services.pipewire.pulse.enable) [
152 ayatana-indicator-sound
153 ]
154 )
155 ++ (
156 with pkgs.lomiri;
157 [ lomiri-telephony-service ]
158 ++ lib.optionals config.networking.networkmanager.enable [ lomiri-indicator-network ]
159 );
160 };
161
162 services.udisks2.enable = true;
163 services.upower.enable = true;
164 services.geoclue2.enable = true;
165
166 services.gnome.evolution-data-server = {
167 enable = true;
168 plugins = with pkgs; [
169 # TODO: lomiri.address-book-service
170 ];
171 };
172
173 services.telepathy.enable = true;
174
175 services.displayManager = {
176 defaultSession = lib.mkDefault "lomiri";
177 sessionPackages = with pkgs.lomiri; [ lomiri-session ];
178 };
179
180 services.xserver = {
181 enable = lib.mkDefault true;
182 displayManager.lightdm = {
183 enable = lib.mkDefault true;
184 greeters.lomiri.enable = lib.mkDefault true;
185 };
186 };
187
188 environment.pathsToLink = [
189 # Configs for inter-app data exchange system
190 "/share/lomiri-content-hub/peers"
191 # Configs for inter-app URL requests
192 "/share/lomiri-url-dispatcher/urls"
193 # Splash screens & other images for desktop apps launched via lomiri-app-launch
194 "/share/lomiri-app-launch"
195 # TODO Try to get maliit stuff working
196 "/share/maliit/plugins"
197 # At least the network indicator is still under the unity name, due to leftover Unity-isms
198 "/share/unity"
199 # Data
200 "/share/sounds"
201 ];
202
203 systemd.user.services =
204 let
205 lomiriService = "lomiri.service";
206 lomiriServiceNames = [
207 lomiriService
208 "lomiri-full-greeter.service"
209 "lomiri-full-shell.service"
210 "lomiri-greeter.service"
211 "lomiri-shell.service"
212 ];
213 in
214 {
215 # Unconditionally run service that collects system-installed URL handlers before LUD
216 # TODO also run user-installed one?
217 "lomiri-url-dispatcher-update-system-dir" = {
218 description = "Lomiri URL dispatcher system directory updater";
219 wantedBy = [ "lomiri-url-dispatcher.service" ];
220 before = [ "lomiri-url-dispatcher.service" ];
221 serviceConfig = {
222 Type = "oneshot";
223 ExecStart = "${pkgs.lomiri.lomiri-url-dispatcher}/libexec/lomiri-url-dispatcher/lomiri-update-directory /run/current-system/sw/share/lomiri-url-dispatcher/urls/";
224 };
225 };
226
227 "lomiri-polkit-agent" = {
228 description = "Lomiri Polkit agent";
229 wantedBy = [ lomiriService ];
230 after = [ lomiriService ];
231 partOf = [ lomiriService ];
232 serviceConfig = {
233 Type = "simple";
234 Restart = "always";
235 ExecStart = "${pkgs.lomiri.lomiri-polkit-agent}/libexec/lomiri-polkit-agent/policykit-agent";
236 };
237 };
238
239 "mediascanner-2.0" = {
240 description = "Media Scanner";
241 wantedBy = lomiriServiceNames;
242 before = lomiriServiceNames;
243 partOf = lomiriServiceNames;
244 serviceConfig = {
245 Type = "dbus";
246 BusName = "com.lomiri.MediaScanner2.Daemon";
247 Restart = "on-failure";
248 ExecStart = "${lib.getExe pkgs.lomiri.mediascanner2}";
249 };
250 };
251 };
252
253 systemd.services = {
254 "dbus-com.lomiri.UserMetrics" = {
255 serviceConfig =
256 {
257 Type = "dbus";
258 BusName = "com.lomiri.UserMetrics";
259 User = "usermetrics";
260 StandardOutput = "syslog";
261 SyslogIdentifier = "com.lomiri.UserMetrics";
262 ExecStart = "${pkgs.lomiri.libusermetrics}/libexec/libusermetrics/usermetricsservice";
263 }
264 // lib.optionalAttrs (!config.security.apparmor.enable) {
265 # Due to https://gitlab.com/ubports/development/core/libusermetrics/-/issues/8, auth must be disabled when not using AppArmor, lest the next database usage breaks
266 Environment = "USERMETRICS_NO_AUTH=1";
267 };
268 };
269 };
270
271 users.users.usermetrics = {
272 group = "usermetrics";
273 home = "/var/lib/usermetrics";
274 createHome = true;
275 isSystemUser = true;
276 };
277
278 users.groups.usermetrics = { };
279 })
280 ];
281
282 meta.maintainers = lib.teams.lomiri.members;
283}