nixos/preload: init
[NixPkgs.git] / nixos / modules / services / x11 / desktop-managers / plasma5.nix
bloba177299bb32b27857fcc9a95720d384dfc78c9a0
1 { config, lib, pkgs, utils, ... }:
3 let
4   xcfg = config.services.xserver;
5   cfg = xcfg.desktopManager.plasma5;
7   # Use only for **internal** options.
8   # This is not exactly user-friendly.
9   kdeConfigurationType = with types;
10     let
11       valueTypes = (oneOf [
12         bool
13         float
14         int
15         str
16       ]) // {
17         description = "KDE Configuration value";
18         emptyValue.value = "";
19       };
20       set = (nullOr (lazyAttrsOf valueTypes)) // {
21         description = "KDE Configuration set";
22         emptyValue.value = {};
23       };
24     in (lazyAttrsOf set) // {
25         description = "KDE Configuration file";
26         emptyValue.value = {};
27       };
29   libsForQt5 = pkgs.plasma5Packages;
30   inherit (libsForQt5) kdeGear kdeFrameworks plasma5;
31   inherit (lib)
32     getBin optionalAttrs optionalString literalExpression
33     mkRemovedOptionModule mkRenamedOptionModule
34     mkDefault mkIf mkMerge mkOption mkPackageOptionMD types;
36   activationScript = ''
37     ${set_XDG_CONFIG_HOME}
39     # The KDE icon cache is supposed to update itself automatically, but it uses
40     # the timestamp on the icon theme directory as a trigger. This doesn't work
41     # on NixOS because the timestamp never changes. As a workaround, delete the
42     # icon cache at login and session activation.
43     # See also: http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html
44     rm -fv $HOME/.cache/icon-cache.kcache
46     # xdg-desktop-settings generates this empty file but
47     # it makes kbuildsyscoca5 fail silently. To fix this
48     # remove that menu if it exists.
49     rm -fv ''${XDG_CONFIG_HOME}/menus/applications-merged/xdg-desktop-menu-dummy.menu
51     # Qt writes a weird â€˜libraryPath’ line to
52     # ~/.config/Trolltech.conf that causes the KDE plugin
53     # paths of previous KDE invocations to be searched.
54     # Obviously using mismatching KDE libraries is potentially
55     # disastrous, so here we nuke references to the Nix store
56     # in Trolltech.conf.  A better solution would be to stop
57     # Qt from doing this wackiness in the first place.
58     trolltech_conf="''${XDG_CONFIG_HOME}/Trolltech.conf"
59     if [ -e "$trolltech_conf" ]; then
60       ${getBin pkgs.gnused}/bin/sed -i "$trolltech_conf" -e '/nix\\store\|nix\/store/ d'
61     fi
63     # Remove the kbuildsyscoca5 cache. It will be regenerated
64     # immediately after. This is necessary for kbuildsyscoca5 to
65     # recognize that software that has been removed.
66     rm -fv $HOME/.cache/ksycoca*
68     ${libsForQt5.kservice}/bin/kbuildsycoca5
69   '';
71   set_XDG_CONFIG_HOME = ''
72     # Set the default XDG_CONFIG_HOME if it is unset.
73     # Per the XDG Base Directory Specification:
74     # https://specifications.freedesktop.org/basedir-spec/latest
75     # 1. Never export this variable! If it is unset, then child processes are
76     # expected to set the default themselves.
77     # 2. Contaminate / if $HOME is unset; do not check if $HOME is set.
78     XDG_CONFIG_HOME=''${XDG_CONFIG_HOME:-$HOME/.config}
79   '';
84   options = {
85     services.xserver.desktopManager.plasma5 = {
86       enable = mkOption {
87         type = types.bool;
88         default = false;
89         description = lib.mdDoc "Enable the Plasma 5 (KDE 5) desktop environment.";
90       };
92       phononBackend = mkOption {
93         type = types.enum [ "gstreamer" "vlc" ];
94         default = "vlc";
95         example = "gstreamer";
96         description = lib.mdDoc "Phonon audio backend to install.";
97       };
99       useQtScaling = mkOption {
100         type = types.bool;
101         default = false;
102         description = lib.mdDoc "Enable HiDPI scaling in Qt.";
103       };
105       runUsingSystemd = mkOption {
106         description = lib.mdDoc "Use systemd to manage the Plasma session";
107         type = types.bool;
108         default = true;
109       };
111       notoPackage = mkPackageOptionMD pkgs "Noto fonts" {
112         default = [ "noto-fonts" ];
113         example = "noto-fonts-lgc-plus";
114       };
116       # Internally allows configuring kdeglobals globally
117       kdeglobals = mkOption {
118         internal = true;
119         default = {};
120         type = kdeConfigurationType;
121       };
123       # Internally allows configuring kwin globally
124       kwinrc = mkOption {
125         internal = true;
126         default = {};
127         type = kdeConfigurationType;
128       };
130       mobile.enable = mkOption {
131         type = types.bool;
132         default = false;
133         description = lib.mdDoc ''
134           Enable support for running the Plasma Mobile shell.
135         '';
136       };
138       mobile.installRecommendedSoftware = mkOption {
139         type = types.bool;
140         default = true;
141         description = lib.mdDoc ''
142           Installs software recommended for use with Plasma Mobile, but which
143           is not strictly required for Plasma Mobile to run.
144         '';
145       };
147       bigscreen.enable = mkOption {
148         type = types.bool;
149         default = false;
150         description = lib.mdDoc ''
151           Enable support for running the Plasma Bigscreen session.
152         '';
153       };
154     };
155     environment.plasma5.excludePackages = mkOption {
156         description = lib.mdDoc "List of default packages to exclude from the configuration";
157         type = types.listOf types.package;
158         default = [];
159         example = literalExpression "[ pkgs.plasma5Packages.oxygen ]";
160       };
161   };
163   imports = [
164     (mkRemovedOptionModule [ "services" "xserver" "desktopManager" "plasma5" "enableQt4Support" ] "Phonon no longer supports Qt 4.")
165     (mkRemovedOptionModule [ "services" "xserver" "desktopManager" "plasma5" "supportDDC" ] "DDC/CI is no longer supported upstream.")
166     (mkRenamedOptionModule [ "services" "xserver" "desktopManager" "kde5" ] [ "services" "xserver" "desktopManager" "plasma5" ])
167     (mkRenamedOptionModule [ "services" "xserver" "desktopManager" "plasma5" "excludePackages" ] [ "environment" "plasma5" "excludePackages" ])
168   ];
170   config = mkMerge [
171     # Common Plasma dependencies
172     (mkIf (cfg.enable || cfg.mobile.enable || cfg.bigscreen.enable) {
174       security.wrappers = {
175         kwin_wayland = {
176           owner = "root";
177           group = "root";
178           capabilities = "cap_sys_nice+ep";
179           source = "${getBin plasma5.kwin}/bin/kwin_wayland";
180         };
181       } // optionalAttrs (!cfg.runUsingSystemd) {
182         start_kdeinit = {
183           setuid = true;
184           owner = "root";
185           group = "root";
186           source = "${getBin libsForQt5.kinit}/libexec/kf5/start_kdeinit";
187         };
188       };
190       environment.systemPackages =
191         with libsForQt5;
192         with plasma5; with kdeGear; with kdeFrameworks;
193         let
194           requiredPackages = [
195             frameworkintegration
196             kactivities
197             kauth
198             kcmutils
199             kconfig
200             kconfigwidgets
201             kcoreaddons
202             kdoctools
203             kdbusaddons
204             kdeclarative
205             kded
206             kdesu
207             kdnssd
208             kemoticons
209             kfilemetadata
210             kglobalaccel
211             kguiaddons
212             kiconthemes
213             kidletime
214             kimageformats
215             kinit
216             kirigami2 # In system profile for SDDM theme. TODO: wrapper.
217             kio
218             kjobwidgets
219             knewstuff
220             knotifications
221             knotifyconfig
222             kpackage
223             kparts
224             kpeople
225             krunner
226             kservice
227             ktextwidgets
228             kwallet
229             kwallet-pam
230             kwalletmanager
231             kwayland
232             kwayland-integration
233             kwidgetsaddons
234             kxmlgui
235             kxmlrpcclient
236             plasma-framework
237             solid
238             sonnet
239             threadweaver
241             breeze-qt5
242             kactivitymanagerd
243             kde-cli-tools
244             kdecoration
245             kdeplasma-addons
246             kgamma5
247             khotkeys
248             kscreen
249             kscreenlocker
250             kwayland
251             kwin
252             kwrited
253             libkscreen
254             libksysguard
255             milou
256             plasma-integration
257             polkit-kde-agent
259             plasma-desktop
260             plasma-workspace
261             plasma-workspace-wallpapers
263             oxygen-sounds
265             breeze-icons
266             pkgs.hicolor-icon-theme
268             kde-gtk-config
269             breeze-gtk
271             qtvirtualkeyboard
273             pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
274           ];
275           optionalPackages = [
276             pkgs.aha # needed by kinfocenter for fwupd support
277             plasma-browser-integration
278             konsole
279             oxygen
280             (lib.getBin qttools) # Expose qdbus in PATH
281           ];
282         in
283         requiredPackages
284         ++ utils.removePackagesByName optionalPackages config.environment.plasma5.excludePackages
286         # Phonon audio backend
287         ++ lib.optional (cfg.phononBackend == "gstreamer") libsForQt5.phonon-backend-gstreamer
288         ++ lib.optional (cfg.phononBackend == "vlc") libsForQt5.phonon-backend-vlc
290         # Optional hardware support features
291         ++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt pkgs.openobex pkgs.obexftp ]
292         ++ lib.optional config.networking.networkmanager.enable plasma-nm
293         ++ lib.optional config.hardware.pulseaudio.enable plasma-pa
294         ++ lib.optional config.services.pipewire.pulse.enable plasma-pa
295         ++ lib.optional config.powerManagement.enable powerdevil
296         ++ lib.optional config.services.colord.enable pkgs.colord-kde
297         ++ lib.optional config.services.hardware.bolt.enable pkgs.plasma5Packages.plasma-thunderbolt
298         ++ lib.optionals config.services.samba.enable [ kdenetwork-filesharing pkgs.samba ]
299         ++ lib.optional config.services.xserver.wacom.enable pkgs.wacomtablet
300         ++ lib.optional config.services.flatpak.enable flatpak-kcm;
302       # Extra services for D-Bus activation
303       services.dbus.packages = [
304         plasma5.kactivitymanagerd
305       ];
307       environment.pathsToLink = [
308         # FIXME: modules should link subdirs of `/share` rather than relying on this
309         "/share"
310       ];
312       environment.etc."X11/xkb".source = xcfg.xkb.dir;
314       environment.sessionVariables = {
315         PLASMA_USE_QT_SCALING = mkIf cfg.useQtScaling "1";
317         # Needed for things that depend on other store.kde.org packages to install correctly,
318         # notably Plasma look-and-feel packages (a.k.a. Global Themes)
319         #
320         # FIXME: this is annoyingly impure and should really be fixed at source level somehow,
321         # but kpackage is a library so we can't just wrap the one thing invoking it and be done.
322         # This also means things won't work for people not on Plasma, but at least this way it
323         # works for SOME people.
324         KPACKAGE_DEP_RESOLVERS_PATH = "${pkgs.plasma5Packages.frameworkintegration.out}/libexec/kf5/kpackagehandlers";
325       };
327       # Enable GTK applications to load SVG icons
328       services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
330       fonts.packages = with pkgs; [ cfg.notoPackage hack-font ];
331       fonts.fontconfig.defaultFonts = {
332         monospace = [ "Hack" "Noto Sans Mono" ];
333         sansSerif = [ "Noto Sans" ];
334         serif = [ "Noto Serif" ];
335       };
337       programs.ssh.askPassword = mkDefault "${plasma5.ksshaskpass.out}/bin/ksshaskpass";
339       # Enable helpful DBus services.
340       services.accounts-daemon.enable = true;
341       # when changing an account picture the accounts-daemon reads a temporary file containing the image which systemsettings5 may place under /tmp
342       systemd.services.accounts-daemon.serviceConfig.PrivateTmp = false;
343       services.power-profiles-daemon.enable = mkDefault true;
344       services.system-config-printer.enable = mkIf config.services.printing.enable (mkDefault true);
345       services.udisks2.enable = true;
346       services.upower.enable = config.powerManagement.enable;
347       services.xserver.libinput.enable = mkDefault true;
349       # Extra UDEV rules used by Solid
350       services.udev.packages = [
351         # libmtp has "bin", "dev", "out" outputs. UDEV rules file is in "out".
352         pkgs.libmtp.out
353         pkgs.media-player-info
354       ];
356       services.xserver.displayManager.sddm = {
357         theme = mkDefault "breeze";
358       };
360       security.pam.services.kde = { allowNullPassword = true; };
362       security.pam.services.login.enableKwallet = true;
364       systemd.user.services = {
365         plasma-early-setup = mkIf cfg.runUsingSystemd {
366           description = "Early Plasma setup";
367           wantedBy = [ "graphical-session-pre.target" ];
368           serviceConfig.Type = "oneshot";
369           script = activationScript;
370         };
371       };
373       xdg.portal.enable = true;
374       xdg.portal.extraPortals = [ plasma5.xdg-desktop-portal-kde ];
375       xdg.portal.configPackages = mkDefault [ plasma5.xdg-desktop-portal-kde ];
376       # xdg-desktop-portal-kde expects PipeWire to be running.
377       # This does not, by default, replace PulseAudio.
378       services.pipewire.enable = mkDefault true;
380       # Update the start menu for each user that is currently logged in
381       system.userActivationScripts.plasmaSetup = activationScript;
383       programs.firefox.nativeMessagingHosts.packages = [ pkgs.plasma5Packages.plasma-browser-integration ];
384     })
386     (mkIf (cfg.kwinrc != {}) {
387       environment.etc."xdg/kwinrc".text = lib.generators.toINI {} cfg.kwinrc;
388     })
390     (mkIf (cfg.kdeglobals != {}) {
391       environment.etc."xdg/kdeglobals".text = lib.generators.toINI {} cfg.kdeglobals;
392     })
394     # Plasma Desktop
395     (mkIf cfg.enable {
397       # Seed our configuration into nixos-generate-config
398       system.nixos-generate-config.desktopConfiguration = [
399         ''
400           # Enable the Plasma 5 Desktop Environment.
401           services.xserver.displayManager.sddm.enable = true;
402           services.xserver.desktopManager.plasma5.enable = true;
403         ''
404       ];
406       services.xserver.displayManager.sessionPackages = [ pkgs.libsForQt5.plasma5.plasma-workspace ];
407       # Default to be `plasma` (X11) instead of `plasmawayland`, since plasma wayland currently has
408       # many tiny bugs.
409       # See: https://github.com/NixOS/nixpkgs/issues/143272
410       services.xserver.displayManager.defaultSession = mkDefault "plasma";
412       environment.systemPackages =
413         with libsForQt5;
414         with plasma5; with kdeGear; with kdeFrameworks;
415         let
416           requiredPackages = [
417             ksystemstats
418             kinfocenter
419             kmenuedit
420             plasma-systemmonitor
421             spectacle
422             systemsettings
424             dolphin
425             dolphin-plugins
426             ffmpegthumbs
427             kdegraphics-thumbnailers
428             kde-inotify-survey
429             kio-admin
430             kio-extras
431           ];
432           optionalPackages = [
433             ark
434             elisa
435             gwenview
436             okular
437             khelpcenter
438             print-manager
439           ];
440       in requiredPackages ++ utils.removePackagesByName optionalPackages config.environment.plasma5.excludePackages;
442       systemd.user.services = {
443         plasma-run-with-systemd = {
444           description = "Run KDE Plasma via systemd";
445           wantedBy = [ "basic.target" ];
446           serviceConfig.Type = "oneshot";
447           script = ''
448             ${set_XDG_CONFIG_HOME}
450             ${kdeFrameworks.kconfig}/bin/kwriteconfig5 \
451               --file startkderc --group General --key systemdBoot ${lib.boolToString cfg.runUsingSystemd}
452           '';
453         };
454       };
455     })
457     # Plasma Mobile
458     (mkIf cfg.mobile.enable {
459       assertions = [
460         {
461           # The user interface breaks without NetworkManager
462           assertion = config.networking.networkmanager.enable;
463           message = "Plasma Mobile requires NetworkManager.";
464         }
465         {
466           # The user interface breaks without bluetooth
467           assertion = config.hardware.bluetooth.enable;
468           message = "Plasma Mobile requires Bluetooth.";
469         }
470         {
471           # The user interface breaks without pulse
472           assertion = config.hardware.pulseaudio.enable || (config.services.pipewire.enable && config.services.pipewire.pulse.enable);
473           message = "Plasma Mobile requires pulseaudio.";
474         }
475       ];
477       environment.systemPackages =
478         with libsForQt5;
479         with plasma5; with kdeApplications; with kdeFrameworks;
480         [
481           # Basic packages without which Plasma Mobile fails to work properly.
482           plasma-mobile
483           plasma-nano
484           pkgs.maliit-framework
485           pkgs.maliit-keyboard
486         ]
487         ++ lib.optionals (cfg.mobile.installRecommendedSoftware) (with libsForQt5.plasmaMobileGear;[
488           # Additional software made for Plasma Mobile.
489           alligator
490           angelfish
491           audiotube
492           calindori
493           kalk
494           kasts
495           kclock
496           keysmith
497           koko
498           krecorder
499           ktrip
500           kweather
501           plasma-dialer
502           plasma-phonebook
503           plasma-settings
504           spacebar
505         ])
506       ;
508       # The following services are needed or the UI is broken.
509       hardware.bluetooth.enable = true;
510       hardware.pulseaudio.enable = true;
511       networking.networkmanager.enable = true;
512       # Required for autorotate
513       hardware.sensor.iio.enable = lib.mkDefault true;
515       # Recommendations can be found here:
516       #  - https://invent.kde.org/plasma-mobile/plasma-phone-settings/-/tree/master/etc/xdg
517       # This configuration is the minimum required for Plasma Mobile to *work*.
518       services.xserver.desktopManager.plasma5 = {
519         kdeglobals = {
520           KDE = {
521             # This forces a numeric PIN for the lockscreen, which is the
522             # recommendation from upstream.
523             LookAndFeelPackage = lib.mkDefault "org.kde.plasma.phone";
524           };
525         };
526         kwinrc = {
527           "Wayland" = {
528             "InputMethod[$e]" = "/run/current-system/sw/share/applications/com.github.maliit.keyboard.desktop";
529             "VirtualKeyboardEnabled" = "true";
530           };
531           "org.kde.kdecoration2" = {
532             # No decorations (title bar)
533             NoPlugin = lib.mkDefault "true";
534           };
535         };
536       };
538       services.xserver.displayManager.sessionPackages = [ pkgs.libsForQt5.plasma5.plasma-mobile ];
539     })
541     # Plasma Bigscreen
542     (mkIf cfg.bigscreen.enable {
543       environment.systemPackages =
544         with pkgs.plasma5Packages;
545         [
546           plasma-nano
547           plasma-settings
548           plasma-bigscreen
549           plasma-remotecontrollers
551           aura-browser
552           plank-player
554           plasma-pa
555           plasma-nm
556           kdeconnect-kde
557         ];
559       services.xserver.displayManager.sessionPackages = [ pkgs.plasma5Packages.plasma-bigscreen ];
561       # required for plasma-remotecontrollers to work correctly
562       hardware.uinput.enable = true;
563     })
564   ];