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