at 16.09-beta 20 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 35 # Just enumerate all heads without discarding XRandR output information. 36 xrandrHeads = let 37 mkHead = num: output: { 38 name = "multihead${toString num}"; 39 inherit output; 40 }; 41 in imap mkHead cfg.xrandrHeads; 42 43 xrandrDeviceSection = let 44 monitors = flip map xrandrHeads (h: '' 45 Option "monitor-${h.output}" "${h.name}" 46 ''); 47 # First option is indented through the space in the config but any 48 # subsequent options aren't so we need to apply indentation to 49 # them here 50 monitorsIndented = if length monitors > 1 51 then singleton (head monitors) ++ map (m: " " + m) (tail monitors) 52 else monitors; 53 in concatStrings monitorsIndented; 54 55 # Here we chain every monitor from the left to right, so we have: 56 # m4 right of m3 right of m2 right of m1 .----.----.----.----. 57 # Which will end up in reverse ----------> | m1 | m2 | m3 | m4 | 58 # `----^----^----^----' 59 xrandrMonitorSections = let 60 mkMonitor = previous: current: singleton { 61 inherit (current) name; 62 value = '' 63 Section "Monitor" 64 Identifier "${current.name}" 65 ${optionalString (previous != []) '' 66 Option "RightOf" "${(head previous).name}" 67 ''} 68 EndSection 69 ''; 70 } ++ previous; 71 monitors = reverseList (foldl mkMonitor [] xrandrHeads); 72 in concatMapStrings (getAttr "value") monitors; 73 74 configFile = pkgs.stdenv.mkDerivation { 75 name = "xserver.conf"; 76 77 xfs = optionalString (cfg.useXFS != false) 78 ''FontPath "${toString cfg.useXFS}"''; 79 80 inherit (cfg) config; 81 82 buildCommand = 83 '' 84 echo 'Section "Files"' >> $out 85 echo $xfs >> $out 86 87 for i in ${toString fontsForXServer}; do 88 if test "''${i:0:''${#NIX_STORE}}" == "$NIX_STORE"; then 89 for j in $(find $i -name fonts.dir); do 90 echo " FontPath \"$(dirname $j)\"" >> $out 91 done 92 fi 93 done 94 95 for i in $(find ${toString cfg.modules} -type d); do 96 if test $(echo $i/*.so* | wc -w) -ne 0; then 97 echo " ModulePath \"$i\"" >> $out 98 fi 99 done 100 101 echo 'EndSection' >> $out 102 103 echo "$config" >> $out 104 ''; # */ 105 }; 106 107in 108 109{ 110 111 imports = 112 [ ./display-managers/default.nix 113 ./window-managers/default.nix 114 ./desktop-managers/default.nix 115 ]; 116 117 118 ###### interface 119 120 options = { 121 122 services.xserver = { 123 124 enable = mkOption { 125 type = types.bool; 126 default = false; 127 description = '' 128 Whether to enable the X server. 129 ''; 130 }; 131 132 autorun = mkOption { 133 type = types.bool; 134 default = true; 135 description = '' 136 Whether to start the X server automatically. 137 ''; 138 }; 139 140 exportConfiguration = mkOption { 141 type = types.bool; 142 default = false; 143 description = '' 144 Whether to symlink the X server configuration under 145 <filename>/etc/X11/xorg.conf</filename>. 146 ''; 147 }; 148 149 enableTCP = mkOption { 150 type = types.bool; 151 default = false; 152 description = '' 153 Whether to allow the X server to accept TCP connections. 154 ''; 155 }; 156 157 inputClassSections = mkOption { 158 type = types.listOf types.lines; 159 default = []; 160 example = literalExample '' 161 [ ''' 162 Identifier "Trackpoint Wheel Emulation" 163 MatchProduct "ThinkPad USB Keyboard with TrackPoint" 164 Option "EmulateWheel" "true" 165 Option "EmulateWheelButton" "2" 166 Option "Emulate3Buttons" "false" 167 ''' 168 ] 169 ''; 170 description = "Content of additional InputClass sections of the X server configuration file."; 171 }; 172 173 modules = mkOption { 174 type = types.listOf types.path; 175 default = []; 176 example = literalExample "[ pkgs.xf86_input_wacom ]"; 177 description = "Packages to be added to the module search path of the X server."; 178 }; 179 180 resolutions = mkOption { 181 type = types.listOf types.attrs; 182 default = []; 183 example = [ { x = 1600; y = 1200; } { x = 1024; y = 786; } ]; 184 description = '' 185 The screen resolutions for the X server. The first element 186 is the default resolution. If this list is empty, the X 187 server will automatically configure the resolution. 188 ''; 189 }; 190 191 videoDrivers = mkOption { 192 type = types.listOf types.str; 193 # !!! We'd like "nv" here, but it segfaults the X server. 194 default = [ "ati" "cirrus" "intel" "vesa" "vmware" "modesetting" ]; 195 example = [ "vesa" ]; 196 description = '' 197 The names of the video drivers the configuration 198 supports. They will be tried in order until one that 199 supports your card is found. 200 ''; 201 }; 202 203 videoDriver = mkOption { 204 type = types.nullOr types.str; 205 default = null; 206 example = "i810"; 207 description = '' 208 The name of the video driver for your graphics card. This 209 option is obsolete; please set the 210 <option>services.xserver.videoDrivers</option> instead. 211 ''; 212 }; 213 214 drivers = mkOption { 215 type = types.listOf types.attrs; 216 internal = true; 217 description = '' 218 A list of attribute sets specifying drivers to be loaded by 219 the X11 server. 220 ''; 221 }; 222 223 dpi = mkOption { 224 type = types.nullOr types.int; 225 default = null; 226 description = "DPI resolution to use for X server."; 227 }; 228 229 startDbusSession = mkOption { 230 type = types.bool; 231 default = true; 232 description = '' 233 Whether to start a new DBus session when you log in with dbus-launch. 234 ''; 235 }; 236 237 updateDbusEnvironment = mkOption { 238 type = types.bool; 239 default = false; 240 description = '' 241 Whether to update the DBus activation environment after launching the 242 desktop manager. 243 ''; 244 }; 245 246 layout = mkOption { 247 type = types.str; 248 default = "us"; 249 description = '' 250 Keyboard layout. 251 ''; 252 }; 253 254 xkbModel = mkOption { 255 type = types.str; 256 default = "pc104"; 257 example = "presario"; 258 description = '' 259 Keyboard model. 260 ''; 261 }; 262 263 xkbOptions = mkOption { 264 type = types.str; 265 default = "terminate:ctrl_alt_bksp"; 266 example = "grp:caps_toggle, grp_led:scroll"; 267 description = '' 268 X keyboard options; layout switching goes here. 269 ''; 270 }; 271 272 xkbVariant = mkOption { 273 type = types.str; 274 default = ""; 275 example = "colemak"; 276 description = '' 277 X keyboard variant. 278 ''; 279 }; 280 281 xkbDir = mkOption { 282 type = types.path; 283 description = '' 284 Path used for -xkbdir xserver parameter. 285 ''; 286 }; 287 288 config = mkOption { 289 type = types.lines; 290 description = '' 291 The contents of the configuration file of the X server 292 (<filename>xorg.conf</filename>). 293 ''; 294 }; 295 296 deviceSection = mkOption { 297 type = types.lines; 298 default = ""; 299 example = "VideoRAM 131072"; 300 description = "Contents of the first Device section of the X server configuration file."; 301 }; 302 303 screenSection = mkOption { 304 type = types.lines; 305 default = ""; 306 example = '' 307 Option "RandRRotation" "on" 308 ''; 309 description = "Contents of the first Screen section of the X server configuration file."; 310 }; 311 312 monitorSection = mkOption { 313 type = types.lines; 314 default = ""; 315 example = "HorizSync 28-49"; 316 description = "Contents of the first Monitor section of the X server configuration file."; 317 }; 318 319 xrandrHeads = mkOption { 320 default = []; 321 example = [ "HDMI-0" "DVI-0" ]; 322 type = with types; listOf string; 323 description = '' 324 Simple multiple monitor configuration, just specify a list of XRandR 325 outputs which will be mapped from left to right in the order of the 326 list. 327 328 Be careful using this option with multiple graphic adapters or with 329 drivers that have poor support for XRandR, unexpected things might 330 happen with those. 331 ''; 332 }; 333 334 serverFlagsSection = mkOption { 335 default = ""; 336 example = 337 '' 338 Option "BlankTime" "0" 339 Option "StandbyTime" "0" 340 Option "SuspendTime" "0" 341 Option "OffTime" "0" 342 ''; 343 description = "Contents of the ServerFlags section of the X server configuration file."; 344 }; 345 346 moduleSection = mkOption { 347 type = types.lines; 348 default = ""; 349 example = 350 '' 351 SubSection "extmod" 352 EndSubsection 353 ''; 354 description = "Contents of the Module section of the X server configuration file."; 355 }; 356 357 serverLayoutSection = mkOption { 358 type = types.lines; 359 default = ""; 360 example = 361 '' 362 Option "AIGLX" "true" 363 ''; 364 description = "Contents of the ServerLayout section of the X server configuration file."; 365 }; 366 367 extraDisplaySettings = mkOption { 368 type = types.lines; 369 default = ""; 370 example = "Virtual 2048 2048"; 371 description = "Lines to be added to every Display subsection of the Screen section."; 372 }; 373 374 defaultDepth = mkOption { 375 type = types.int; 376 default = 0; 377 example = 8; 378 description = "Default colour depth."; 379 }; 380 381 useXFS = mkOption { 382 # FIXME: what's the type of this option? 383 default = false; 384 example = "unix/:7100"; 385 description = "Determines how to connect to the X Font Server."; 386 }; 387 388 tty = mkOption { 389 type = types.nullOr types.int; 390 default = 7; 391 description = "Virtual console for the X server."; 392 }; 393 394 display = mkOption { 395 type = types.nullOr types.int; 396 default = 0; 397 description = "Display number for the X server."; 398 }; 399 400 virtualScreen = mkOption { 401 type = types.nullOr types.attrs; 402 default = null; 403 example = { x = 2048; y = 2048; }; 404 description = '' 405 Virtual screen size for Xrandr. 406 ''; 407 }; 408 409 useGlamor = mkOption { 410 type = types.bool; 411 default = false; 412 description = '' 413 Whether to use the Glamor module for 2D acceleration, 414 if possible. 415 ''; 416 }; 417 418 enableCtrlAltBackspace = mkOption { 419 type = types.bool; 420 default = false; 421 description = '' 422 Whether to enable the DontZap option, which binds Ctrl+Alt+Backspace 423 to forcefully kill X. This can lead to data loss and is disabled 424 by default. 425 ''; 426 }; 427 }; 428 429 }; 430 431 432 433 ###### implementation 434 435 config = mkIf cfg.enable { 436 437 hardware.opengl.enable = mkDefault true; 438 439 services.xserver.videoDrivers = mkIf (cfg.videoDriver != null) [ cfg.videoDriver ]; 440 441 # FIXME: somehow check for unknown driver names. 442 services.xserver.drivers = flip concatMap cfg.videoDrivers (name: 443 let driver = 444 attrByPath [name] 445 (if xorg ? ${"xf86video" + name} 446 then { modules = [xorg.${"xf86video" + name}]; } 447 else null) 448 knownVideoDrivers; 449 in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver)); 450 451 assertions = 452 [ { assertion = config.security.polkit.enable; 453 message = "X11 requires Polkit to be enabled (security.polkit.enable = true)."; 454 } 455 ]; 456 457 environment.etc = 458 (optionals cfg.exportConfiguration 459 [ { source = "${configFile}"; 460 target = "X11/xorg.conf"; 461 } 462 # -xkbdir command line option does not seems to be passed to xkbcomp. 463 { source = "${cfg.xkbDir}"; 464 target = "X11/xkb"; 465 } 466 ]) 467 # Needed since 1.18; see https://bugs.freedesktop.org/show_bug.cgi?id=89023#c5 468 ++ (let cfgPath = "/X11/xorg.conf.d/10-evdev.conf"; in 469 [{ 470 source = xorg.xf86inputevdev.out + "/share" + cfgPath; 471 target = cfgPath; 472 }] 473 ); 474 475 environment.systemPackages = 476 [ xorg.xorgserver.out 477 xorg.xrandr 478 xorg.xrdb 479 xorg.setxkbmap 480 xorg.iceauth # required for KDE applications (it's called by dcopserver) 481 xorg.xlsclients 482 xorg.xset 483 xorg.xsetroot 484 xorg.xinput 485 xorg.xprop 486 xorg.xauth 487 pkgs.xterm 488 pkgs.xdg_utils 489 xorg.xf86inputevdev.out # get evdev.4 man page 490 ] 491 ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh; 492 493 environment.pathsToLink = 494 [ "/etc/xdg" "/share/xdg" "/share/applications" "/share/icons" "/share/pixmaps" ]; 495 496 # The default max inotify watches is 8192. 497 # Nowadays most apps require a good number of inotify watches, 498 # the value below is used by default on several other distros. 499 boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288; 500 501 systemd.defaultUnit = mkIf cfg.autorun "graphical.target"; 502 503 systemd.services.display-manager = 504 { description = "X11 Server"; 505 506 after = [ "systemd-udev-settle.service" "local-fs.target" "acpid.service" "systemd-logind.service" ]; 507 508 restartIfChanged = false; 509 510 environment = 511 { 512 XKB_BINDIR = "${xorg.xkbcomp}/bin"; # Needed for the Xkb extension. 513 XORG_DRI_DRIVER_PATH = "/run/opengl-driver/lib/dri"; # !!! Depends on the driver selected at runtime. 514 LD_LIBRARY_PATH = concatStringsSep ":" ( 515 [ "${xorg.libX11.out}/lib" "${xorg.libXext.out}/lib" "/run/opengl-driver/lib" ] 516 ++ concatLists (catAttrs "libPath" cfg.drivers)); 517 } // cfg.displayManager.job.environment; 518 519 preStart = 520 '' 521 ${cfg.displayManager.job.preStart} 522 523 rm -f /tmp/.X0-lock 524 ''; 525 526 script = "${cfg.displayManager.job.execCmd}"; 527 528 serviceConfig = { 529 Restart = "always"; 530 RestartSec = "200ms"; 531 SyslogIdentifier = "display-manager"; 532 }; 533 }; 534 535 services.xserver.displayManager.xserverArgs = 536 [ "-terminate" 537 "-config ${configFile}" 538 "-xkbdir" "${cfg.xkbDir}" 539 # Log at the default verbosity level to stderr rather than /var/log/X.*.log. 540 "-verbose" "3" "-logfile" "/dev/null" 541 ] ++ optional (cfg.display != null) ":${toString cfg.display}" 542 ++ optional (cfg.tty != null) "vt${toString cfg.tty}" 543 ++ optional (cfg.dpi != null) "-dpi ${toString cfg.dpi}" 544 ++ optional (!cfg.enableTCP) "-nolisten tcp"; 545 546 services.xserver.modules = 547 concatLists (catAttrs "modules" cfg.drivers) ++ 548 [ xorg.xorgserver.out 549 xorg.xf86inputevdev.out 550 ]; 551 552 services.xserver.xkbDir = mkDefault "${pkgs.xkeyboard_config}/etc/X11/xkb"; 553 554 services.xserver.config = 555 '' 556 Section "ServerFlags" 557 Option "AllowMouseOpenFail" "on" 558 Option "DontZap" "${if cfg.enableCtrlAltBackspace then "off" else "on"}" 559 ${cfg.serverFlagsSection} 560 EndSection 561 562 Section "Module" 563 ${cfg.moduleSection} 564 EndSection 565 566 Section "Monitor" 567 Identifier "Monitor[0]" 568 ${cfg.monitorSection} 569 EndSection 570 571 Section "InputClass" 572 Identifier "Keyboard catchall" 573 MatchIsKeyboard "on" 574 Option "XkbRules" "base" 575 Option "XkbModel" "${cfg.xkbModel}" 576 Option "XkbLayout" "${cfg.layout}" 577 Option "XkbOptions" "${cfg.xkbOptions}" 578 Option "XkbVariant" "${cfg.xkbVariant}" 579 EndSection 580 581 # Additional "InputClass" sections 582 ${flip concatMapStrings cfg.inputClassSections (inputClassSection: '' 583 Section "InputClass" 584 ${inputClassSection} 585 EndSection 586 '')} 587 588 589 Section "ServerLayout" 590 Identifier "Layout[all]" 591 ${cfg.serverLayoutSection} 592 # Reference the Screen sections for each driver. This will 593 # cause the X server to try each in turn. 594 ${flip concatMapStrings cfg.drivers (d: '' 595 Screen "Screen-${d.name}[0]" 596 '')} 597 EndSection 598 599 ${if cfg.useGlamor then '' 600 Section "Module" 601 Load "dri2" 602 Load "glamoregl" 603 EndSection 604 '' else ""} 605 606 # For each supported driver, add a "Device" and "Screen" 607 # section. 608 ${flip concatMapStrings cfg.drivers (driver: '' 609 610 Section "Device" 611 Identifier "Device-${driver.name}[0]" 612 Driver "${driver.driverName or driver.name}" 613 ${if cfg.useGlamor then ''Option "AccelMethod" "glamor"'' else ""} 614 ${cfg.deviceSection} 615 ${xrandrDeviceSection} 616 EndSection 617 618 Section "Screen" 619 Identifier "Screen-${driver.name}[0]" 620 Device "Device-${driver.name}[0]" 621 ${optionalString (cfg.monitorSection != "") '' 622 Monitor "Monitor[0]" 623 ''} 624 625 ${cfg.screenSection} 626 627 ${optionalString (cfg.defaultDepth != 0) '' 628 DefaultDepth ${toString cfg.defaultDepth} 629 ''} 630 631 ${optionalString 632 (driver.name != "virtualbox" && 633 (cfg.resolutions != [] || 634 cfg.extraDisplaySettings != "" || 635 cfg.virtualScreen != null)) 636 (let 637 f = depth: 638 '' 639 SubSection "Display" 640 Depth ${toString depth} 641 ${optionalString (cfg.resolutions != []) 642 "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"} 643 ${cfg.extraDisplaySettings} 644 ${optionalString (cfg.virtualScreen != null) 645 "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"} 646 EndSubSection 647 ''; 648 in concatMapStrings f [8 16 24] 649 )} 650 651 EndSection 652 '')} 653 654 ${xrandrMonitorSections} 655 ''; 656 657 }; 658 659}