{ config, lib, pkgs, ... }: with lib; let xcfg = config.services.xserver; cfg = xcfg.desktopManager.plasma5; libsForQt5 = pkgs.plasma5Packages; inherit (libsForQt5) kdeGear kdeFrameworks plasma5; inherit (pkgs) writeText; pulseaudio = config.hardware.pulseaudio; pactl = "${getBin pulseaudio.package}/bin/pactl"; startplasma-x11 = "${getBin plasma5.plasma-workspace}/bin/startplasma-x11"; sed = "${getBin pkgs.gnused}/bin/sed"; gtkrc2 = writeText "gtkrc-2.0" '' # Default GTK+ 2 config for NixOS Plasma 5 include "/run/current-system/sw/share/themes/Breeze/gtk-2.0/gtkrc" style "user-font" { font_name="Sans Serif Regular" } widget_class "*" style "user-font" gtk-font-name="Sans Serif Regular 10" gtk-theme-name="Breeze" gtk-icon-theme-name="breeze" gtk-fallback-icon-theme="hicolor" gtk-cursor-theme-name="breeze_cursors" gtk-toolbar-style=GTK_TOOLBAR_ICONS gtk-menu-images=1 gtk-button-images=1 ''; gtk3_settings = writeText "settings.ini" '' [Settings] gtk-font-name=Sans Serif Regular 10 gtk-theme-name=Breeze gtk-icon-theme-name=breeze gtk-fallback-icon-theme=hicolor gtk-cursor-theme-name=breeze_cursors gtk-toolbar-style=GTK_TOOLBAR_ICONS gtk-menu-images=1 gtk-button-images=1 ''; kcminputrc = writeText "kcminputrc" '' [Mouse] cursorTheme=breeze_cursors cursorSize=0 ''; activationScript = '' ${set_XDG_CONFIG_HOME} # The KDE icon cache is supposed to update itself automatically, but it uses # the timestamp on the icon theme directory as a trigger. This doesn't work # on NixOS because the timestamp never changes. As a workaround, delete the # icon cache at login and session activation. # See also: http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html rm -fv $HOME/.cache/icon-cache.kcache # xdg-desktop-settings generates this empty file but # it makes kbuildsyscoca5 fail silently. To fix this # remove that menu if it exists. rm -fv ''${XDG_CONFIG_HOME}/menus/applications-merged/xdg-desktop-menu-dummy.menu # Qt writes a weird ‘libraryPath’ line to # ~/.config/Trolltech.conf that causes the KDE plugin # paths of previous KDE invocations to be searched. # Obviously using mismatching KDE libraries is potentially # disastrous, so here we nuke references to the Nix store # in Trolltech.conf. A better solution would be to stop # Qt from doing this wackiness in the first place. trolltech_conf="''${XDG_CONFIG_HOME}/Trolltech.conf" if [ -e "$trolltech_conf" ]; then ${sed} -i "$trolltech_conf" -e '/nix\\store\|nix\/store/ d' fi # Remove the kbuildsyscoca5 cache. It will be regenerated # immediately after. This is necessary for kbuildsyscoca5 to # recognize that software that has been removed. rm -fv $HOME/.cache/ksycoca* ${libsForQt5.kservice}/bin/kbuildsycoca5 ''; set_XDG_CONFIG_HOME = '' # Set the default XDG_CONFIG_HOME if it is unset. # Per the XDG Base Directory Specification: # https://specifications.freedesktop.org/basedir-spec/latest # 1. Never export this variable! If it is unset, then child processes are # expected to set the default themselves. # 2. Contaminate / if $HOME is unset; do not check if $HOME is set. XDG_CONFIG_HOME=''${XDG_CONFIG_HOME:-$HOME/.config} ''; startplasma = '' ${set_XDG_CONFIG_HOME} mkdir -p "''${XDG_CONFIG_HOME}" '' + optionalString pulseaudio.enable '' # Load PulseAudio module for routing support. # See also: http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/ ${pactl} load-module module-device-manager "do_routing=1" '' + '' ${activationScript} # Create default configurations if Plasma has never been started. kdeglobals="''${XDG_CONFIG_HOME}/kdeglobals" if ! [ -f "$kdeglobals" ] then kcminputrc="''${XDG_CONFIG_HOME}/kcminputrc" if ! [ -f "$kcminputrc" ] then cat ${kcminputrc} >"$kcminputrc" fi gtkrc2="$HOME/.gtkrc-2.0" if ! [ -f "$gtkrc2" ] then cat ${gtkrc2} >"$gtkrc2" fi gtk3_settings="''${XDG_CONFIG_HOME}/gtk-3.0/settings.ini" if ! [ -f "$gtk3_settings" ] then mkdir -p "$(dirname "$gtk3_settings")" cat ${gtk3_settings} >"$gtk3_settings" fi fi '' + '' exec "${startplasma-x11}" ''; in { options = { services.xserver.desktopManager.plasma5 = { enable = mkOption { type = types.bool; default = false; description = "Enable the Plasma 5 (KDE 5) desktop environment."; }; phononBackend = mkOption { type = types.enum [ "gstreamer" "vlc" ]; default = "gstreamer"; example = "vlc"; description = "Phonon audio backend to install."; }; supportDDC = mkOption { type = types.bool; default = false; description = '' Support setting monitor brightness via DDC. This is not needed for controlling brightness of the internal monitor of a laptop and as it is considered experimental by upstream, it is disabled by default. ''; }; }; }; imports = [ (mkRemovedOptionModule [ "services" "xserver" "desktopManager" "plasma5" "enableQt4Support" ] "Phonon no longer supports Qt 4.") (mkRenamedOptionModule [ "services" "xserver" "desktopManager" "kde5" ] [ "services" "xserver" "desktopManager" "plasma5" ]) ]; config = mkMerge [ (mkIf cfg.enable { # Seed our configuration into nixos-generate-config system.nixos-generate-config.desktopConfiguration = ['' # Enable the Plasma 5 Desktop Environment. services.xserver.displayManager.sddm.enable = true; services.xserver.desktopManager.plasma5.enable = true; '']; services.xserver.desktopManager.session = singleton { name = "plasma5"; bgSupport = true; start = startplasma; }; security.wrappers = { kcheckpass.source = "${lib.getBin libsForQt5.kscreenlocker}/libexec/kcheckpass"; start_kdeinit.source = "${lib.getBin libsForQt5.kinit}/libexec/kf5/start_kdeinit"; kwin_wayland = { source = "${lib.getBin plasma5.kwin}/bin/kwin_wayland"; capabilities = "cap_sys_nice+ep"; }; }; # DDC support boot.kernelModules = lib.optional cfg.supportDDC "i2c_dev"; services.udev.extraRules = lib.optionalString cfg.supportDDC '' KERNEL=="i2c-[0-9]*", TAG+="uaccess" ''; environment.systemPackages = with libsForQt5; with plasma5; with kdeGear; with kdeFrameworks; [ frameworkintegration kactivities kauth kcmutils kconfig kconfigwidgets kcoreaddons kdoctools kdbusaddons kdeclarative kded kdesu kdnssd kemoticons kfilemetadata kglobalaccel kguiaddons kiconthemes kidletime kimageformats kinit kirigami2 # In system profile for SDDM theme. TODO: wrapper. kio kjobwidgets knewstuff knotifications knotifyconfig kpackage kparts kpeople krunner kservice ktextwidgets kwallet kwallet-pam kwalletmanager kwayland kwidgetsaddons kxmlgui kxmlrpcclient plasma-framework solid sonnet threadweaver breeze-qt5 kactivitymanagerd kde-cli-tools kdecoration kdeplasma-addons kgamma5 khotkeys kinfocenter kmenuedit kscreen kscreenlocker ksysguard kwayland kwin kwrited libkscreen libksysguard milou plasma-browser-integration plasma-integration polkit-kde-agent spectacle systemsettings plasma-desktop plasma-workspace plasma-workspace-wallpapers dolphin dolphin-plugins ffmpegthumbs kdegraphics-thumbnailers khelpcenter kio-extras konsole oxygen print-manager breeze-icons pkgs.hicolor-icon-theme kde-gtk-config breeze-gtk qtvirtualkeyboard pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/ ] # Phonon audio backend ++ lib.optional (cfg.phononBackend == "gstreamer") libsForQt5.phonon-backend-gstreamer ++ lib.optional (cfg.phononBackend == "vlc") libsForQt5.phonon-backend-vlc # Optional hardware support features ++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt pkgs.openobex pkgs.obexftp ] ++ lib.optional config.networking.networkmanager.enable plasma-nm ++ lib.optional config.hardware.pulseaudio.enable plasma-pa ++ lib.optional config.services.pipewire.pulse.enable plasma-pa ++ lib.optional config.powerManagement.enable powerdevil ++ lib.optional config.services.colord.enable pkgs.colord-kde ++ lib.optionals config.services.samba.enable [ kdenetwork-filesharing pkgs.samba ] ++ lib.optional config.services.xserver.wacom.enable pkgs.wacomtablet; environment.pathsToLink = [ # FIXME: modules should link subdirs of `/share` rather than relying on this "/share" ]; environment.etc."X11/xkb".source = xcfg.xkbDir; # Enable GTK applications to load SVG icons services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ]; fonts.fonts = with pkgs; [ noto-fonts hack-font ]; fonts.fontconfig.defaultFonts = { monospace = [ "Hack" "Noto Sans Mono" ]; sansSerif = [ "Noto Sans" ]; serif = [ "Noto Serif" ]; }; programs.ssh.askPassword = mkDefault "${plasma5.ksshaskpass.out}/bin/ksshaskpass"; # Enable helpful DBus services. services.udisks2.enable = true; services.upower.enable = config.powerManagement.enable; services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true)); services.xserver.libinput.enable = mkDefault true; # Extra UDEV rules used by Solid services.udev.packages = [ pkgs.libmtp pkgs.media-player-info ]; services.xserver.displayManager.sddm = { theme = mkDefault "breeze"; }; security.pam.services.kde = { allowNullPassword = true; }; # Doing these one by one seems silly, but we currently lack a better # construct for handling common pam configs. security.pam.services.gdm.enableKwallet = true; security.pam.services.kdm.enableKwallet = true; security.pam.services.lightdm.enableKwallet = true; security.pam.services.sddm.enableKwallet = true; xdg.portal.enable = true; xdg.portal.extraPortals = [ plasma5.xdg-desktop-portal-kde ]; # Update the start menu for each user that is currently logged in system.userActivationScripts.plasmaSetup = activationScript; nixpkgs.config.firefox.enablePlasmaBrowserIntegration = true; }) ]; }