at 23.11-pre 30 kB view raw
1{ config, lib, utils, pkgs, ... }: 2 3with lib; 4 5let 6 7 # Abbreviations. 8 cfg = config.services.xserver; 9 xorg = pkgs.xorg; 10 11 12 # Map video driver names to driver packages. FIXME: move into card-specific modules. 13 knownVideoDrivers = { 14 # Alias so people can keep using "virtualbox" instead of "vboxvideo". 15 virtualbox = { modules = [ xorg.xf86videovboxvideo ]; driverName = "vboxvideo"; }; 16 17 # Alias so that "radeon" uses the xf86-video-ati driver. 18 radeon = { modules = [ xorg.xf86videoati ]; driverName = "ati"; }; 19 20 # modesetting does not have a xf86videomodesetting package as it is included in xorgserver 21 modesetting = {}; 22 }; 23 24 fontsForXServer = 25 config.fonts.fonts ++ 26 # We don't want these fonts in fonts.conf, because then modern, 27 # fontconfig-based applications will get horrible bitmapped 28 # Helvetica fonts. It's better to get a substitution (like Nimbus 29 # Sans) than that horror. But we do need the Adobe fonts for some 30 # old non-fontconfig applications. (Possibly this could be done 31 # better using a fontconfig rule.) 32 [ pkgs.xorg.fontadobe100dpi 33 pkgs.xorg.fontadobe75dpi 34 ]; 35 36 xrandrOptions = { 37 output = mkOption { 38 type = types.str; 39 example = "DVI-0"; 40 description = lib.mdDoc '' 41 The output name of the monitor, as shown by 42 {manpage}`xrandr(1)` invoked without arguments. 43 ''; 44 }; 45 46 primary = mkOption { 47 type = types.bool; 48 default = false; 49 description = lib.mdDoc '' 50 Whether this head is treated as the primary monitor, 51 ''; 52 }; 53 54 monitorConfig = mkOption { 55 type = types.lines; 56 default = ""; 57 example = '' 58 DisplaySize 408 306 59 Option "DPMS" "false" 60 ''; 61 description = lib.mdDoc '' 62 Extra lines to append to the `Monitor` section 63 verbatim. Available options are documented in the MONITOR section in 64 {manpage}`xorg.conf(5)`. 65 ''; 66 }; 67 }; 68 69 # Just enumerate all heads without discarding XRandR output information. 70 xrandrHeads = let 71 mkHead = num: config: { 72 name = "multihead${toString num}"; 73 inherit config; 74 }; 75 in imap1 mkHead cfg.xrandrHeads; 76 77 xrandrDeviceSection = let 78 monitors = forEach xrandrHeads (h: '' 79 Option "monitor-${h.config.output}" "${h.name}" 80 ''); 81 in concatStrings monitors; 82 83 # Here we chain every monitor from the left to right, so we have: 84 # m4 right of m3 right of m2 right of m1 .----.----.----.----. 85 # Which will end up in reverse ----------> | m1 | m2 | m3 | m4 | 86 # `----^----^----^----' 87 xrandrMonitorSections = let 88 mkMonitor = previous: current: singleton { 89 inherit (current) name; 90 value = '' 91 Section "Monitor" 92 Identifier "${current.name}" 93 ${optionalString (current.config.primary) '' 94 Option "Primary" "true" 95 ''} 96 ${optionalString (previous != []) '' 97 Option "RightOf" "${(head previous).name}" 98 ''} 99 ${current.config.monitorConfig} 100 EndSection 101 ''; 102 } ++ previous; 103 monitors = reverseList (foldl mkMonitor [] xrandrHeads); 104 in concatMapStrings (getAttr "value") monitors; 105 106 configFile = pkgs.runCommand "xserver.conf" 107 { fontpath = optionalString (cfg.fontPath != null) 108 ''FontPath "${cfg.fontPath}"''; 109 inherit (cfg) config; 110 preferLocalBuild = true; 111 } 112 '' 113 echo 'Section "Files"' >> $out 114 echo $fontpath >> $out 115 116 for i in ${toString fontsForXServer}; do 117 if test "''${i:0:''${#NIX_STORE}}" == "$NIX_STORE"; then 118 for j in $(find $i -name fonts.dir); do 119 echo " FontPath \"$(dirname $j)\"" >> $out 120 done 121 fi 122 done 123 124 for i in $(find ${toString cfg.modules} -type d | sort); do 125 if test $(echo $i/*.so* | wc -w) -ne 0; then 126 echo " ModulePath \"$i\"" >> $out 127 fi 128 done 129 130 echo '${cfg.filesSection}' >> $out 131 echo 'EndSection' >> $out 132 echo >> $out 133 134 echo "$config" >> $out 135 ''; # */ 136 137 prefixStringLines = prefix: str: 138 concatMapStringsSep "\n" (line: prefix + line) (splitString "\n" str); 139 140 indent = prefixStringLines " "; 141 142 # A scalable variant of the X11 "core" cursor 143 # 144 # If not running a fancy desktop environment, the cursor is likely set to 145 # the default `cursor.pcf` bitmap font. This is 17px wide, so it's very 146 # small and almost invisible on 4K displays. 147 fontcursormisc_hidpi = pkgs.xorg.fontxfree86type1.overrideAttrs (old: 148 let 149 # The scaling constant is 230/96: the scalable `left_ptr` glyph at 150 # about 23 points is rendered as 17px, on a 96dpi display. 151 # Note: the XLFD font size is in decipoints. 152 size = 2.39583 * cfg.dpi; 153 sizeString = builtins.head (builtins.split "\\." (toString size)); 154 in 155 { 156 postInstall = '' 157 alias='cursor -xfree86-cursor-medium-r-normal--0-${sizeString}-0-0-p-0-adobe-fontspecific' 158 echo "$alias" > $out/lib/X11/fonts/Type1/fonts.alias 159 ''; 160 }); 161in 162 163{ 164 165 imports = 166 [ ./display-managers/default.nix 167 ./window-managers/default.nix 168 ./desktop-managers/default.nix 169 (mkRemovedOptionModule [ "services" "xserver" "startGnuPGAgent" ] 170 "See the 16.09 release notes for more information.") 171 (mkRemovedOptionModule 172 [ "services" "xserver" "startDbusSession" ] 173 "The user D-Bus session is now always socket activated and this option can safely be removed.") 174 (mkRemovedOptionModule [ "services" "xserver" "useXFS" ] 175 "Use services.xserver.fontPath instead of useXFS") 176 (mkRemovedOptionModule [ "services" "xserver" "useGlamor" ] 177 "Option services.xserver.useGlamor was removed because it is unnecessary. Drivers that uses Glamor will use it automatically.") 178 ]; 179 180 181 ###### interface 182 183 options = { 184 185 services.xserver = { 186 187 enable = mkOption { 188 type = types.bool; 189 default = false; 190 description = lib.mdDoc '' 191 Whether to enable the X server. 192 ''; 193 }; 194 195 autorun = mkOption { 196 type = types.bool; 197 default = true; 198 description = lib.mdDoc '' 199 Whether to start the X server automatically. 200 ''; 201 }; 202 203 excludePackages = mkOption { 204 default = []; 205 example = literalExpression "[ pkgs.xterm ]"; 206 type = types.listOf types.package; 207 description = lib.mdDoc "Which X11 packages to exclude from the default environment"; 208 }; 209 210 exportConfiguration = mkOption { 211 type = types.bool; 212 default = false; 213 description = lib.mdDoc '' 214 Whether to symlink the X server configuration under 215 {file}`/etc/X11/xorg.conf`. 216 ''; 217 }; 218 219 enableTCP = mkOption { 220 type = types.bool; 221 default = false; 222 description = lib.mdDoc '' 223 Whether to allow the X server to accept TCP connections. 224 ''; 225 }; 226 227 autoRepeatDelay = mkOption { 228 type = types.nullOr types.int; 229 default = null; 230 description = lib.mdDoc '' 231 Sets the autorepeat delay (length of time in milliseconds that a key must be depressed before autorepeat starts). 232 ''; 233 }; 234 235 autoRepeatInterval = mkOption { 236 type = types.nullOr types.int; 237 default = null; 238 description = lib.mdDoc '' 239 Sets the autorepeat interval (length of time in milliseconds that should elapse between autorepeat-generated keystrokes). 240 ''; 241 }; 242 243 inputClassSections = mkOption { 244 type = types.listOf types.lines; 245 default = []; 246 example = literalExpression '' 247 [ ''' 248 Identifier "Trackpoint Wheel Emulation" 249 MatchProduct "ThinkPad USB Keyboard with TrackPoint" 250 Option "EmulateWheel" "true" 251 Option "EmulateWheelButton" "2" 252 Option "Emulate3Buttons" "false" 253 ''' 254 ] 255 ''; 256 description = lib.mdDoc "Content of additional InputClass sections of the X server configuration file."; 257 }; 258 259 modules = mkOption { 260 type = types.listOf types.path; 261 default = []; 262 example = literalExpression "[ pkgs.xf86_input_wacom ]"; 263 description = lib.mdDoc "Packages to be added to the module search path of the X server."; 264 }; 265 266 resolutions = mkOption { 267 type = types.listOf types.attrs; 268 default = []; 269 example = [ { x = 1600; y = 1200; } { x = 1024; y = 786; } ]; 270 description = lib.mdDoc '' 271 The screen resolutions for the X server. The first element 272 is the default resolution. If this list is empty, the X 273 server will automatically configure the resolution. 274 ''; 275 }; 276 277 videoDrivers = mkOption { 278 type = types.listOf types.str; 279 default = [ "modesetting" "fbdev" ]; 280 example = [ 281 "nvidia" "nvidiaLegacy390" "nvidiaLegacy340" "nvidiaLegacy304" 282 "amdgpu-pro" 283 ]; 284 # TODO(@oxij): think how to easily add the rest, like those nvidia things 285 relatedPackages = concatLists 286 (mapAttrsToList (n: v: 287 optional (hasPrefix "xf86video" n) { 288 path = [ "xorg" n ]; 289 title = removePrefix "xf86video" n; 290 }) pkgs.xorg); 291 description = lib.mdDoc '' 292 The names of the video drivers the configuration 293 supports. They will be tried in order until one that 294 supports your card is found. 295 Don't combine those with "incompatible" OpenGL implementations, 296 e.g. free ones (mesa-based) with proprietary ones. 297 298 For unfree "nvidia*", the supported GPU lists are on 299 https://www.nvidia.com/object/unix.html 300 ''; 301 }; 302 303 videoDriver = mkOption { 304 type = types.nullOr types.str; 305 default = null; 306 example = "i810"; 307 description = lib.mdDoc '' 308 The name of the video driver for your graphics card. This 309 option is obsolete; please set the 310 {option}`services.xserver.videoDrivers` instead. 311 ''; 312 }; 313 314 drivers = mkOption { 315 type = types.listOf types.attrs; 316 internal = true; 317 description = lib.mdDoc '' 318 A list of attribute sets specifying drivers to be loaded by 319 the X11 server. 320 ''; 321 }; 322 323 dpi = mkOption { 324 type = types.nullOr types.int; 325 default = null; 326 description = lib.mdDoc '' 327 Force global DPI resolution to use for X server. It's recommended to 328 use this only when DPI is detected incorrectly; also consider using 329 `Monitor` section in configuration file instead. 330 ''; 331 }; 332 333 updateDbusEnvironment = mkOption { 334 type = types.bool; 335 default = false; 336 description = lib.mdDoc '' 337 Whether to update the DBus activation environment after launching the 338 desktop manager. 339 ''; 340 }; 341 342 layout = mkOption { 343 type = types.str; 344 default = "us"; 345 description = lib.mdDoc '' 346 Keyboard layout, or multiple keyboard layouts separated by commas. 347 ''; 348 }; 349 350 xkbModel = mkOption { 351 type = types.str; 352 default = "pc104"; 353 example = "presario"; 354 description = lib.mdDoc '' 355 Keyboard model. 356 ''; 357 }; 358 359 xkbOptions = mkOption { 360 type = types.commas; 361 default = "terminate:ctrl_alt_bksp"; 362 example = "grp:caps_toggle,grp_led:scroll"; 363 description = lib.mdDoc '' 364 X keyboard options; layout switching goes here. 365 ''; 366 }; 367 368 xkbVariant = mkOption { 369 type = types.str; 370 default = ""; 371 example = "colemak"; 372 description = lib.mdDoc '' 373 X keyboard variant. 374 ''; 375 }; 376 377 xkbDir = mkOption { 378 type = types.path; 379 default = "${pkgs.xkeyboard_config}/etc/X11/xkb"; 380 defaultText = literalExpression ''"''${pkgs.xkeyboard_config}/etc/X11/xkb"''; 381 description = lib.mdDoc '' 382 Path used for -xkbdir xserver parameter. 383 ''; 384 }; 385 386 config = mkOption { 387 type = types.lines; 388 description = lib.mdDoc '' 389 The contents of the configuration file of the X server 390 ({file}`xorg.conf`). 391 392 This option is set by multiple modules, and the configs are 393 concatenated together. 394 395 In Xorg configs the last config entries take precedence, 396 so you may want to use `lib.mkAfter` on this option 397 to override NixOS's defaults. 398 ''; 399 }; 400 401 filesSection = mkOption { 402 type = types.lines; 403 default = ""; 404 example = ''FontPath "/path/to/my/fonts"''; 405 description = lib.mdDoc "Contents of the first `Files` section of the X server configuration file."; 406 }; 407 408 deviceSection = mkOption { 409 type = types.lines; 410 default = ""; 411 example = "VideoRAM 131072"; 412 description = lib.mdDoc "Contents of the first Device section of the X server configuration file."; 413 }; 414 415 screenSection = mkOption { 416 type = types.lines; 417 default = ""; 418 example = '' 419 Option "RandRRotation" "on" 420 ''; 421 description = lib.mdDoc "Contents of the first Screen section of the X server configuration file."; 422 }; 423 424 monitorSection = mkOption { 425 type = types.lines; 426 default = ""; 427 example = "HorizSync 28-49"; 428 description = lib.mdDoc "Contents of the first Monitor section of the X server configuration file."; 429 }; 430 431 extraConfig = mkOption { 432 type = types.lines; 433 default = ""; 434 description = lib.mdDoc "Additional contents (sections) included in the X server configuration file"; 435 }; 436 437 xrandrHeads = mkOption { 438 default = []; 439 example = [ 440 "HDMI-0" 441 { output = "DVI-0"; primary = true; } 442 { output = "DVI-1"; monitorConfig = "Option \"Rotate\" \"left\""; } 443 ]; 444 type = with types; listOf (coercedTo str (output: { 445 inherit output; 446 }) (submodule { options = xrandrOptions; })); 447 # Set primary to true for the first head if no other has been set 448 # primary already. 449 apply = heads: let 450 hasPrimary = any (x: x.primary) heads; 451 firstPrimary = head heads // { primary = true; }; 452 newHeads = singleton firstPrimary ++ tail heads; 453 in if heads != [] && !hasPrimary then newHeads else heads; 454 description = lib.mdDoc '' 455 Multiple monitor configuration, just specify a list of XRandR 456 outputs. The individual elements should be either simple strings or 457 an attribute set of output options. 458 459 If the element is a string, it is denoting the physical output for a 460 monitor, if it's an attribute set, you must at least provide the 461 {option}`output` option. 462 463 The monitors will be mapped from left to right in the order of the 464 list. 465 466 By default, the first monitor will be set as the primary monitor if 467 none of the elements contain an option that has set 468 {option}`primary` to `true`. 469 470 ::: {.note} 471 Only one monitor is allowed to be primary. 472 ::: 473 474 Be careful using this option with multiple graphic adapters or with 475 drivers that have poor support for XRandR, unexpected things might 476 happen with those. 477 ''; 478 }; 479 480 serverFlagsSection = mkOption { 481 default = ""; 482 type = types.lines; 483 example = 484 '' 485 Option "BlankTime" "0" 486 Option "StandbyTime" "0" 487 Option "SuspendTime" "0" 488 Option "OffTime" "0" 489 ''; 490 description = lib.mdDoc "Contents of the ServerFlags section of the X server configuration file."; 491 }; 492 493 moduleSection = mkOption { 494 type = types.lines; 495 default = ""; 496 example = 497 '' 498 SubSection "extmod" 499 EndSubsection 500 ''; 501 description = lib.mdDoc "Contents of the Module section of the X server configuration file."; 502 }; 503 504 serverLayoutSection = mkOption { 505 type = types.lines; 506 default = ""; 507 example = 508 '' 509 Option "AIGLX" "true" 510 ''; 511 description = lib.mdDoc "Contents of the ServerLayout section of the X server configuration file."; 512 }; 513 514 extraDisplaySettings = mkOption { 515 type = types.lines; 516 default = ""; 517 example = "Virtual 2048 2048"; 518 description = lib.mdDoc "Lines to be added to every Display subsection of the Screen section."; 519 }; 520 521 defaultDepth = mkOption { 522 type = types.int; 523 default = 0; 524 example = 8; 525 description = lib.mdDoc "Default colour depth."; 526 }; 527 528 fontPath = mkOption { 529 type = types.nullOr types.str; 530 default = null; 531 example = "unix/:7100"; 532 description = lib.mdDoc '' 533 Set the X server FontPath. Defaults to null, which 534 means the compiled in defaults will be used. See 535 man xorg.conf for details. 536 ''; 537 }; 538 539 tty = mkOption { 540 type = types.nullOr types.int; 541 default = 7; 542 description = lib.mdDoc "Virtual console for the X server."; 543 }; 544 545 display = mkOption { 546 type = types.nullOr types.int; 547 default = 0; 548 description = lib.mdDoc "Display number for the X server."; 549 }; 550 551 virtualScreen = mkOption { 552 type = types.nullOr types.attrs; 553 default = null; 554 example = { x = 2048; y = 2048; }; 555 description = lib.mdDoc '' 556 Virtual screen size for Xrandr. 557 ''; 558 }; 559 560 logFile = mkOption { 561 type = types.nullOr types.str; 562 default = "/dev/null"; 563 example = "/var/log/Xorg.0.log"; 564 description = lib.mdDoc '' 565 Controls the file Xorg logs to. 566 567 The default of `/dev/null` is set so that systemd services (like `displayManagers`) only log to the journal and don't create their own log files. 568 569 Setting this to `null` will not pass the `-logfile` argument to Xorg which allows it to log to its default logfile locations instead (see `man Xorg`). You probably only want this behaviour when running Xorg manually (e.g. via `startx`). 570 ''; 571 }; 572 573 verbose = mkOption { 574 type = types.nullOr types.int; 575 default = 3; 576 example = 7; 577 description = lib.mdDoc '' 578 Controls verbosity of X logging. 579 ''; 580 }; 581 582 enableCtrlAltBackspace = mkOption { 583 type = types.bool; 584 default = false; 585 description = lib.mdDoc '' 586 Whether to enable the DontZap option, which binds Ctrl+Alt+Backspace 587 to forcefully kill X. This can lead to data loss and is disabled 588 by default. 589 ''; 590 }; 591 592 terminateOnReset = mkOption { 593 type = types.bool; 594 default = true; 595 description = lib.mdDoc '' 596 Whether to terminate X upon server reset. 597 ''; 598 }; 599 600 upscaleDefaultCursor = mkOption { 601 type = types.bool; 602 default = false; 603 description = lib.mdDoc '' 604 Upscale the default X cursor to be more visible on high-density displays. 605 Requires `config.services.xserver.dpi` to be set. 606 ''; 607 }; 608 }; 609 610 }; 611 612 613 614 ###### implementation 615 616 config = mkIf cfg.enable { 617 618 services.xserver.displayManager.lightdm.enable = 619 let dmConf = cfg.displayManager; 620 default = !(dmConf.gdm.enable 621 || dmConf.sddm.enable 622 || dmConf.xpra.enable 623 || dmConf.sx.enable 624 || dmConf.startx.enable 625 || config.services.greetd.enable); 626 in mkIf (default) (mkDefault true); 627 628 # so that the service won't be enabled when only startx is used 629 systemd.services.display-manager.enable = 630 let dmConf = cfg.displayManager; 631 noDmUsed = !(dmConf.gdm.enable 632 || dmConf.sddm.enable 633 || dmConf.xpra.enable 634 || dmConf.lightdm.enable); 635 in mkIf (noDmUsed) (mkDefault false); 636 637 hardware.opengl.enable = mkDefault true; 638 639 services.xserver.videoDrivers = mkIf (cfg.videoDriver != null) [ cfg.videoDriver ]; 640 641 # FIXME: somehow check for unknown driver names. 642 services.xserver.drivers = flip concatMap cfg.videoDrivers (name: 643 let driver = 644 attrByPath [name] 645 (if xorg ? ${"xf86video" + name} 646 then { modules = [xorg.${"xf86video" + name}]; } 647 else null) 648 knownVideoDrivers; 649 in optional (driver != null) ({ inherit name; modules = []; driverName = name; display = true; } // driver)); 650 651 assertions = [ 652 (let primaryHeads = filter (x: x.primary) cfg.xrandrHeads; in { 653 assertion = length primaryHeads < 2; 654 message = "Only one head is allowed to be primary in " 655 + "services.xserver.xrandrHeads, but there are " 656 + "${toString (length primaryHeads)} heads set to primary: " 657 + concatMapStringsSep ", " (x: x.output) primaryHeads; 658 }) 659 { 660 assertion = cfg.upscaleDefaultCursor -> cfg.dpi != null; 661 message = "Specify `config.services.xserver.dpi` to upscale the default cursor."; 662 } 663 ]; 664 665 environment.etc = 666 (optionalAttrs cfg.exportConfiguration 667 { 668 "X11/xorg.conf".source = "${configFile}"; 669 # -xkbdir command line option does not seems to be passed to xkbcomp. 670 "X11/xkb".source = "${cfg.xkbDir}"; 671 }) 672 # localectl looks into 00-keyboard.conf 673 //{ 674 "X11/xorg.conf.d/00-keyboard.conf".text = '' 675 Section "InputClass" 676 Identifier "Keyboard catchall" 677 MatchIsKeyboard "on" 678 Option "XkbModel" "${cfg.xkbModel}" 679 Option "XkbLayout" "${cfg.layout}" 680 Option "XkbOptions" "${cfg.xkbOptions}" 681 Option "XkbVariant" "${cfg.xkbVariant}" 682 EndSection 683 ''; 684 } 685 # Needed since 1.18; see https://bugs.freedesktop.org/show_bug.cgi?id=89023#c5 686 // (let cfgPath = "/X11/xorg.conf.d/10-evdev.conf"; in 687 { 688 ${cfgPath}.source = xorg.xf86inputevdev.out + "/share" + cfgPath; 689 }); 690 691 environment.systemPackages = utils.removePackagesByName 692 [ xorg.xorgserver.out 693 xorg.xrandr 694 xorg.xrdb 695 xorg.setxkbmap 696 xorg.iceauth # required for KDE applications (it's called by dcopserver) 697 xorg.xlsclients 698 xorg.xset 699 xorg.xsetroot 700 xorg.xinput 701 xorg.xprop 702 xorg.xauth 703 pkgs.xterm 704 pkgs.xdg-utils 705 xorg.xf86inputevdev.out # get evdev.4 man page 706 pkgs.nixos-icons # needed for gnome and pantheon about dialog, nixos-manual and maybe more 707 ] config.services.xserver.excludePackages 708 ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh; 709 710 environment.pathsToLink = [ "/share/X11" ]; 711 712 xdg = { 713 autostart.enable = true; 714 menus.enable = true; 715 mime.enable = true; 716 icons.enable = true; 717 }; 718 719 # The default max inotify watches is 8192. 720 # Nowadays most apps require a good number of inotify watches, 721 # the value below is used by default on several other distros. 722 boot.kernel.sysctl."fs.inotify.max_user_instances" = mkDefault 524288; 723 boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288; 724 725 systemd.defaultUnit = mkIf cfg.autorun "graphical.target"; 726 727 systemd.services.display-manager = 728 { description = "X11 Server"; 729 730 after = [ "acpid.service" "systemd-logind.service" "systemd-user-sessions.service" ]; 731 732 restartIfChanged = false; 733 734 environment = 735 optionalAttrs config.hardware.opengl.setLdLibraryPath 736 { LD_LIBRARY_PATH = lib.makeLibraryPath [ pkgs.addOpenGLRunpath.driverLink ]; } 737 // cfg.displayManager.job.environment; 738 739 preStart = 740 '' 741 ${cfg.displayManager.job.preStart} 742 743 rm -f /tmp/.X0-lock 744 ''; 745 746 # TODO: move declaring the systemd service to its own mkIf 747 script = mkIf (config.systemd.services.display-manager.enable == true) "${cfg.displayManager.job.execCmd}"; 748 749 # Stop restarting if the display manager stops (crashes) 2 times 750 # in one minute. Starting X typically takes 3-4s. 751 startLimitIntervalSec = 30; 752 startLimitBurst = 3; 753 serviceConfig = { 754 Restart = "always"; 755 RestartSec = "200ms"; 756 SyslogIdentifier = "display-manager"; 757 }; 758 }; 759 760 services.xserver.displayManager.xserverArgs = 761 [ "-config ${configFile}" 762 "-xkbdir" "${cfg.xkbDir}" 763 ] ++ optional (cfg.display != null) ":${toString cfg.display}" 764 ++ optional (cfg.tty != null) "vt${toString cfg.tty}" 765 ++ optional (cfg.dpi != null) "-dpi ${toString cfg.dpi}" 766 ++ optional (cfg.logFile != null) "-logfile ${toString cfg.logFile}" 767 ++ optional (cfg.verbose != null) "-verbose ${toString cfg.verbose}" 768 ++ optional (!cfg.enableTCP) "-nolisten tcp" 769 ++ optional (cfg.autoRepeatDelay != null) "-ardelay ${toString cfg.autoRepeatDelay}" 770 ++ optional (cfg.autoRepeatInterval != null) "-arinterval ${toString cfg.autoRepeatInterval}" 771 ++ optional cfg.terminateOnReset "-terminate"; 772 773 services.xserver.modules = 774 concatLists (catAttrs "modules" cfg.drivers) ++ 775 [ xorg.xorgserver.out 776 xorg.xf86inputevdev.out 777 ]; 778 779 system.checks = singleton (pkgs.runCommand "xkb-validated" { 780 inherit (cfg) xkbModel layout xkbVariant xkbOptions; 781 nativeBuildInputs = with pkgs.buildPackages; [ xkbvalidate ]; 782 preferLocalBuild = true; 783 } '' 784 ${optionalString (config.environment.sessionVariables ? XKB_CONFIG_ROOT) 785 "export XKB_CONFIG_ROOT=${config.environment.sessionVariables.XKB_CONFIG_ROOT}" 786 } 787 xkbvalidate "$xkbModel" "$layout" "$xkbVariant" "$xkbOptions" 788 touch "$out" 789 ''); 790 791 services.xserver.config = 792 '' 793 Section "ServerFlags" 794 Option "AllowMouseOpenFail" "on" 795 Option "DontZap" "${if cfg.enableCtrlAltBackspace then "off" else "on"}" 796 ${indent cfg.serverFlagsSection} 797 EndSection 798 799 Section "Module" 800 ${indent cfg.moduleSection} 801 EndSection 802 803 Section "Monitor" 804 Identifier "Monitor[0]" 805 ${indent cfg.monitorSection} 806 EndSection 807 808 # Additional "InputClass" sections 809 ${flip (concatMapStringsSep "\n") cfg.inputClassSections (inputClassSection: '' 810 Section "InputClass" 811 ${indent inputClassSection} 812 EndSection 813 '')} 814 815 816 Section "ServerLayout" 817 Identifier "Layout[all]" 818 ${indent cfg.serverLayoutSection} 819 # Reference the Screen sections for each driver. This will 820 # cause the X server to try each in turn. 821 ${flip concatMapStrings (filter (d: d.display) cfg.drivers) (d: '' 822 Screen "Screen-${d.name}[0]" 823 '')} 824 EndSection 825 826 # For each supported driver, add a "Device" and "Screen" 827 # section. 828 ${flip concatMapStrings cfg.drivers (driver: '' 829 830 Section "Device" 831 Identifier "Device-${driver.name}[0]" 832 Driver "${driver.driverName or driver.name}" 833 ${indent cfg.deviceSection} 834 ${indent (driver.deviceSection or "")} 835 ${indent xrandrDeviceSection} 836 EndSection 837 ${optionalString driver.display '' 838 839 Section "Screen" 840 Identifier "Screen-${driver.name}[0]" 841 Device "Device-${driver.name}[0]" 842 ${optionalString (cfg.monitorSection != "") '' 843 Monitor "Monitor[0]" 844 ''} 845 846 ${indent cfg.screenSection} 847 ${indent (driver.screenSection or "")} 848 849 ${optionalString (cfg.defaultDepth != 0) '' 850 DefaultDepth ${toString cfg.defaultDepth} 851 ''} 852 853 ${optionalString 854 ( 855 driver.name != "virtualbox" 856 && 857 (cfg.resolutions != [] || 858 cfg.extraDisplaySettings != "" || 859 cfg.virtualScreen != null 860 ) 861 ) 862 (let 863 f = depth: 864 '' 865 SubSection "Display" 866 Depth ${toString depth} 867 ${optionalString (cfg.resolutions != []) 868 "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"} 869 ${indent cfg.extraDisplaySettings} 870 ${optionalString (cfg.virtualScreen != null) 871 "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"} 872 EndSubSection 873 ''; 874 in concatMapStrings f [8 16 24] 875 )} 876 877 EndSection 878 ''} 879 '')} 880 881 ${xrandrMonitorSections} 882 883 ${cfg.extraConfig} 884 ''; 885 886 fonts.enableDefaultFonts = mkDefault true; 887 fonts.fonts = [ 888 (if cfg.upscaleDefaultCursor then fontcursormisc_hidpi else pkgs.xorg.fontcursormisc) 889 pkgs.xorg.fontmiscmisc 890 ]; 891 892 }; 893 894 # uses relatedPackages 895 meta.buildDocsInSandbox = false; 896}