{config, pkgs, ...}: # TODO: this file need some make-up (Nicolas Pierron) with pkgs.lib; let kernelPackages = config.boot.kernelPackages; # List of font directories. fontDirectories = config.fonts.fonts; options = { services = { xserver = { enable = mkOption { default = false; description = " Whether to enable the X server. "; }; autorun = mkOption { default = true; description = " Switch to false to create upstart-job and configuration, but not run it automatically "; }; exportConfiguration = mkOption { default = false; description = " Create /etc/X11/xorg.conf and a file with environment variables "; }; tcpEnable = mkOption { default = false; description = " Whether to enable TCP socket for the X server. "; }; resolutions = mkOption { default = [{x = 1024; y = 768;} {x = 800; y = 600;} {x = 640; y = 480;}]; description = " The screen resolutions for the X server. The first element is the default resolution. "; }; videoDriver = mkOption { default = "vesa"; example = "i810"; description = " The name of the video driver for your graphics card. "; }; driSupport = mkOption { default = false; description = " Whether to enable accelerated OpenGL rendering through the Direct Rendering Interface (DRI). "; }; /* sessionType = mkOption { default = "gnome"; example = "xterm"; description = " The kind of session to start after login. Current possibilies are kde (which starts KDE), gnome (which starts gnome-terminal) and xterm (which starts xterm). "; }; windowManager = mkOption { default = ""; description = " This option selects the window manager. Available values are twm (extremely primitive), metacity, xmonad and compiz. If left empty, the determines the window manager, e.g., Metacity for Gnome, and kwm for KDE. "; }; sessionStarter = mkOption { example = "${pkgs.xterm}/bin/xterm -ls"; description = " The command executed after login and after the window manager has been started. Used if is empty. "; }; */ startSSHAgent = mkOption { default = true; description = " Whether to start the SSH agent when you log in. The SSH agent remembers private keys for you so that you don't have to type in passphrases every time you make an SSH connection. Use ssh-add to add a key to the agent. "; }; isClone = mkOption { default = true; example = false; description = " Whether to enable the X server clone mode for dual-head. "; }; synaptics = { enable = mkOption { default = false; example = true; description = " Whether to replace mouse with touchpad. "; }; dev = mkOption { default = "/dev/input/event0"; description = " Event device for Synaptics touchpad. "; }; minSpeed = mkOption { default = "0.06"; description = "Cursor speed factor for precision finger motion"; }; maxSpeed = mkOption { default = "0.12"; description = "Cursor speed factor for highest-speed finger motion"; }; twoFingerScroll = mkOption { default = false; description = "Whether to enable two-finger drag-scrolling"; }; }; layout = mkOption { default = "us"; description = " Keyboard layout. "; }; xkbModel = mkOption { default = "pc104"; example = "presario"; description = " Keyboard model. "; }; xkbOptions = mkOption { default = ""; example = "grp:caps_toggle, grp_led:scroll"; description = " X keyboard options; layout switching goes here. "; }; useInternalAGPGART = mkOption { default = ""; example = "no"; description = " Just the wrapper for an xorg.conf option. "; }; extraDeviceConfig = mkOption { default = ""; example = "VideoRAM 131072"; description = " Just anything to add into Device section. "; }; extraMonitorSettings = mkOption { default = ""; example = "HorizSync 28-49"; description = " Just anything to add into Monitor section. "; }; extraDisplaySettings = mkOption { default = ""; example = "Virtual 2048 2048"; description = " Just anything to add into Display subsection (located in Screen section). "; }; extraModules = mkOption { default = ""; example = " SubSection \"extmod\" EndSubsection "; description = " Just anything to add into Modules section. "; }; serverLayoutOptions = mkOption { default = ""; example = " Option \"AIGLX\" \"true\" "; description = " Just anything to add into Monitor section. "; }; defaultDepth = mkOption { default = 24; example = 8; description = " Default colour depth. "; }; useXFS = mkOption { default = false; example = "unix/:7100"; description = " Way to access the X Font Server to use. "; }; tty = mkOption { default = 7; example = 9; description = " Virtual console for the X server. "; }; display = mkOption { default = 0; example = 1; description = " Display number for the X server. "; }; package = mkOption { default = pkgs.xorg; description = " Alternative X.org package to use. For example, you can replace individual drivers. "; }; virtualScreen = mkOption { default = null; example = { x=2048; y=2048; }; description = " Virtual screen size for Xrandr "; }; }; }; environment.x11Packages = mkOption { default = []; type = types.list types.package; description = " List of packages added to the system when the xserver is activated. (). "; }; }; in let # Abbreviations. cfg = config.services.xserver; xorg = cfg.package; stdenv = pkgs.stdenv; knownVideoDrivers = { nvidia = { modulesFirst = [ kernelPackages.nvidia_x11 ]; }; #make sure it first loads the nvidia libs vesa = { modules = [xorg.xf86videovesa]; }; vga = { modules = [xorg.xf86videovga]; }; sis = { modules = [xorg.xf86videosis]; }; i810 = { modules = [xorg.xf86videoi810]; }; intel = { modules = [xorg.xf86videointel]; }; nv = { modules = [xorg.xf86videonv]; }; ati = { modules = [xorg.xf86videoati]; }; via = { modules = [xorg.xf86videovia]; }; cirrus = { modules = [xorg.xf86videocirrus]; }; }; # Get a bunch of user settings. videoDriver = cfg.videoDriver; resolutions = map (res: ''"${toString res.x}x${toString res.y}"'') (cfg.resolutions); videoDriverModules = attrByPath [videoDriver] (throw "unknown video driver: `${videoDriver}'") knownVideoDrivers; modules = attrByPath ["modulesFirst"] [] videoDriverModules ++ [ xorg.xorgserver xorg.xf86inputevdev ] ++ attrByPath ["modules"] [] videoDriverModules ++ optional cfg.synaptics.enable xorg.xf86inputsynaptics; fontsForXServer = fontDirectories ++ # We don't want these fonts in fonts.conf, because then modern, # fontconfig-based applications will get horrible bitmapped # Helvetica fonts. It's better to get a substitution (like Nimbus # Sans) than that horror. But we do need the Adobe fonts for some # old non-fontconfig applications. (Possibly this could be done # better using a fontconfig rule.) [ pkgs.xorg.fontadobe100dpi pkgs.xorg.fontadobe75dpi ]; halConfigFiles = [ (pkgs.writeTextFile { name = "hal-policy-keymap"; destination = "/policy/30-keymap.fdi"; text = '' hal-setup-keymap base ${cfg.xkbModel} ${cfg.layout} ${cfg.xkbOptions} ''; }) ]; configFile = stdenv.mkDerivation { name = "xserver.conf"; src = ./xserver.conf; inherit fontsForXServer videoDriver resolutions; isClone = if cfg.isClone then "on" else "off"; synapticsInputDevice = if cfg.synaptics.enable then '' Section "InputDevice" Identifier "Touchpad[0]" Driver "synaptics" Option "Device" "${cfg.synaptics.dev}" Option "Protocol" "PS/2" Option "LeftEdge" "1700" Option "RightEdge" "5300" Option "TopEdge" "1700" Option "BottomEdge" "4200" Option "FingerLow" "25" Option "FingerHigh" "30" Option "MaxTapTime" "180" Option "MaxTapMove" "220" Option "VertScrollDelta" "100" Option "MinSpeed" "${cfg.synaptics.minSpeed}" Option "MaxSpeed" "${cfg.synaptics.maxSpeed}" Option "AccelFactor" "0.0010" Option "SHMConfig" "on" Option "Repeater" "/dev/input/mice" Option "TapButton1" "1" Option "TapButton2" "2" Option "TapButton3" "3" Option "VertTwoFingerScroll" "${if cfg.synaptics.twoFingerScroll then "1" else "0"}" Option "HorizTwoFingerScroll" "${if cfg.synaptics.twoFingerScroll then "1" else "0"}" EndSection '' else ""; xkbOptions = if cfg.xkbOptions == "" then "" else '' Option "XkbOptions" "${cfg.xkbOptions}" ''; setCorePointer = if cfg.synaptics.enable then '' InputDevice "Touchpad[0]" "CorePointer" '' else ""; internalAGPGART = if cfg.useInternalAGPGART == "yes" then '' Option "UseInternalAGPGART" "yes"'' else if cfg.useInternalAGPGART == "no" then '' Option "UseInternalAGPGART" "no"'' else ""; extraDeviceConfig = cfg.extraDeviceConfig; extraMonitorSettings = cfg.extraMonitorSettings; extraDisplaySettings = cfg.extraDisplaySettings; extraModules = cfg.extraModules; serverLayoutOptions = cfg.serverLayoutOptions; defaultDepth = cfg.defaultDepth; virtualScreen = if cfg.virtualScreen != null then "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}" else ""; xfs = if cfg.useXFS == false then "" else ''FontPath "${toString cfg.useXFS}"''; buildCommand = '' buildCommand= # urgh, don't substitute this export fontPaths= for i in $fontsForXServer; do if test "''${i:0:''${#NIX_STORE}}" == "$NIX_STORE"; then for j in $(find $i -name fonts.dir); do fontPaths="''${fontPaths}FontPath \"$(dirname $j)\"''\n" done fi done export modulePaths= for i in $(find ${toString modules} -type d); do if ls $i/*.so* > /dev/null 2>&1; then modulePaths="''${modulePaths}ModulePath \"$i\"''\n" fi done export moduleSection="" export screen="" export device="" export extensions="" #if only my gf were this dirty if test "${toString videoDriver}" == "nvidia"; then export screen=' Option "AddARGBGLXVisuals" "true" Option "DisableGLXRootClipping" "true" Option "RandRRotation" "on" ' export device=' Option "RenderAccel" "true" Option "AllowGLXWithComposite" "true" Option "AddARGBGLXVisuals" "true" ' export extensions=' Option "Composite" "Enable" ' fi if [ "${toString videoDriver}" = i810 ]; then export extensions=' Option "Composite" "Enable" '; fi; if [ "${toString videoDriver}" = ati ]; then export extensions=' Option "Composite" "Enable" '; fi; if [ "${toString videoDriver}" = radeonhd ]; then export extensions=' Option "Composite" "Enable" '; fi; substituteAll $src $out ''; # */ }; in mkIf cfg.enable { assertions = [ { assertion = config.services.hal.enable == true; message = "The X server needs HAL running. Set services.hal.enable to true"; } ]; require = [ options # services.xserver.*Manager ./display-managers/default.nix ./window-managers/default.nix ./desktop-managers/default.nix # services.extraJobs # ../../upstart-jobs/default.nix # environment.etc # ../../etc/default.nix # fonts.fonts # ../../system/fonts.nix # boot.extraModulePackages # security.extraSetuidPrograms # environment.extraPackages ]; boot = { extraModulePackages = mkIf (cfg.videoDriver == "nvidia") [ kernelPackages.nvidia_x11 ]; }; environment = { etc = mkIf cfg.exportConfiguration [ { source = "${configFile}"; target = "X11/xorg.conf"; } # -xkbdir command line option does not seems to be passed to xkbcomp. { source = "${pkgs.xkeyboard_config}/etc/X11/xkb"; target = "X11/xkb"; } ]; x11Packages = [ xorg.xrandr xorg.xrdb xorg.setxkbmap xorg.iceauth # required for KDE applications (it's called by dcopserver) ] ++ optional (videoDriver == "nvidia") kernelPackages.nvidia_x11; extraPackages = config.environment.x11Packages; }; services = { xserver = { displayManager = { xserverArgs = [ "-ac" "-logverbose" "-verbose" "-terminate" "-logfile" "/var/log/X.${toString cfg.display}.log" "-config ${configFile}" ":${toString cfg.display}" "vt${toString cfg.tty}" "-xkbdir" "${pkgs.xkeyboard_config}/etc/X11/xkb" ] ++ optional (!cfg.tcpEnable) "-nolisten tcp"; }; }; hal = { extraFdi = halConfigFiles; }; extraJobs = [{ name = "xserver"; job = '' start on ${if cfg.autorun then "hal" else "never"} start script # Ugly hack: wait until udev has started since the X server # needs various devices. This would more properly be # expressed as an Upstart dependency, but AFAIK in "start # on" we can't express a logical AND. while ! initctl status udev 2>&1 | grep -q running; do sleep 1 done rm -f /var/run/opengl-driver ${if videoDriver == "nvidia" then '' ln -sf ${kernelPackages.nvidia_x11} /var/run/opengl-driver '' else if cfg.driSupport then "ln -sf ${pkgs.mesa} /var/run/opengl-driver" else "" } ${cfg.displayManager.job.beforeScript} rm -f /tmp/.X0-lock end script ${cfg.displayManager.job.env} env FONTCONFIG_FILE=/etc/fonts/fonts.conf # !!! cleanup env XKB_BINDIR=${xorg.xkbcomp}/bin # Needed for the Xkb extension. ${if videoDriver == "nvidia" then "env LD_LIBRARY_PATH=${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.nvidia_x11}/lib" else "" } ${if videoDriver != "nvidia" then "env XORG_DRI_DRIVER_PATH=${pkgs.mesa}/lib/dri" else "" } exec ${cfg.displayManager.job.execCmd} ''; }]; }; }