at 18.03-beta 25 kB view raw
1{ config, lib, pkgs, pkgs_i686, ... }: 2 3with lib; 4 5let 6 7 kernelPackages = config.boot.kernelPackages; 8 9 # Abbreviations. 10 cfg = config.services.xserver; 11 xorg = pkgs.xorg; 12 13 14 # Map video driver names to driver packages. FIXME: move into card-specific modules. 15 knownVideoDrivers = { 16 virtualbox = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; }; 17 18 # modesetting does not have a xf86videomodesetting package as it is included in xorgserver 19 modesetting = {}; 20 }; 21 22 fontsForXServer = 23 config.fonts.fonts ++ 24 # We don't want these fonts in fonts.conf, because then modern, 25 # fontconfig-based applications will get horrible bitmapped 26 # Helvetica fonts. It's better to get a substitution (like Nimbus 27 # Sans) than that horror. But we do need the Adobe fonts for some 28 # old non-fontconfig applications. (Possibly this could be done 29 # better using a fontconfig rule.) 30 [ pkgs.xorg.fontadobe100dpi 31 pkgs.xorg.fontadobe75dpi 32 ]; 33 34 xrandrOptions = { 35 output = mkOption { 36 type = types.str; 37 example = "DVI-0"; 38 description = '' 39 The output name of the monitor, as shown by <citerefentry> 40 <refentrytitle>xrandr</refentrytitle> 41 <manvolnum>1</manvolnum> 42 </citerefentry> 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 <literal>Monitor</literal> section 63 verbatim. 64 ''; 65 }; 66 }; 67 68 # Just enumerate all heads without discarding XRandR output information. 69 xrandrHeads = let 70 mkHead = num: config: { 71 name = "multihead${toString num}"; 72 inherit config; 73 }; 74 in imap1 mkHead cfg.xrandrHeads; 75 76 xrandrDeviceSection = let 77 monitors = flip map xrandrHeads (h: '' 78 Option "monitor-${h.config.output}" "${h.name}" 79 ''); 80 # First option is indented through the space in the config but any 81 # subsequent options aren't so we need to apply indentation to 82 # them here 83 monitorsIndented = if length monitors > 1 84 then singleton (head monitors) ++ map (m: " " + m) (tail monitors) 85 else monitors; 86 in concatStrings monitorsIndented; 87 88 # Here we chain every monitor from the left to right, so we have: 89 # m4 right of m3 right of m2 right of m1 .----.----.----.----. 90 # Which will end up in reverse ----------> | m1 | m2 | m3 | m4 | 91 # `----^----^----^----' 92 xrandrMonitorSections = let 93 mkMonitor = previous: current: singleton { 94 inherit (current) name; 95 value = '' 96 Section "Monitor" 97 Identifier "${current.name}" 98 ${optionalString (current.config.primary) '' 99 Option "Primary" "true" 100 ''} 101 ${optionalString (previous != []) '' 102 Option "RightOf" "${(head previous).name}" 103 ''} 104 ${current.config.monitorConfig} 105 EndSection 106 ''; 107 } ++ previous; 108 monitors = reverseList (foldl mkMonitor [] xrandrHeads); 109 in concatMapStrings (getAttr "value") monitors; 110 111 configFile = pkgs.runCommand "xserver.conf" 112 { xfs = optionalString (cfg.useXFS != false) 113 ''FontPath "${toString cfg.useXFS}"''; 114 inherit (cfg) config; 115 } 116 '' 117 echo 'Section "Files"' >> $out 118 echo $xfs >> $out 119 120 for i in ${toString fontsForXServer}; do 121 if test "''${i:0:''${#NIX_STORE}}" == "$NIX_STORE"; then 122 for j in $(find $i -name fonts.dir); do 123 echo " FontPath \"$(dirname $j)\"" >> $out 124 done 125 fi 126 done 127 128 for i in $(find ${toString cfg.modules} -type d); do 129 if test $(echo $i/*.so* | wc -w) -ne 0; then 130 echo " ModulePath \"$i\"" >> $out 131 fi 132 done 133 134 echo 'EndSection' >> $out 135 136 echo "$config" >> $out 137 ''; # */ 138 139in 140 141{ 142 143 imports = 144 [ ./display-managers/default.nix 145 ./window-managers/default.nix 146 ./desktop-managers/default.nix 147 ]; 148 149 150 ###### interface 151 152 options = { 153 154 services.xserver = { 155 156 enable = mkOption { 157 type = types.bool; 158 default = false; 159 description = '' 160 Whether to enable the X server. 161 ''; 162 }; 163 164 plainX = mkOption { 165 type = types.bool; 166 default = false; 167 description = '' 168 Whether the X11 session can be plain (without DM/WM) and 169 the Xsession script will be used as fallback or not. 170 ''; 171 }; 172 173 autorun = mkOption { 174 type = types.bool; 175 default = true; 176 description = '' 177 Whether to start the X server automatically. 178 ''; 179 }; 180 181 exportConfiguration = mkOption { 182 type = types.bool; 183 default = false; 184 description = '' 185 Whether to symlink the X server configuration under 186 <filename>/etc/X11/xorg.conf</filename>. 187 ''; 188 }; 189 190 enableTCP = mkOption { 191 type = types.bool; 192 default = false; 193 description = '' 194 Whether to allow the X server to accept TCP connections. 195 ''; 196 }; 197 198 autoRepeatDelay = mkOption { 199 type = types.nullOr types.int; 200 default = null; 201 description = '' 202 Sets the autorepeat delay (length of time in milliseconds that a key must be depressed before autorepeat starts). 203 ''; 204 }; 205 206 autoRepeatInterval = mkOption { 207 type = types.nullOr types.int; 208 default = null; 209 description = '' 210 Sets the autorepeat interval (length of time in milliseconds that should elapse between autorepeat-generated keystrokes). 211 ''; 212 }; 213 214 inputClassSections = mkOption { 215 type = types.listOf types.lines; 216 default = []; 217 example = literalExample '' 218 [ ''' 219 Identifier "Trackpoint Wheel Emulation" 220 MatchProduct "ThinkPad USB Keyboard with TrackPoint" 221 Option "EmulateWheel" "true" 222 Option "EmulateWheelButton" "2" 223 Option "Emulate3Buttons" "false" 224 ''' 225 ] 226 ''; 227 description = "Content of additional InputClass sections of the X server configuration file."; 228 }; 229 230 modules = mkOption { 231 type = types.listOf types.path; 232 default = []; 233 example = literalExample "[ pkgs.xf86_input_wacom ]"; 234 description = "Packages to be added to the module search path of the X server."; 235 }; 236 237 resolutions = mkOption { 238 type = types.listOf types.attrs; 239 default = []; 240 example = [ { x = 1600; y = 1200; } { x = 1024; y = 786; } ]; 241 description = '' 242 The screen resolutions for the X server. The first element 243 is the default resolution. If this list is empty, the X 244 server will automatically configure the resolution. 245 ''; 246 }; 247 248 videoDrivers = mkOption { 249 type = types.listOf types.str; 250 # !!! We'd like "nv" here, but it segfaults the X server. 251 default = [ "ati" "cirrus" "intel" "vesa" "vmware" "modesetting" ]; 252 example = [ "vesa" ]; 253 description = '' 254 The names of the video drivers the configuration 255 supports. They will be tried in order until one that 256 supports your card is found. 257 ''; 258 }; 259 260 videoDriver = mkOption { 261 type = types.nullOr types.str; 262 default = null; 263 example = "i810"; 264 description = '' 265 The name of the video driver for your graphics card. This 266 option is obsolete; please set the 267 <option>services.xserver.videoDrivers</option> instead. 268 ''; 269 }; 270 271 drivers = mkOption { 272 type = types.listOf types.attrs; 273 internal = true; 274 description = '' 275 A list of attribute sets specifying drivers to be loaded by 276 the X11 server. 277 ''; 278 }; 279 280 dpi = mkOption { 281 type = types.nullOr types.int; 282 default = null; 283 description = "DPI resolution to use for X server."; 284 }; 285 286 startDbusSession = mkOption { 287 type = types.bool; 288 default = true; 289 description = '' 290 Whether to start a new DBus session when you log in with dbus-launch. 291 ''; 292 }; 293 294 updateDbusEnvironment = mkOption { 295 type = types.bool; 296 default = false; 297 description = '' 298 Whether to update the DBus activation environment after launching the 299 desktop manager. 300 ''; 301 }; 302 303 layout = mkOption { 304 type = types.str; 305 default = "us"; 306 description = '' 307 Keyboard layout, or multiple keyboard layouts separated by commas. 308 ''; 309 }; 310 311 xkbModel = mkOption { 312 type = types.str; 313 default = "pc104"; 314 example = "presario"; 315 description = '' 316 Keyboard model. 317 ''; 318 }; 319 320 xkbOptions = mkOption { 321 type = types.str; 322 default = "terminate:ctrl_alt_bksp"; 323 example = "grp:caps_toggle, grp_led:scroll"; 324 description = '' 325 X keyboard options; layout switching goes here. 326 ''; 327 }; 328 329 xkbVariant = mkOption { 330 type = types.str; 331 default = ""; 332 example = "colemak"; 333 description = '' 334 X keyboard variant. 335 ''; 336 }; 337 338 xkbDir = mkOption { 339 type = types.path; 340 description = '' 341 Path used for -xkbdir xserver parameter. 342 ''; 343 }; 344 345 config = mkOption { 346 type = types.lines; 347 description = '' 348 The contents of the configuration file of the X server 349 (<filename>xorg.conf</filename>). 350 ''; 351 }; 352 353 deviceSection = mkOption { 354 type = types.lines; 355 default = ""; 356 example = "VideoRAM 131072"; 357 description = "Contents of the first Device section of the X server configuration file."; 358 }; 359 360 screenSection = mkOption { 361 type = types.lines; 362 default = ""; 363 example = '' 364 Option "RandRRotation" "on" 365 ''; 366 description = "Contents of the first Screen section of the X server configuration file."; 367 }; 368 369 monitorSection = mkOption { 370 type = types.lines; 371 default = ""; 372 example = "HorizSync 28-49"; 373 description = "Contents of the first Monitor section of the X server configuration file."; 374 }; 375 376 xrandrHeads = mkOption { 377 default = []; 378 example = [ 379 "HDMI-0" 380 { output = "DVI-0"; primary = true; } 381 { output = "DVI-1"; monitorConfig = "Option \"Rotate\" \"left\""; } 382 ]; 383 type = with types; listOf (coercedTo str (output: { 384 inherit output; 385 }) (submodule { options = xrandrOptions; })); 386 # Set primary to true for the first head if no other has been set 387 # primary already. 388 apply = heads: let 389 hasPrimary = any (x: x.primary) heads; 390 firstPrimary = head heads // { primary = true; }; 391 newHeads = singleton firstPrimary ++ tail heads; 392 in if heads != [] && !hasPrimary then newHeads else heads; 393 description = '' 394 Multiple monitor configuration, just specify a list of XRandR 395 outputs. The individual elements should be either simple strings or 396 an attribute set of output options. 397 398 If the element is a string, it is denoting the physical output for a 399 monitor, if it's an attribute set, you must at least provide the 400 <option>output</option> option. 401 402 The monitors will be mapped from left to right in the order of the 403 list. 404 405 By default, the first monitor will be set as the primary monitor if 406 none of the elements contain an option that has set 407 <option>primary</option> to <literal>true</literal>. 408 409 <note><para>Only one monitor is allowed to be primary.</para></note> 410 411 Be careful using this option with multiple graphic adapters or with 412 drivers that have poor support for XRandR, unexpected things might 413 happen with those. 414 ''; 415 }; 416 417 serverFlagsSection = mkOption { 418 default = ""; 419 example = 420 '' 421 Option "BlankTime" "0" 422 Option "StandbyTime" "0" 423 Option "SuspendTime" "0" 424 Option "OffTime" "0" 425 ''; 426 description = "Contents of the ServerFlags section of the X server configuration file."; 427 }; 428 429 moduleSection = mkOption { 430 type = types.lines; 431 default = ""; 432 example = 433 '' 434 SubSection "extmod" 435 EndSubsection 436 ''; 437 description = "Contents of the Module section of the X server configuration file."; 438 }; 439 440 serverLayoutSection = mkOption { 441 type = types.lines; 442 default = ""; 443 example = 444 '' 445 Option "AIGLX" "true" 446 ''; 447 description = "Contents of the ServerLayout section of the X server configuration file."; 448 }; 449 450 extraDisplaySettings = mkOption { 451 type = types.lines; 452 default = ""; 453 example = "Virtual 2048 2048"; 454 description = "Lines to be added to every Display subsection of the Screen section."; 455 }; 456 457 defaultDepth = mkOption { 458 type = types.int; 459 default = 0; 460 example = 8; 461 description = "Default colour depth."; 462 }; 463 464 useXFS = mkOption { 465 # FIXME: what's the type of this option? 466 default = false; 467 example = "unix/:7100"; 468 description = "Determines how to connect to the X Font Server."; 469 }; 470 471 tty = mkOption { 472 type = types.nullOr types.int; 473 default = 7; 474 description = "Virtual console for the X server."; 475 }; 476 477 display = mkOption { 478 type = types.nullOr types.int; 479 default = 0; 480 description = "Display number for the X server."; 481 }; 482 483 virtualScreen = mkOption { 484 type = types.nullOr types.attrs; 485 default = null; 486 example = { x = 2048; y = 2048; }; 487 description = '' 488 Virtual screen size for Xrandr. 489 ''; 490 }; 491 492 verbose = mkOption { 493 type = types.nullOr types.int; 494 default = 3; 495 example = 7; 496 description = '' 497 Controls verbosity of X logging. 498 ''; 499 }; 500 501 useGlamor = mkOption { 502 type = types.bool; 503 default = false; 504 description = '' 505 Whether to use the Glamor module for 2D acceleration, 506 if possible. 507 ''; 508 }; 509 510 enableCtrlAltBackspace = mkOption { 511 type = types.bool; 512 default = false; 513 description = '' 514 Whether to enable the DontZap option, which binds Ctrl+Alt+Backspace 515 to forcefully kill X. This can lead to data loss and is disabled 516 by default. 517 ''; 518 }; 519 520 terminateOnReset = mkOption { 521 type = types.bool; 522 default = true; 523 description = '' 524 Whether to terminate X upon server reset. 525 ''; 526 }; 527 }; 528 529 }; 530 531 532 533 ###### implementation 534 535 config = mkIf cfg.enable { 536 537 hardware.opengl.enable = mkDefault true; 538 539 services.xserver.videoDrivers = mkIf (cfg.videoDriver != null) [ cfg.videoDriver ]; 540 541 # FIXME: somehow check for unknown driver names. 542 services.xserver.drivers = flip concatMap cfg.videoDrivers (name: 543 let driver = 544 attrByPath [name] 545 (if xorg ? ${"xf86video" + name} 546 then { modules = [xorg.${"xf86video" + name}]; } 547 else null) 548 knownVideoDrivers; 549 in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver)); 550 551 nixpkgs.config = optionalAttrs (elem "vboxvideo" cfg.videoDrivers) { xorg.abiCompat = "1.18"; }; 552 553 assertions = [ 554 { assertion = config.security.polkit.enable; 555 message = "X11 requires Polkit to be enabled (security.polkit.enable = true)."; 556 } 557 (let primaryHeads = filter (x: x.primary) cfg.xrandrHeads; in { 558 assertion = length primaryHeads < 2; 559 message = "Only one head is allowed to be primary in " 560 + "services.xserver.xrandrHeads, but there are " 561 + "${toString (length primaryHeads)} heads set to primary: " 562 + concatMapStringsSep ", " (x: x.output) primaryHeads; 563 }) 564 { assertion = cfg.desktopManager.default == "none" && cfg.windowManager.default == "none" -> cfg.plainX; 565 message = "Either the desktop manager or the window manager shouldn't be `none`! " 566 + "To explicitly allow this, you can also set `services.xserver.plainX` to `true`. " 567 + "The `default` value looks for enabled WMs/DMs and select the first one."; 568 } 569 ]; 570 571 environment.etc = 572 (optionals cfg.exportConfiguration 573 [ { source = "${configFile}"; 574 target = "X11/xorg.conf"; 575 } 576 # -xkbdir command line option does not seems to be passed to xkbcomp. 577 { source = "${cfg.xkbDir}"; 578 target = "X11/xkb"; 579 } 580 ]) 581 # localectl looks into 00-keyboard.conf 582 ++ [ 583 { 584 text = '' 585 Section "InputClass" 586 Identifier "Keyboard catchall" 587 MatchIsKeyboard "on" 588 Option "XkbModel" "${cfg.xkbModel}" 589 Option "XkbLayout" "${cfg.layout}" 590 Option "XkbOptions" "${cfg.xkbOptions}" 591 Option "XkbVariant" "${cfg.xkbVariant}" 592 EndSection 593 ''; 594 target = "X11/xorg.conf.d/00-keyboard.conf"; 595 } 596 ] 597 # Needed since 1.18; see https://bugs.freedesktop.org/show_bug.cgi?id=89023#c5 598 ++ (let cfgPath = "/X11/xorg.conf.d/10-evdev.conf"; in 599 [{ 600 source = xorg.xf86inputevdev.out + "/share" + cfgPath; 601 target = cfgPath; 602 }] 603 ); 604 605 environment.systemPackages = 606 [ xorg.xorgserver.out 607 xorg.xrandr 608 xorg.xrdb 609 xorg.setxkbmap 610 xorg.iceauth # required for KDE applications (it's called by dcopserver) 611 xorg.xlsclients 612 xorg.xset 613 xorg.xsetroot 614 xorg.xinput 615 xorg.xprop 616 xorg.xauth 617 pkgs.xterm 618 pkgs.xdg_utils 619 xorg.xf86inputevdev.out # get evdev.4 man page 620 ] 621 ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh; 622 623 environment.pathsToLink = 624 [ "/etc/xdg" "/share/xdg" "/share/applications" "/share/icons" "/share/pixmaps" ]; 625 626 # The default max inotify watches is 8192. 627 # Nowadays most apps require a good number of inotify watches, 628 # the value below is used by default on several other distros. 629 boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288; 630 631 systemd.defaultUnit = mkIf cfg.autorun "graphical.target"; 632 633 systemd.services.display-manager = 634 { description = "X11 Server"; 635 636 after = [ "systemd-udev-settle.service" "local-fs.target" "acpid.service" "systemd-logind.service" ]; 637 wants = [ "systemd-udev-settle.service" ]; 638 639 restartIfChanged = false; 640 641 environment = 642 { 643 XORG_DRI_DRIVER_PATH = "/run/opengl-driver/lib/dri"; # !!! Depends on the driver selected at runtime. 644 LD_LIBRARY_PATH = concatStringsSep ":" ( 645 [ "${xorg.libX11.out}/lib" "${xorg.libXext.out}/lib" "/run/opengl-driver/lib" ] 646 ++ concatLists (catAttrs "libPath" cfg.drivers)); 647 } // cfg.displayManager.job.environment; 648 649 preStart = 650 '' 651 ${cfg.displayManager.job.preStart} 652 653 rm -f /tmp/.X0-lock 654 ''; 655 656 script = "${cfg.displayManager.job.execCmd}"; 657 658 serviceConfig = { 659 Restart = "always"; 660 RestartSec = "200ms"; 661 SyslogIdentifier = "display-manager"; 662 # Stop restarting if the display manager stops (crashes) 2 times 663 # in one minute. Starting X typically takes 3-4s. 664 StartLimitInterval = "30s"; 665 StartLimitBurst = "3"; 666 }; 667 }; 668 669 services.xserver.displayManager.xserverArgs = 670 [ "-config ${configFile}" 671 "-xkbdir" "${cfg.xkbDir}" 672 # Log at the default verbosity level to stderr rather than /var/log/X.*.log. 673 "-logfile" "/dev/null" 674 ] ++ optional (cfg.display != null) ":${toString cfg.display}" 675 ++ optional (cfg.tty != null) "vt${toString cfg.tty}" 676 ++ optional (cfg.dpi != null) "-dpi ${toString cfg.dpi}" 677 ++ optional (cfg.verbose != null) "-verbose ${toString cfg.verbose}" 678 ++ optional (!cfg.enableTCP) "-nolisten tcp" 679 ++ optional (cfg.autoRepeatDelay != null) "-ardelay ${toString cfg.autoRepeatDelay}" 680 ++ optional (cfg.autoRepeatInterval != null) "-arinterval ${toString cfg.autoRepeatInterval}" 681 ++ optional cfg.terminateOnReset "-terminate"; 682 683 services.xserver.modules = 684 concatLists (catAttrs "modules" cfg.drivers) ++ 685 [ xorg.xorgserver.out 686 xorg.xf86inputevdev.out 687 ]; 688 689 services.xserver.xkbDir = mkDefault "${pkgs.xkeyboard_config}/etc/X11/xkb"; 690 691 system.extraDependencies = singleton (pkgs.runCommand "xkb-validated" { 692 inherit (cfg) xkbModel layout xkbVariant xkbOptions; 693 nativeBuildInputs = [ pkgs.xkbvalidate ]; 694 } '' 695 validate "$xkbModel" "$layout" "$xkbVariant" "$xkbOptions" 696 touch "$out" 697 ''); 698 699 services.xserver.config = 700 '' 701 Section "ServerFlags" 702 Option "AllowMouseOpenFail" "on" 703 Option "DontZap" "${if cfg.enableCtrlAltBackspace then "off" else "on"}" 704 ${cfg.serverFlagsSection} 705 EndSection 706 707 Section "Module" 708 ${cfg.moduleSection} 709 EndSection 710 711 Section "Monitor" 712 Identifier "Monitor[0]" 713 ${cfg.monitorSection} 714 EndSection 715 716 # Additional "InputClass" sections 717 ${flip concatMapStrings cfg.inputClassSections (inputClassSection: '' 718 Section "InputClass" 719 ${inputClassSection} 720 EndSection 721 '')} 722 723 724 Section "ServerLayout" 725 Identifier "Layout[all]" 726 ${cfg.serverLayoutSection} 727 # Reference the Screen sections for each driver. This will 728 # cause the X server to try each in turn. 729 ${flip concatMapStrings cfg.drivers (d: '' 730 Screen "Screen-${d.name}[0]" 731 '')} 732 EndSection 733 734 ${if cfg.useGlamor then '' 735 Section "Module" 736 Load "dri2" 737 Load "glamoregl" 738 EndSection 739 '' else ""} 740 741 # For each supported driver, add a "Device" and "Screen" 742 # section. 743 ${flip concatMapStrings cfg.drivers (driver: '' 744 745 Section "Device" 746 Identifier "Device-${driver.name}[0]" 747 Driver "${driver.driverName or driver.name}" 748 ${if cfg.useGlamor then ''Option "AccelMethod" "glamor"'' else ""} 749 ${cfg.deviceSection} 750 ${xrandrDeviceSection} 751 EndSection 752 753 Section "Screen" 754 Identifier "Screen-${driver.name}[0]" 755 Device "Device-${driver.name}[0]" 756 ${optionalString (cfg.monitorSection != "") '' 757 Monitor "Monitor[0]" 758 ''} 759 760 ${cfg.screenSection} 761 762 ${optionalString (cfg.defaultDepth != 0) '' 763 DefaultDepth ${toString cfg.defaultDepth} 764 ''} 765 766 ${optionalString 767 (driver.name != "virtualbox" && 768 (cfg.resolutions != [] || 769 cfg.extraDisplaySettings != "" || 770 cfg.virtualScreen != null)) 771 (let 772 f = depth: 773 '' 774 SubSection "Display" 775 Depth ${toString depth} 776 ${optionalString (cfg.resolutions != []) 777 "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"} 778 ${cfg.extraDisplaySettings} 779 ${optionalString (cfg.virtualScreen != null) 780 "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"} 781 EndSubSection 782 ''; 783 in concatMapStrings f [8 16 24] 784 )} 785 786 EndSection 787 '')} 788 789 ${xrandrMonitorSections} 790 ''; 791 792 fonts.enableDefaultFonts = mkDefault true; 793 794 }; 795 796}