1{ config, lib, pkgs, ... }:
2
3with lib;
4
5let
6
7 xcfg = config.services.xserver;
8 cfg = xcfg.desktopManager.plasma5;
9
10 libsForQt5 = pkgs.plasma5Packages;
11 inherit (libsForQt5) kdeGear kdeFrameworks plasma5;
12 inherit (pkgs) writeText;
13
14 pulseaudio = config.hardware.pulseaudio;
15 pactl = "${getBin pulseaudio.package}/bin/pactl";
16 startplasma-x11 = "${getBin plasma5.plasma-workspace}/bin/startplasma-x11";
17 sed = "${getBin pkgs.gnused}/bin/sed";
18
19 gtkrc2 = writeText "gtkrc-2.0" ''
20 # Default GTK+ 2 config for NixOS Plasma 5
21 include "/run/current-system/sw/share/themes/Breeze/gtk-2.0/gtkrc"
22 style "user-font"
23 {
24 font_name="Sans Serif Regular"
25 }
26 widget_class "*" style "user-font"
27 gtk-font-name="Sans Serif Regular 10"
28 gtk-theme-name="Breeze"
29 gtk-icon-theme-name="breeze"
30 gtk-fallback-icon-theme="hicolor"
31 gtk-cursor-theme-name="breeze_cursors"
32 gtk-toolbar-style=GTK_TOOLBAR_ICONS
33 gtk-menu-images=1
34 gtk-button-images=1
35 '';
36
37 gtk3_settings = writeText "settings.ini" ''
38 [Settings]
39 gtk-font-name=Sans Serif Regular 10
40 gtk-theme-name=Breeze
41 gtk-icon-theme-name=breeze
42 gtk-fallback-icon-theme=hicolor
43 gtk-cursor-theme-name=breeze_cursors
44 gtk-toolbar-style=GTK_TOOLBAR_ICONS
45 gtk-menu-images=1
46 gtk-button-images=1
47 '';
48
49 kcminputrc = writeText "kcminputrc" ''
50 [Mouse]
51 cursorTheme=breeze_cursors
52 cursorSize=0
53 '';
54
55 activationScript = ''
56 ${set_XDG_CONFIG_HOME}
57
58 # The KDE icon cache is supposed to update itself automatically, but it uses
59 # the timestamp on the icon theme directory as a trigger. This doesn't work
60 # on NixOS because the timestamp never changes. As a workaround, delete the
61 # icon cache at login and session activation.
62 # See also: http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html
63 rm -fv $HOME/.cache/icon-cache.kcache
64
65 # xdg-desktop-settings generates this empty file but
66 # it makes kbuildsyscoca5 fail silently. To fix this
67 # remove that menu if it exists.
68 rm -fv ''${XDG_CONFIG_HOME}/menus/applications-merged/xdg-desktop-menu-dummy.menu
69
70 # Qt writes a weird ‘libraryPath’ line to
71 # ~/.config/Trolltech.conf that causes the KDE plugin
72 # paths of previous KDE invocations to be searched.
73 # Obviously using mismatching KDE libraries is potentially
74 # disastrous, so here we nuke references to the Nix store
75 # in Trolltech.conf. A better solution would be to stop
76 # Qt from doing this wackiness in the first place.
77 trolltech_conf="''${XDG_CONFIG_HOME}/Trolltech.conf"
78 if [ -e "$trolltech_conf" ]; then
79 ${sed} -i "$trolltech_conf" -e '/nix\\store\|nix\/store/ d'
80 fi
81
82 # Remove the kbuildsyscoca5 cache. It will be regenerated
83 # immediately after. This is necessary for kbuildsyscoca5 to
84 # recognize that software that has been removed.
85 rm -fv $HOME/.cache/ksycoca*
86
87 ${libsForQt5.kservice}/bin/kbuildsycoca5
88 '';
89
90 set_XDG_CONFIG_HOME = ''
91 # Set the default XDG_CONFIG_HOME if it is unset.
92 # Per the XDG Base Directory Specification:
93 # https://specifications.freedesktop.org/basedir-spec/latest
94 # 1. Never export this variable! If it is unset, then child processes are
95 # expected to set the default themselves.
96 # 2. Contaminate / if $HOME is unset; do not check if $HOME is set.
97 XDG_CONFIG_HOME=''${XDG_CONFIG_HOME:-$HOME/.config}
98 '';
99
100 startplasma =
101 ''
102 ${set_XDG_CONFIG_HOME}
103 mkdir -p "''${XDG_CONFIG_HOME}"
104
105 ''
106 + optionalString pulseaudio.enable ''
107 # Load PulseAudio module for routing support.
108 # See also: http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
109 ${pactl} load-module module-device-manager "do_routing=1"
110
111 ''
112 + ''
113 ${activationScript}
114
115 # Create default configurations if Plasma has never been started.
116 kdeglobals="''${XDG_CONFIG_HOME}/kdeglobals"
117 if ! [ -f "$kdeglobals" ]
118 then
119 kcminputrc="''${XDG_CONFIG_HOME}/kcminputrc"
120 if ! [ -f "$kcminputrc" ]
121 then
122 cat ${kcminputrc} >"$kcminputrc"
123 fi
124
125 gtkrc2="$HOME/.gtkrc-2.0"
126 if ! [ -f "$gtkrc2" ]
127 then
128 cat ${gtkrc2} >"$gtkrc2"
129 fi
130
131 gtk3_settings="''${XDG_CONFIG_HOME}/gtk-3.0/settings.ini"
132 if ! [ -f "$gtk3_settings" ]
133 then
134 mkdir -p "$(dirname "$gtk3_settings")"
135 cat ${gtk3_settings} >"$gtk3_settings"
136 fi
137 fi
138
139 ''
140 + ''
141 exec "${startplasma-x11}"
142 '';
143
144in
145
146{
147 options = {
148
149 services.xserver.desktopManager.plasma5 = {
150 enable = mkOption {
151 type = types.bool;
152 default = false;
153 description = "Enable the Plasma 5 (KDE 5) desktop environment.";
154 };
155
156 phononBackend = mkOption {
157 type = types.enum [ "gstreamer" "vlc" ];
158 default = "gstreamer";
159 example = "vlc";
160 description = "Phonon audio backend to install.";
161 };
162
163 supportDDC = mkOption {
164 type = types.bool;
165 default = false;
166 description = ''
167 Support setting monitor brightness via DDC.
168 </para>
169 <para>
170 This is not needed for controlling brightness of the internal monitor
171 of a laptop and as it is considered experimental by upstream, it is
172 disabled by default.
173 '';
174 };
175 };
176
177 };
178
179 imports = [
180 (mkRemovedOptionModule [ "services" "xserver" "desktopManager" "plasma5" "enableQt4Support" ] "Phonon no longer supports Qt 4.")
181 (mkRenamedOptionModule [ "services" "xserver" "desktopManager" "kde5" ] [ "services" "xserver" "desktopManager" "plasma5" ])
182 ];
183
184 config = mkMerge [
185 (mkIf cfg.enable {
186 # Seed our configuration into nixos-generate-config
187 system.nixos-generate-config.desktopConfiguration = [''
188 # Enable the Plasma 5 Desktop Environment.
189 services.xserver.displayManager.sddm.enable = true;
190 services.xserver.desktopManager.plasma5.enable = true;
191 ''];
192
193 services.xserver.desktopManager.session = singleton {
194 name = "plasma5";
195 bgSupport = true;
196 start = startplasma;
197 };
198
199 security.wrappers = {
200 kcheckpass.source = "${lib.getBin libsForQt5.kscreenlocker}/libexec/kcheckpass";
201 start_kdeinit.source = "${lib.getBin libsForQt5.kinit}/libexec/kf5/start_kdeinit";
202 kwin_wayland = {
203 source = "${lib.getBin plasma5.kwin}/bin/kwin_wayland";
204 capabilities = "cap_sys_nice+ep";
205 };
206 };
207
208 # DDC support
209 boot.kernelModules = lib.optional cfg.supportDDC "i2c_dev";
210 services.udev.extraRules = lib.optionalString cfg.supportDDC ''
211 KERNEL=="i2c-[0-9]*", TAG+="uaccess"
212 '';
213
214 environment.systemPackages =
215 with libsForQt5;
216 with plasma5; with kdeGear; with kdeFrameworks;
217 [
218 frameworkintegration
219 kactivities
220 kauth
221 kcmutils
222 kconfig
223 kconfigwidgets
224 kcoreaddons
225 kdoctools
226 kdbusaddons
227 kdeclarative
228 kded
229 kdesu
230 kdnssd
231 kemoticons
232 kfilemetadata
233 kglobalaccel
234 kguiaddons
235 kiconthemes
236 kidletime
237 kimageformats
238 kinit
239 kirigami2 # In system profile for SDDM theme. TODO: wrapper.
240 kio
241 kjobwidgets
242 knewstuff
243 knotifications
244 knotifyconfig
245 kpackage
246 kparts
247 kpeople
248 krunner
249 kservice
250 ktextwidgets
251 kwallet
252 kwallet-pam
253 kwalletmanager
254 kwayland
255 kwidgetsaddons
256 kxmlgui
257 kxmlrpcclient
258 plasma-framework
259 solid
260 sonnet
261 threadweaver
262
263 breeze-qt5
264 kactivitymanagerd
265 kde-cli-tools
266 kdecoration
267 kdeplasma-addons
268 kgamma5
269 khotkeys
270 kinfocenter
271 kmenuedit
272 kscreen
273 kscreenlocker
274 ksysguard
275 kwayland
276 kwin
277 kwrited
278 libkscreen
279 libksysguard
280 milou
281 plasma-browser-integration
282 plasma-integration
283 polkit-kde-agent
284 spectacle
285 systemsettings
286
287 plasma-desktop
288 plasma-workspace
289 plasma-workspace-wallpapers
290
291 dolphin
292 dolphin-plugins
293 ffmpegthumbs
294 kdegraphics-thumbnailers
295 khelpcenter
296 kio-extras
297 konsole
298 oxygen
299 print-manager
300
301 breeze-icons
302 pkgs.hicolor-icon-theme
303
304 kde-gtk-config breeze-gtk
305
306 qtvirtualkeyboard
307
308 pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
309 ]
310
311 # Phonon audio backend
312 ++ lib.optional (cfg.phononBackend == "gstreamer") libsForQt5.phonon-backend-gstreamer
313 ++ lib.optional (cfg.phononBackend == "vlc") libsForQt5.phonon-backend-vlc
314
315 # Optional hardware support features
316 ++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt pkgs.openobex pkgs.obexftp ]
317 ++ lib.optional config.networking.networkmanager.enable plasma-nm
318 ++ lib.optional config.hardware.pulseaudio.enable plasma-pa
319 ++ lib.optional config.services.pipewire.pulse.enable plasma-pa
320 ++ lib.optional config.powerManagement.enable powerdevil
321 ++ lib.optional config.services.colord.enable pkgs.colord-kde
322 ++ lib.optionals config.services.samba.enable [ kdenetwork-filesharing pkgs.samba ]
323 ++ lib.optional config.services.xserver.wacom.enable pkgs.wacomtablet;
324
325 environment.pathsToLink = [
326 # FIXME: modules should link subdirs of `/share` rather than relying on this
327 "/share"
328 ];
329
330 environment.etc."X11/xkb".source = xcfg.xkbDir;
331
332 # Enable GTK applications to load SVG icons
333 services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
334
335 fonts.fonts = with pkgs; [ noto-fonts hack-font ];
336 fonts.fontconfig.defaultFonts = {
337 monospace = [ "Hack" "Noto Sans Mono" ];
338 sansSerif = [ "Noto Sans" ];
339 serif = [ "Noto Serif" ];
340 };
341
342 programs.ssh.askPassword = mkDefault "${plasma5.ksshaskpass.out}/bin/ksshaskpass";
343
344 # Enable helpful DBus services.
345 services.udisks2.enable = true;
346 services.upower.enable = config.powerManagement.enable;
347 services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
348 services.xserver.libinput.enable = mkDefault true;
349
350 # Extra UDEV rules used by Solid
351 services.udev.packages = [
352 pkgs.libmtp
353 pkgs.media-player-info
354 ];
355
356 services.xserver.displayManager.sddm = {
357 theme = mkDefault "breeze";
358 };
359
360 security.pam.services.kde = { allowNullPassword = true; };
361
362 # Doing these one by one seems silly, but we currently lack a better
363 # construct for handling common pam configs.
364 security.pam.services.gdm.enableKwallet = true;
365 security.pam.services.kdm.enableKwallet = true;
366 security.pam.services.lightdm.enableKwallet = true;
367 security.pam.services.sddm.enableKwallet = true;
368
369 xdg.portal.enable = true;
370 xdg.portal.extraPortals = [ plasma5.xdg-desktop-portal-kde ];
371
372 # Update the start menu for each user that is currently logged in
373 system.userActivationScripts.plasmaSetup = activationScript;
374
375 nixpkgs.config.firefox.enablePlasmaBrowserIntegration = true;
376 })
377 ];
378
379}