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