diff options
Diffstat (limited to 'nixos/modules/services/x11')
31 files changed, 2649 insertions, 0 deletions
diff --git a/nixos/modules/services/x11/desktop-managers/default.nix b/nixos/modules/services/x11/desktop-managers/default.nix new file mode 100644 index 0000000000000..0fea74d5ba731 --- /dev/null +++ b/nixos/modules/services/x11/desktop-managers/default.nix @@ -0,0 +1,75 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + xcfg = config.services.xserver; + cfg = xcfg.desktopManager; + + # Whether desktop manager `d' is capable of setting a background. + # If it isn't, the `feh' program is used as a fallback. + needBGCond = d: ! (d ? bgSupport && d.bgSupport); + +in + +{ + # Note: the order in which desktop manager modules are imported here + # determines the default: later modules (if enabled) are preferred. + # E.g., if KDE is enabled, it supersedes xterm. + imports = [ ./none.nix ./xterm.nix ./xfce.nix ./gnome.nix ./kde4.nix ./e17.nix ]; + + options = { + + services.xserver.desktopManager = { + + session = mkOption { + default = []; + example = singleton + { name = "kde"; + bgSupport = true; + start = "..."; + }; + description = " + Internal option used to add some common line to desktop manager + scripts before forwarding the value to the + <varname>displayManager</varname>. + "; + apply = list: { + list = map (d: d // { + manage = "desktop"; + start = d.start + + optionalString (needBGCond d) '' + if test -e $HOME/.background-image; then + ${pkgs.feh}/bin/feh --bg-scale $HOME/.background-image + fi + ''; + }) list; + needBGPackages = [] != filter needBGCond list; + }; + }; + + default = mkOption { + default = ""; + example = "none"; + description = "Default desktop manager loaded if none have been chosen."; + merge = mergeOneOption; + apply = defaultDM: + if defaultDM == "" && cfg.session.list != [] then + (head cfg.session.list).name + else if any (w: w.name == defaultDM) cfg.session.list then + defaultDM + else + throw "Default desktop manager ($(defaultDM)) not found."; + }; + + }; + + }; + + config = { + services.xserver.displayManager.session = cfg.session.list; + environment.x11Packages = + mkIf cfg.session.needBGPackages [ pkgs.feh ]; + }; +} diff --git a/nixos/modules/services/x11/desktop-managers/e17.nix b/nixos/modules/services/x11/desktop-managers/e17.nix new file mode 100644 index 0000000000000..3d91617c62aa1 --- /dev/null +++ b/nixos/modules/services/x11/desktop-managers/e17.nix @@ -0,0 +1,30 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + xcfg = config.services.xserver; + cfg = xcfg.desktopManager.e17; + +in + +{ + options = { + + services.xserver.desktopManager.e17.enable = mkOption { + default = false; + example = true; + description = "Enable support for the E17 desktop environment."; + }; + + }; + + + config = mkIf (xcfg.enable && cfg.enable) { + + services.dbus.packages = [ pkgs.e17.ethumb ]; + + }; + +} diff --git a/nixos/modules/services/x11/desktop-managers/gnome.nix b/nixos/modules/services/x11/desktop-managers/gnome.nix new file mode 100644 index 0000000000000..b0212446ad36e --- /dev/null +++ b/nixos/modules/services/x11/desktop-managers/gnome.nix @@ -0,0 +1,42 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.desktopManager.gnome; + gnome = pkgs.gnome; + +in + +{ + + options = { + + services.xserver.desktopManager.gnome.enable = mkOption { + default = false; + example = true; + description = "Enable a gnome terminal as a desktop manager."; + }; + + }; + + config = mkIf cfg.enable { + + services.xserver.desktopManager.session = singleton + { name = "gnome"; + start = '' + ${gnome.gnometerminal}/bin/gnome-terminal -ls & + waitPID=$! + ''; + }; + + environment.systemPackages = + [ gnome.gnometerminal + gnome.GConf + gnome.gconfeditor + ]; + + }; + +} diff --git a/nixos/modules/services/x11/desktop-managers/kde4.nix b/nixos/modules/services/x11/desktop-managers/kde4.nix new file mode 100644 index 0000000000000..c76acfbcd4e24 --- /dev/null +++ b/nixos/modules/services/x11/desktop-managers/kde4.nix @@ -0,0 +1,169 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + xcfg = config.services.xserver; + cfg = xcfg.desktopManager.kde4; + xorg = pkgs.xorg; + + # Disable Nepomuk and Strigi by default. As of KDE 4.7, they don't + # really work very well (e.g. searching files often fails to find + # files), segfault sometimes and consume significant resources. + # They can be re-enabled in the KDE System Settings under "Desktop + # Search". + nepomukConfig = pkgs.writeTextFile + { name = "nepomuk-config"; + destination = "/share/config/nepomukserverrc"; + text = + '' + [Basic Settings] + Start Nepomuk=false + + [Service-nepomukstrigiservice] + autostart=false + ''; + }; + + phononBackends = { + gstreamer = [ + pkgs.phonon_backend_gstreamer + pkgs.gst_all.gstPluginsBase + pkgs.gst_all.gstPluginsGood + pkgs.gst_all.gstPluginsUgly + pkgs.gst_all.gstPluginsBad + pkgs.gst_all.gstFfmpeg # for mp3 playback + pkgs.gst_all.gstreamer # needed? + ]; + + vlc = [pkgs.phonon_backend_vlc]; + }; + + phononBackendPackages = flip concatMap cfg.phononBackends + (name: attrByPath [name] (throw "unknown phonon backend `${name}'") phononBackends); + + wantsUdisks2 = pkgs.kde4.kdelibs.wantsUdisks2 or false; +in + +{ + options = { + + services.xserver.desktopManager.kde4 = { + enable = mkOption { + default = false; + example = true; + description = "Enable the KDE 4 desktop environment."; + }; + + phononBackends = mkOption { + type = types.listOf types.string; + default = ["gstreamer"]; + example = ["gstreamer" "vlc"]; + description = "Which phonon multimedia backend kde should use"; + }; + }; + + environment.kdePackages = mkOption { + default = []; + example = "[ pkgs.kde4.kdesdk ]"; + type = types.listOf types.package; + description = "This option is obsolete. Please use <option>environment.systemPackages</option> instead."; + }; + + }; + + + config = mkIf (xcfg.enable && cfg.enable) { + + # If KDE 4 is enabled, make it the default desktop manager (unless + # overridden by the user's configuration). + # !!! doesn't work yet ("Multiple definitions. Only one is allowed + # for this option.") + # services.xserver.desktopManager.default = mkOverrideTemplate 900 "kde4"; + + services.xserver.desktopManager.session = singleton + { name = "kde4"; + bgSupport = true; + start = + '' + # The KDE icon cache is supposed to update itself + # automatically, but it uses the timestamp on the icon + # theme directory as a trigger. Since in Nix the + # timestamp is always the same, this doesn't work. So as + # a workaround, nuke the icon cache on login. This isn't + # perfect, since it may require logging out after + # installing new applications to update the cache. + # See http://lists-archives.org/kde-devel/26175-what-when-will-icon-cache-refresh.html + rm -fv $HOME/.kde/cache-*/icon-cache.kcache + + # Qt writes a weird ‘libraryPath’ line to + # ~/.config/Trolltech.conf that causes the KDE plugin + # paths of previous KDE invocations to be searched. + # Obviously using mismatching KDE libraries is potentially + # disastrous, so here we nuke references to the Nix store + # in Trolltech.conf. A better solution would be to stop + # Qt from doing this wackiness in the first place. + if [ -e $HOME/.config/Trolltech.conf ]; then + sed -e '/nix\\store\|nix\/store/ d' -i $HOME/.config/Trolltech.conf + fi + + # Start KDE. + exec ${pkgs.kde4.kdebase_workspace}/bin/startkde + ''; + }; + + security.setuidOwners = singleton + { program = "kcheckpass"; + source = "${pkgs.kde4.kdebase_workspace}/lib/kde4/libexec/kcheckpass"; + owner = "root"; + group = "root"; + setuid = true; + }; + + environment.systemPackages = + [ pkgs.kde4.kdelibs + + pkgs.kde4.kde_baseapps # Splitted kdebase + pkgs.kde4.kde_workspace + pkgs.kde4.kde_runtime + pkgs.kde4.konsole + pkgs.kde4.kate + + pkgs.kde4.kde_wallpapers # contains kdm's default background + pkgs.kde4.oxygen_icons + pkgs.virtuoso # to enable Nepomuk to find Virtuoso + + # Starts KDE's Polkit authentication agent. + pkgs.kde4.polkit_kde_agent + + # Miscellaneous runtime dependencies. + pkgs.kde4.qt4 # needed for qdbus + pkgs.shared_mime_info + xorg.xmessage # so that startkde can show error messages + xorg.xset # used by startkde, non-essential + xorg.xauth # used by kdesu + pkgs.shared_desktop_ontologies # used by nepomuk + pkgs.strigi # used by nepomuk + pkgs.mysql # used by akonadi + ] + ++ [ nepomukConfig ] ++ phononBackendPackages + ++ config.environment.kdePackages; + + environment.pathsToLink = [ "/share" ]; + + environment.etc = singleton + { source = "${pkgs.xkeyboard_config}/etc/X11/xkb"; + target = "X11/xkb"; + }; + + # Enable helpful DBus services. + services.udisks.enable = ! wantsUdisks2; + services.udisks2.enable = wantsUdisks2; + services.upower.enable = config.powerManagement.enable; + + security.pam.services = [ { name = "kde"; allowNullPassword = true; startSession = true; } ]; + + }; + +} diff --git a/nixos/modules/services/x11/desktop-managers/none.nix b/nixos/modules/services/x11/desktop-managers/none.nix new file mode 100644 index 0000000000000..af7a376ae0296 --- /dev/null +++ b/nixos/modules/services/x11/desktop-managers/none.nix @@ -0,0 +1,7 @@ +{ + services.xserver.desktopManager.session = + [ { name = "none"; + start = ""; + } + ]; +} diff --git a/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixos/modules/services/x11/desktop-managers/xfce.nix new file mode 100644 index 0000000000000..f5d544ad0462d --- /dev/null +++ b/nixos/modules/services/x11/desktop-managers/xfce.nix @@ -0,0 +1,90 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + xcfg = config.services.xserver; + cfg = xcfg.desktopManager.xfce; + +in + +{ + options = { + + services.xserver.desktopManager.xfce.enable = mkOption { + default = false; + example = true; + description = "Enable the Xfce desktop environment."; + }; + + }; + + + config = mkIf (xcfg.enable && cfg.enable) { + + services.xserver.desktopManager.session = singleton + { name = "xfce"; + bgSupport = true; + start = + '' + # Set GTK_PATH so that GTK+ can find the theme engines. + export GTK_PATH=${config.system.path}/lib/gtk-2.0 + + # Set GTK_DATA_PREFIX so that GTK+ can find the Xfce themes. + export GTK_DATA_PREFIX=${config.system.path} + + # Necessary to get xfce4-mixer to find GST's ALSA plugin. + # Ugly. + export GST_PLUGIN_PATH=${config.system.path}/lib + + exec ${pkgs.stdenv.shell} ${pkgs.xfce.xinitrc} + ''; + }; + + environment.systemPackages = + [ pkgs.gtk # To get GTK+'s themes. + pkgs.hicolor_icon_theme + pkgs.tango-icon-theme + pkgs.shared_mime_info + pkgs.which # Needed by the xfce's xinitrc script. + pkgs.xfce.exo + pkgs.xfce.gtk_xfce_engine + pkgs.xfce.libxfcegui4 # For the icons. + pkgs.xfce.mousepad + pkgs.xfce.ristretto + pkgs.xfce.terminal + pkgs.xfce.thunar + pkgs.xfce.xfce4icontheme + pkgs.xfce.xfce4panel + pkgs.xfce.xfce4session + pkgs.xfce.xfce4settings + pkgs.xfce.xfce4mixer + pkgs.xfce.xfceutils + pkgs.xfce.xfconf + pkgs.xfce.xfdesktop + pkgs.xfce.xfwm4 + # This supplies some "abstract" icons such as + # "utilities-terminal" and "accessories-text-editor". + pkgs.gnome.gnomeicontheme + pkgs.desktop_file_utils + pkgs.xfce.libxfce4ui + pkgs.xfce.garcon + pkgs.xfce.thunar_volman + pkgs.xfce.gvfs + pkgs.xfce.xfce4_appfinder + ] + ++ optional config.powerManagement.enable pkgs.xfce.xfce4_power_manager; + + environment.pathsToLink = + [ "/share/xfce4" "/share/themes" "/share/mime" "/share/desktop-directories" "/share/gtksourceview-2.0" ]; + + environment.variables.GIO_EXTRA_MODULES = "${pkgs.xfce.gvfs}/lib/gio/modules"; + + # Enable helpful DBus services. + services.udisks2.enable = true; + services.upower.enable = config.powerManagement.enable; + + }; + +} diff --git a/nixos/modules/services/x11/desktop-managers/xterm.nix b/nixos/modules/services/x11/desktop-managers/xterm.nix new file mode 100644 index 0000000000000..edc61c103ea9f --- /dev/null +++ b/nixos/modules/services/x11/desktop-managers/xterm.nix @@ -0,0 +1,36 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.desktopManager.xterm; + +in + +{ + options = { + + services.xserver.desktopManager.xterm.enable = mkOption { + default = true; + example = false; + description = "Enable a xterm terminal as a desktop manager."; + }; + + }; + + config = mkIf cfg.enable { + + services.xserver.desktopManager.session = singleton + { name = "xterm"; + start = '' + ${pkgs.xterm}/bin/xterm -ls & + waitPID=$! + ''; + }; + + environment.systemPackages = [ pkgs.xterm ]; + + }; + +} diff --git a/nixos/modules/services/x11/display-managers/auto.nix b/nixos/modules/services/x11/display-managers/auto.nix new file mode 100644 index 0000000000000..33d97e0e07a95 --- /dev/null +++ b/nixos/modules/services/x11/display-managers/auto.nix @@ -0,0 +1,52 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + dmcfg = config.services.xserver.displayManager; + cfg = dmcfg.auto; + +in + +{ + + ###### interface + + options = { + + services.xserver.displayManager.auto = { + + enable = mkOption { + default = false; + description = '' + Whether to enable the fake "auto" display manager, which + automatically logs in the user specified in the + <option>user</option> option. This is mostly useful for + automated tests. + ''; + }; + + user = mkOption { + default = "root"; + description = "The user account to login automatically."; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.displayManager.slim = { + enable = true; + autoLogin = true; + defaultUser = cfg.user; + }; + + }; + +} diff --git a/nixos/modules/services/x11/display-managers/default.nix b/nixos/modules/services/x11/display-managers/default.nix new file mode 100644 index 0000000000000..c7599e245b059 --- /dev/null +++ b/nixos/modules/services/x11/display-managers/default.nix @@ -0,0 +1,283 @@ +# This module declares the options to define a *display manager*, the +# program responsible for handling X logins (such as xdm, kdm, gdb, or +# SLiM). The display manager allows the user to select a *session +# type*. When the user logs in, the display manager starts the +# *session script* ("xsession" below) to launch the selected session +# type. The session type defines two things: the *desktop manager* +# (e.g., KDE, Gnome or a plain xterm), and optionally the *window +# manager* (e.g. kwin or twm). + +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver; + xorg = pkgs.xorg; + + vaapiDrivers = pkgs.buildEnv { + name = "vaapi-drivers"; + paths = cfg.vaapiDrivers; + # We only want /lib/dri, but with a single input path, we need "/" for it to work + pathsToLink = [ "/" ]; + }; + + # file provided by services.xserver.displayManager.session.script + xsession = wm: dm: pkgs.writeScript "xsession" + '' + #! /bin/sh + + . /etc/profile + cd "$HOME" + + # The first argument of this script is the session type. + sessionType="$1" + if [ "$sessionType" = default ]; then sessionType=""; fi + + ${optionalString (!cfg.displayManager.job.logsXsession) '' + exec > ~/.xsession-errors 2>&1 + ''} + + ${optionalString cfg.displayManager.desktopManagerHandlesLidAndPower '' + # Stop systemd from handling the power button and lid switch, + # since presumably the desktop environment will handle these. + if [ -z "$_INHIBITION_LOCK_TAKEN" ]; then + export _INHIBITION_LOCK_TAKEN=1 + exec ${config.systemd.package}/bin/systemd-inhibit --what=handle-lid-switch:handle-power-key "$0" "$sessionType" + fi + + ''} + + ${optionalString cfg.startOpenSSHAgent '' + if test -z "$SSH_AUTH_SOCK"; then + # Restart this script as a child of the SSH agent. (It is + # also possible to start the agent as a child that prints + # the required environment variabled on stdout, but in + # that mode ssh-agent is not terminated when we log out.) + export SSH_ASKPASS=${pkgs.x11_ssh_askpass}/libexec/x11-ssh-askpass + exec ${pkgs.openssh}/bin/ssh-agent "$0" "$sessionType" + fi + ''} + + ${optionalString cfg.startGnuPGAgent '' + if test -z "$SSH_AUTH_SOCK"; then + # Restart this script as a child of the GnuPG agent. + exec "${pkgs.gnupg}/bin/gpg-agent" \ + --enable-ssh-support --daemon \ + --pinentry-program "${pkgs.pinentry}/bin/pinentry-gtk-2" \ + --write-env-file "$HOME/.gpg-agent-info" \ + "$0" "$sessionType" + fi + ''} + + # Handle being called by kdm. + if test "''${1:0:1}" = /; then eval exec "$1"; fi + + # Start PulseAudio if enabled. + ${optionalString (config.hardware.pulseaudio.enable) '' + ${optionalString (!config.hardware.pulseaudio.systemWide) + "${pkgs.pulseaudio}/bin/pulseaudio --start" + } + + # Publish access credentials in the root window. + ${pkgs.pulseaudio}/bin/pactl load-module module-x11-publish "display=$DISPLAY" + + # Keep track of devices. Mostly useful for Phonon/KDE. + ${pkgs.pulseaudio}/bin/pactl load-module module-device-manager "do_routing=1" + ''} + + # Load X defaults. + if test -e ~/.Xdefaults; then + ${xorg.xrdb}/bin/xrdb -merge ~/.Xdefaults + fi + + export LIBVA_DRIVERS_PATH=${vaapiDrivers}/lib/dri + + # Speed up application start by 50-150ms according to + # http://kdemonkey.blogspot.nl/2008/04/magic-trick.html + rm -rf $HOME/.compose-cache + mkdir $HOME/.compose-cache + + ${cfg.displayManager.sessionCommands} + + # Allow the user to setup a custom session type. + if test -x ~/.xsession; then + exec ~/.xsession + else + if test "$sessionType" = "custom"; then + sessionType="" # fall-thru if there is no ~/.xsession + fi + fi + + # The session type is "<desktop-manager> + <window-manager>", so + # extract those. + windowManager="''${sessionType##* + }" + : ''${windowManager:=${cfg.windowManager.default}} + desktopManager="''${sessionType% + *}" + : ''${desktopManager:=${cfg.desktopManager.default}} + + # Start the window manager. + case $windowManager in + ${concatMapStrings (s: '' + (${s.name}) + ${s.start} + ;; + '') wm} + (*) echo "$0: Window manager '$windowManager' not found.";; + esac + + # Start the desktop manager. + case $desktopManager in + ${concatMapStrings (s: '' + (${s.name}) + ${s.start} + ;; + '') dm} + (*) echo "$0: Desktop manager '$desktopManager' not found.";; + esac + + test -n "$waitPID" && wait "$waitPID" + exit 0 + ''; + + mkDesktops = names: pkgs.runCommand "desktops" {} + '' + mkdir -p $out + ${concatMapStrings (n: '' + cat - > "$out/${n}.desktop" << EODESKTOP + [Desktop Entry] + Version=1.0 + Type=XSession + TryExec=${cfg.displayManager.session.script} + Exec=${cfg.displayManager.session.script} '${n}' + Name=${n} + Comment= + EODESKTOP + '') names} + ''; + +in + +{ + + options = { + + services.xserver.displayManager = { + + xauthBin = mkOption { + default = "${xorg.xauth}/bin/xauth"; + description = "Path to the <command>xauth</command> program used by display managers."; + }; + + xserverBin = mkOption { + default = "${xorg.xorgserver}/bin/X"; + description = "Path to the X server used by display managers."; + }; + + xserverArgs = mkOption { + default = []; + example = [ "-ac" "-logverbose" "-nolisten tcp" ]; + description = "List of arguments for the X server."; + apply = toString; + }; + + sessionCommands = mkOption { + default = ""; + example = + '' + xmessage "Hello World!" & + ''; + type = types.string; + description = "Shell commands executed just before the window or desktop manager is started."; + }; + + desktopManagerHandlesLidAndPower = mkOption { + default = true; + description = '' + Whether the display manager should prevent systemd from handling + lid and power events. This is normally handled by the desktop + environment's power manager. Turn this off when using a minimal + X11 setup without a full power manager. + ''; + }; + + session = mkOption { + default = []; + example = [ + { + manage = "desktop"; + name = "xterm"; + start = " + ${pkgs.xterm}/bin/xterm -ls & + waitPID=$! + "; + } + ]; + description = '' + List of sessions supported with the command used to start each + session. Each session script can set the + <varname>waitPID</varname> shell variable to make this script + wait until the end of the user session. Each script is used + to define either a windows manager or a desktop manager. These + can be differentiated by setting the attribute + <varname>manage</varname> either to <literal>"window"</literal> + or <literal>"desktop"</literal>. + + The list of desktop manager and window manager should appear + inside the display manager with the desktop manager name + followed by the window manager name. + ''; + apply = list: rec { + wm = filter (s: s.manage == "window") list; + dm = filter (s: s.manage == "desktop") list; + names = flip concatMap dm + (d: map (w: d.name + optionalString (w.name != "none") (" + " + w.name)) + (filter (w: d.name != "none" || w.name != "none") wm)); + desktops = mkDesktops names; + script = xsession wm dm; + }; + }; + + job = mkOption { + default = {}; + type = types.uniq types.optionSet; + description = "This option defines how to start the display manager."; + + options = { + + preStart = mkOption { + default = ""; + example = "rm -f /var/log/my-display-manager.log"; + description = "Script executed before the display manager is started."; + }; + + execCmd = mkOption { + example = "${pkgs.slim}/bin/slim"; + description = "Command to start the display manager."; + }; + + environment = mkOption { + default = {}; + example = { SLIM_CFGFILE = /etc/slim.conf; }; + description = "Additional environment variables needed by the display manager."; + }; + + logsXsession = mkOption { + default = false; + description = '' + Whether the display manager redirects the + output of the session script to + <filename>~/.xsession-errors</filename>. + ''; + }; + + }; + + }; + + }; + + }; + +} diff --git a/nixos/modules/services/x11/display-managers/kdm.nix b/nixos/modules/services/x11/display-managers/kdm.nix new file mode 100644 index 0000000000000..229ab12c6e1ba --- /dev/null +++ b/nixos/modules/services/x11/display-managers/kdm.nix @@ -0,0 +1,151 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + dmcfg = config.services.xserver.displayManager; + cfg = dmcfg.kdm; + + inherit (pkgs.kde4) kdebase_workspace; + + defaultConfig = + '' + [Shutdown] + HaltCmd=${config.systemd.package}/sbin/shutdown -h now + RebootCmd=${config.systemd.package}/sbin/shutdown -r now + ${optionalString (config.system.boot.loader.id == "grub") '' + BootManager=${if config.boot.loader.grub.version == 2 then "Grub2" else "Grub"} + ''} + + [X-*-Core] + Xrdb=${pkgs.xlibs.xrdb}/bin/xrdb + SessionsDirs=${dmcfg.session.desktops} + Session=${dmcfg.session.script} + FailsafeClient=${pkgs.xterm}/bin/xterm + + [X-:*-Core] + ServerCmd=${dmcfg.xserverBin} ${dmcfg.xserverArgs} + # KDM calls `rm' somewhere to clean up some temporary directory. + SystemPath=${pkgs.coreutils}/bin + # The default timeout (15) is too short in a heavily loaded boot process. + ServerTimeout=60 + # Needed to prevent the X server from dying on logout and not coming back: + TerminateServer=true + ${optionalString (cfg.setupScript != "") + '' + Setup=${cfg.setupScript} + ''} + + [X-*-Greeter] + HiddenUsers=root,nixbld1,nixbld2,nixbld3,nixbld4,nixbld5,nixbld6,nixbld7,nixbld8,nixbld9,nixbld10 + PluginsLogin=${kdebase_workspace}/lib/kde4/kgreet_classic.so + ${optionalString (cfg.themeDirectory != "") + '' + UseTheme=true + Theme=${cfg.themeDirectory} + '' + } + + ${optionalString (cfg.enableXDMCP) + '' + [Xdmcp] + Enable=true + ''} + ''; + + kdmrc = pkgs.stdenv.mkDerivation { + name = "kdmrc"; + config = defaultConfig + cfg.extraConfig; + buildCommand = + '' + echo "$config" > $out + + # The default kdmrc would add "-nolisten tcp", and we already + # have that managed by nixos. Hence the grep. + cat ${kdebase_workspace}/share/config/kdm/kdmrc | grep -v nolisten >> $out + ''; + }; + +in + +{ + + ###### interface + + options = { + + services.xserver.displayManager.kdm = { + + enable = mkOption { + default = false; + description = '' + Whether to enable the KDE display manager. + ''; + }; + + enableXDMCP = mkOption { + default = false; + description = '' + Whether to enable XDMCP, which allows remote logins. + ''; + }; + + themeDirectory = mkOption { + default = ""; + description = '' + The path to a KDM theme directory. This theme + will be used by the KDM greeter. + ''; + }; + + setupScript = mkOption { + default = ""; + description = '' + The path to a KDM setup script. This script is run as root just + before KDM starts. Can be used for setting up + monitors with xrandr, for example. + ''; + }; + + extraConfig = mkOption { + default = ""; + description = '' + Options appended to <filename>kdmrc</filename>, the + configuration file of KDM. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.displayManager.slim.enable = false; + + services.xserver.displayManager.job = + { execCmd = + '' + mkdir -m 0755 -p /var/lib/kdm + chown kdm /var/lib/kdm + ${(optionalString (config.system.boot.loader.id == "grub" && config.system.build.grub != null) "PATH=${config.system.build.grub}/sbin:$PATH ") + + "KDEDIRS=/run/current-system/sw exec ${kdebase_workspace}/bin/kdm -config ${kdmrc} -nodaemon"} + ''; + logsXsession = true; + }; + + security.pam.services = [ { name = "kde"; allowNullPassword = true; startSession = true; } ]; + + users.extraUsers = singleton + { name = "kdm"; + uid = config.ids.uids.kdm; + description = "KDM user"; + }; + + }; + +} diff --git a/nixos/modules/services/x11/display-managers/lightdm.nix b/nixos/modules/services/x11/display-managers/lightdm.nix new file mode 100644 index 0000000000000..c2b90d239eaab --- /dev/null +++ b/nixos/modules/services/x11/display-managers/lightdm.nix @@ -0,0 +1,119 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + dmcfg = config.services.xserver.displayManager; + xEnv = config.systemd.services."display-manager".environment; + cfg = dmcfg.lightdm; + + inherit (pkgs) stdenv lightdm writeScript writeText; + + # lightdm runs with clearenv(), but we need a few things in the enviornment for X to startup + xserverWrapper = writeScript "xserver-wrapper" + '' + #! /bin/sh + ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)} + exec ${dmcfg.xserverBin} ${dmcfg.xserverArgs} + ''; + + # The default greeter provided with this expression is the GTK greeter. + # Again, we need a few things in the environment for the greeter to run with + # fonts/icons. + wrappedGtkGreeter = stdenv.mkDerivation { + name = "lightdm-gtk-greeter"; + buildInputs = [ pkgs.makeWrapper ]; + + buildCommand = '' + ensureDir $out/gtk-3.0/ + + # This wrapper ensures that we actually get fonts + makeWrapper ${pkgs.lightdm_gtk_greeter}/sbin/lightdm-gtk-greeter \ + $out/greeter \ + --set XDG_DATA_DIRS ${pkgs.gnome2.gnome_icon_theme}/share \ + --set FONTCONFIG_FILE /etc/fonts/fonts.conf \ + --set XDG_CONFIG_HOME $out/ + + # We need this to ensure that it actually tries to find icons from gnome-icon-theme + cat - > $out/gtk-3.0/settings.ini << EOF + [Settings] + gtk-icon-theme-name=gnome + EOF + + cat - > $out/lightdm-gtk-greeter.desktop << EOF + [Desktop Entry] + Name=LightDM Greeter + Comment=This runs the LightDM Greeter + Exec=$out/greeter + Type=Application + EOF + ''; + }; + + lightdmConf = writeText "lightdm.conf" + '' + [LightDM] + greeter-user = ${config.users.extraUsers.lightdm.name} + xgreeters-directory = ${cfg.greeter.package} + xsessions-directory = ${dmcfg.session.desktops} + + [SeatDefaults] + xserver-command = ${xserverWrapper} + session-wrapper = ${dmcfg.session.script} + greeter-session = ${cfg.greeter.name} + ''; + +in +{ + options = { + services.xserver.displayManager.lightdm = { + enable = mkOption { + default = false; + description = '' + Whether to enable lightdm as the display manager. + ''; + }; + + greeter = mkOption { + description = '' + The LightDM greeter to login via. The package should be a directory + containing a .desktop file matching the name in the 'name' option. + ''; + default = { + name = "lightdm-gtk-greeter"; + package = wrappedGtkGreeter; + }; + }; + }; + }; + + config = mkIf cfg.enable { + services.xserver.displayManager.job = { + logsXsession = true; + + # lightdm relaunches itself via just `lightdm`, so needs to be on the PATH + execCmd = '' + export PATH=${lightdm}/sbin:$PATH + ${lightdm}/sbin/lightdm --log-dir=/var/log --run-dir=/run --config=${lightdmConf} + ''; + }; + + services.dbus.enable = true; + services.dbus.packages = [ lightdm ]; + + security.pam.services = [ + { name = "lightdm"; allowNullPassword = true; startSession = true; } + { name = "lightdm-greeter"; allowNullPassword = true; startSession = true; } + ]; + + users.extraUsers.lightdm = { + createHome = true; + home = "/var/lib/lightdm"; + group = "lightdm"; + uid = config.ids.uids.lightdm; + }; + + users.extraGroups.lightdm.gid = config.ids.gids.lightdm; + }; +} diff --git a/nixos/modules/services/x11/display-managers/slim.nix b/nixos/modules/services/x11/display-managers/slim.nix new file mode 100644 index 0000000000000..9e8b9391f45f2 --- /dev/null +++ b/nixos/modules/services/x11/display-managers/slim.nix @@ -0,0 +1,113 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + dmcfg = config.services.xserver.displayManager; + cfg = dmcfg.slim; + + slimConfig = pkgs.writeText "slim.cfg" + '' + xauth_path ${dmcfg.xauthBin} + default_xserver ${dmcfg.xserverBin} + xserver_arguments ${dmcfg.xserverArgs} + sessions ${pkgs.lib.concatStringsSep "," (dmcfg.session.names ++ ["custom"])} + login_cmd exec ${pkgs.stdenv.shell} ${dmcfg.session.script} "%session" + halt_cmd ${config.systemd.package}/sbin/shutdown -h now + reboot_cmd ${config.systemd.package}/sbin/shutdown -r now + ${optionalString (cfg.defaultUser != "") ("default_user " + cfg.defaultUser)} + ${optionalString cfg.autoLogin "auto_login yes"} + ''; + + # Unpack the SLiM theme, or use the default. + slimThemesDir = + let + unpackedTheme = pkgs.stdenv.mkDerivation { + name = "slim-theme"; + buildCommand = '' + ensureDir $out + cd $out + unpackFile ${cfg.theme} + ln -s * default + ''; + }; + in if cfg.theme == null then "${pkgs.slim}/share/slim/themes" else unpackedTheme; + +in + +{ + + ###### interface + + options = { + + services.xserver.displayManager.slim = { + + enable = mkOption { + default = true; + description = '' + Whether to enable SLiM as the display manager. + ''; + }; + + theme = mkOption { + default = null; + example = pkgs.fetchurl { + url = http://download.berlios.de/slim/slim-wave.tar.gz; + sha256 = "0ndr419i5myzcylvxb89m9grl2xyq6fbnyc3lkd711mzlmnnfxdy"; + }; + description = '' + The theme for the SLiM login manager. If not specified, SLiM's + default theme is used. See <link + xlink:href='http://slim.berlios.de/themes01.php'/> for a + collection of themes. + ''; + }; + + defaultUser = mkOption { + default = ""; + example = "login"; + description = '' + The default user to load. If you put a username here you + get it automatically loaded into the username field, and + the focus is placed on the password. + ''; + }; + + autoLogin = mkOption { + default = false; + example = true; + description = '' + Automatically log in as the default user. + ''; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.displayManager.job = + { preStart = + '' + rm -f /var/log/slim.log + ''; + environment = + { SLIM_CFGFILE = slimConfig; + SLIM_THEMESDIR = slimThemesDir; + }; + execCmd = "exec ${pkgs.slim}/bin/slim"; + }; + + # Allow null passwords so that the user can login as root on the + # installation CD. + security.pam.services = [ { name = "slim"; allowNullPassword = true; startSession = true; } ]; + + }; + +} diff --git a/nixos/modules/services/x11/hardware/multitouch.nix b/nixos/modules/services/x11/hardware/multitouch.nix new file mode 100644 index 0000000000000..4f9048bfd910b --- /dev/null +++ b/nixos/modules/services/x11/hardware/multitouch.nix @@ -0,0 +1,60 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let cfg = config.services.xserver.multitouch; in + +{ + + options = { + + services.xserver.multitouch = { + + enable = mkOption { + default = false; + example = true; + description = "Whether to enable multitouch touchpad support."; + }; + + invertScroll = mkOption { + default = false; + example = true; + type = types.bool; + description = "Whether to invert scrolling direction à la OSX Lion"; + }; + + ignorePalm = mkOption { + default = false; + example = true; + type = types.bool; + description = "Whether to ignore touches detected as being the palm (i.e when typing)"; + }; + + }; + + }; + + config = mkIf cfg.enable { + + services.xserver.modules = [ pkgs.xf86_input_mtrack ]; + + services.xserver.config = + '' + # Automatically enable the multitouch driver + Section "InputClass" + MatchIsTouchpad "on" + Identifier "Touchpads" + Driver "mtrack" + Option "IgnorePalm" "${if cfg.ignorePalm then "true" else "false"}" + ${optionalString cfg.invertScroll '' + Option "ScrollUpButton" "5" + Option "ScrollDownButton" "4" + Option "ScrollLeftButton" "7" + Option "ScrollRightButton" "6" + ''} + EndSection + ''; + + }; + +} diff --git a/nixos/modules/services/x11/hardware/synaptics.nix b/nixos/modules/services/x11/hardware/synaptics.nix new file mode 100644 index 0000000000000..d16142a5fdf3c --- /dev/null +++ b/nixos/modules/services/x11/hardware/synaptics.nix @@ -0,0 +1,122 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let cfg = config.services.xserver.synaptics; in + +{ + + options = { + + services.xserver.synaptics = { + + enable = mkOption { + default = false; + example = true; + description = "Whether to enable touchpad support."; + }; + + dev = mkOption { + default = null; + example = "/dev/input/event0"; + description = + '' + Path for touchpad device. Set to null to apply to any + auto-detected touchpad. + ''; + }; + + accelFactor = mkOption { + default = "0.001"; + description = "Cursor acceleration (how fast speed increases from minSpeed to maxSpeed)."; + }; + + minSpeed = mkOption { + default = "0.6"; + description = "Cursor speed factor for precision finger motion."; + }; + + maxSpeed = mkOption { + default = "1.0"; + description = "Cursor speed factor for highest-speed finger motion."; + }; + + twoFingerScroll = mkOption { + default = false; + description = "Whether to enable two-finger drag-scrolling."; + }; + + vertEdgeScroll = mkOption { + default = ! cfg.twoFingerScroll; + description = "Whether to enable vertical edge drag-scrolling."; + }; + + tapButtons = mkOption { + default = true; + example = false; + description = "Whether to enable tap buttons."; + }; + + palmDetect = mkOption { + default = false; + example = true; + description = "Whether to enable palm detection (hardware support required)"; + }; + + horizontalScroll = mkOption { + default = true; + example = false; + description = "Whether to enable horizontal scrolling (on touchpad)"; + }; + + additionalOptions = mkOption { + default = ""; + example = '' + Option "RTCornerButton" "2" + Option "RBCornerButton" "3" + ''; + description = '' + Additional options for synaptics touchpad driver. + ''; + }; + + }; + + }; + + + config = mkIf cfg.enable { + + services.xserver.modules = [ pkgs.xorg.xf86inputsynaptics ]; + + environment.systemPackages = [ pkgs.xorg.xf86inputsynaptics ]; + + services.xserver.config = + '' + # Automatically enable the synaptics driver for all touchpads. + Section "InputClass" + Identifier "synaptics touchpad catchall" + MatchIsTouchpad "on" + ${optionalString (cfg.dev != null) ''MatchDevicePath "${cfg.dev}"''} + Driver "synaptics" + Option "MaxTapTime" "180" + Option "MaxTapMove" "220" + Option "MinSpeed" "${cfg.minSpeed}" + Option "MaxSpeed" "${cfg.maxSpeed}" + Option "AccelFactor" "${cfg.accelFactor}" + Option "TapButton1" "${if cfg.tapButtons then "1" else "0"}" + Option "TapButton2" "${if cfg.tapButtons then "2" else "0"}" + Option "TapButton3" "${if cfg.tapButtons then "3" else "0"}" + ${if cfg.tapButtons then "" else ''Option "MaxTapTime" "0"''} + Option "VertTwoFingerScroll" "${if cfg.twoFingerScroll then "1" else "0"}" + Option "HorizTwoFingerScroll" "${if cfg.twoFingerScroll then "1" else "0"}" + Option "VertEdgeScroll" "${if cfg.vertEdgeScroll then "1" else "0"}" + ${if cfg.palmDetect then ''Option "PalmDetect" "1"'' else ""} + ${if cfg.horizontalScroll then "" else ''Option "HorizScrollDelta" "0"''} + ${cfg.additionalOptions} + EndSection + ''; + + }; + +} diff --git a/nixos/modules/services/x11/hardware/wacom.nix b/nixos/modules/services/x11/hardware/wacom.nix new file mode 100644 index 0000000000000..dfc588cd21322 --- /dev/null +++ b/nixos/modules/services/x11/hardware/wacom.nix @@ -0,0 +1,47 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.wacom; + +in + +{ + + options = { + + services.xserver.wacom = { + + enable = mkOption { + default = false; + description = '' + Whether to enable the Wacom touchscreen/digitizer/tablet. + If you ever have any issues such as, try switching to terminal (ctrl-alt-F1) and back + which will make Xorg reconfigure the device ? + + If you're not satisfied by the default behaviour you can override + <option>environment.etc."X11/xorg.conf.d/50-wacom.conf"</option> in + configuration.nix easily. + ''; + }; + + }; + + }; + + + config = mkIf cfg.enable { + + environment.systemPackages = [ pkgs.xf86_input_wacom ]; # provides xsetwacom + + services.xserver.modules = [ pkgs.xf86_input_wacom ]; + + services.udev.packages = [ pkgs.xf86_input_wacom ]; + + environment.etc."X11/xorg.conf.d/50-wacom.conf".source = "${pkgs.xf86_input_wacom}/share/X11/xorg.conf.d/50-wacom.conf"; + + }; + +} diff --git a/nixos/modules/services/x11/terminal-server.nix b/nixos/modules/services/x11/terminal-server.nix new file mode 100644 index 0000000000000..ab05639aeca6b --- /dev/null +++ b/nixos/modules/services/x11/terminal-server.nix @@ -0,0 +1,66 @@ +# This module implements a terminal service based on ‘x11vnc’. It +# listens on port 5900 for VNC connections. It then presents a login +# screen to the user. If the user successfully authenticates, x11vnc +# checks to see if a X server is already running for that user. If +# not, a X server (Xvfb) is started for that user. The Xvfb instances +# persist across VNC sessions. + +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + # Wrap Xvfb to set some flags/variables. + xvfbWrapper = pkgs.writeScriptBin "Xvfb" + '' + #! ${pkgs.stdenv.shell} + export XKB_BINDIR=${pkgs.xorg.xkbcomp}/bin + export XORG_DRI_DRIVER_PATH=${pkgs.mesa}/lib/dri + exec ${pkgs.xorg.xorgserver}/bin/Xvfb "$@" -xkbdir "${pkgs.xkeyboard_config}/etc/X11/xkb" + ''; + + # ‘xinetd’ is insanely braindamaged in that it sends stderr to + # stdout. Thus requires just about any xinetd program to be + # wrapped to redirect its stderr. Sigh. + x11vncWrapper = pkgs.writeScriptBin "x11vnc-wrapper" + '' + #! ${pkgs.stdenv.shell} + export PATH=${makeSearchPath "bin" [ xvfbWrapper pkgs.gawk pkgs.which pkgs.openssl pkgs.xorg.xauth pkgs.nettools pkgs.shadow pkgs.procps pkgs.utillinux pkgs.bash ]}:$PATH + export FD_GEOM=1024x786x24 + exec ${pkgs.x11vnc}/bin/x11vnc -inetd -display WAIT:1024x786:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp -unixpw -ssl SAVE 2> /var/log/x11vnc.log + ''; + +in + +{ + + config = { + + services.xserver.enable = true; + + # Enable KDM. Any display manager will do as long as it supports XDMCP. + services.xserver.displayManager.kdm.enable = true; + services.xserver.displayManager.kdm.enableXDMCP = true; + services.xserver.displayManager.kdm.extraConfig = + '' + [General] + # We're headless, so don't bother starting an X server. + StaticServers= + + [Xdmcp] + Xaccess=${pkgs.writeText "Xaccess" "localhost"} + ''; + + services.xinetd.enable = true; + services.xinetd.services = singleton + { name = "x11vnc"; + port = 5900; + unlisted = true; + user = "root"; + server = "${x11vncWrapper}/bin/x11vnc-wrapper"; + }; + + }; + +} diff --git a/nixos/modules/services/x11/window-managers/awesome.nix b/nixos/modules/services/x11/window-managers/awesome.nix new file mode 100644 index 0000000000000..880ebf1eca6a0 --- /dev/null +++ b/nixos/modules/services/x11/window-managers/awesome.nix @@ -0,0 +1,42 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.windowManager.awesome; + +in + +{ + + ###### interface + + options = { + + services.xserver.windowManager.awesome.enable = mkOption { + default = false; + description = "Enable the Awesome window manager."; + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.windowManager.session = singleton + { name = "awesome"; + start = + '' + ${pkgs.awesome}/bin/awesome & + waitPID=$! + ''; + }; + + environment.x11Packages = [ pkgs.awesome ]; + + }; + +} diff --git a/nixos/modules/services/x11/window-managers/compiz.nix b/nixos/modules/services/x11/window-managers/compiz.nix new file mode 100644 index 0000000000000..209401f26468b --- /dev/null +++ b/nixos/modules/services/x11/window-managers/compiz.nix @@ -0,0 +1,63 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.windowManager.compiz; + xorg = config.services.xserver.package; + +in + +{ + + options = { + + services.xserver.windowManager.compiz = { + + enable = mkOption { + default = false; + description = "Enable the Compiz window manager."; + }; + + renderingFlag = mkOption { + default = ""; + example = "--indirect-rendering"; + description = "Pass the <option>--indirect-rendering</option> flag to Compiz."; + }; + + }; + + }; + + + config = mkIf cfg.enable { + + services.xserver.windowManager.session = singleton + { name = "compiz"; + start = + '' + # Start Compiz using the flat-file configuration backend + # (ccp). + export COMPIZ_PLUGINDIR=${config.system.path}/lib/compiz + export COMPIZ_METADATADIR=${config.system.path}/share/compiz + ${pkgs.compiz}/bin/compiz ccp ${cfg.renderingFlag} & + + # Start GTK-style window decorator. + ${pkgs.compiz}/bin/gtk-window-decorator & + ''; + }; + + environment.systemPackages = + [ pkgs.compiz + pkgs.compiz_ccsm + pkgs.compiz_plugins_main + pkgs.compiz_plugins_extra + pkgs.libcompizconfig # for the "ccp" plugin + ]; + + environment.pathsToLink = [ "/lib/compiz" "/share/compiz" ]; + + }; + +} diff --git a/nixos/modules/services/x11/window-managers/default.nix b/nixos/modules/services/x11/window-managers/default.nix new file mode 100644 index 0000000000000..c201b789ae48d --- /dev/null +++ b/nixos/modules/services/x11/window-managers/default.nix @@ -0,0 +1,61 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + cfg = config.services.xserver.windowManager; +in + +{ + imports = + [ ./compiz.nix + ./openbox.nix + ./metacity.nix + ./none.nix + ./twm.nix + ./wmii.nix + ./xmonad.nix + ./i3.nix + ./xbmc.nix + ]; + + options = { + + services.xserver.windowManager = { + + session = mkOption { + default = []; + example = [{ + name = "wmii"; + start = "..."; + }]; + description = '' + Internal option used to add some common line to window manager + scripts before forwarding the value to the + <varname>displayManager</varname>. + ''; + apply = map (d: d // { + manage = "window"; + }); + }; + + default = mkOption { + default = "none"; + example = "wmii"; + description = "Default window manager loaded if none have been chosen."; + merge = mergeOneOption; + apply = defaultWM: + if any (w: w.name == defaultWM) cfg.session then + defaultWM + else + throw "Default window manager (${defaultWM}) not found."; + }; + + }; + + }; + + config = { + services.xserver.displayManager.session = cfg.session; + }; +} diff --git a/nixos/modules/services/x11/window-managers/i3.nix b/nixos/modules/services/x11/window-managers/i3.nix new file mode 100644 index 0000000000000..6777a95ddc8ca --- /dev/null +++ b/nixos/modules/services/x11/window-managers/i3.nix @@ -0,0 +1,43 @@ +{ pkgs, config, ... }: + +with pkgs.lib; + +let + cfg = config.services.xserver.windowManager.i3; +in + +{ + options = { + services.xserver.windowManager.i3 = { + enable = mkOption { + default = false; + example = true; + description = "Enable the i3 tiling window manager."; + }; + + configFile = mkOption { + default = null; + type = types.nullOr types.path; + description = '' + Path to the i3 configuration file. + If left at the default value, $HOME/.i3/config will be used. + ''; + }; + }; + }; + + config = mkIf cfg.enable { + services.xserver.windowManager = { + session = [{ + name = "i3"; + start = " + ${pkgs.i3}/bin/i3 ${optionalString (cfg.configFile != null) + "-c \"${cfg.configFile}\"" + } & + waitPID=$! + "; + }]; + }; + environment.x11Packages = [ pkgs.i3 ]; + }; +} diff --git a/nixos/modules/services/x11/window-managers/icewm.nix b/nixos/modules/services/x11/window-managers/icewm.nix new file mode 100644 index 0000000000000..9da4a415fad1a --- /dev/null +++ b/nixos/modules/services/x11/window-managers/icewm.nix @@ -0,0 +1,42 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.windowManager.icewm; + +in + +{ + + ###### interface + + options = { + + services.xserver.windowManager.icewm.enable = mkOption { + default = false; + description = "Enable the IceWM window manager."; + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.windowManager.session = singleton + { name = "icewm"; + start = + '' + ${pkgs.icewm}/bin/icewm & + waitPID=$! + ''; + }; + + environment.x11Packages = [ pkgs.icewm ]; + + }; + +} diff --git a/nixos/modules/services/x11/window-managers/metacity.nix b/nixos/modules/services/x11/window-managers/metacity.nix new file mode 100644 index 0000000000000..712e2038594eb --- /dev/null +++ b/nixos/modules/services/x11/window-managers/metacity.nix @@ -0,0 +1,42 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.windowManager.metacity; + xorg = config.services.xserver.package; + gnome = pkgs.gnome; + +in + +{ + options = { + + services.xserver.windowManager.metacity.enable = mkOption { + default = false; + example = true; + description = "Enable the metacity window manager."; + }; + + }; + + config = mkIf cfg.enable { + + services.xserver.windowManager.session = singleton + { name = "metacity"; + start = '' + env LD_LIBRARY_PATH=${xorg.libX11}/lib:${xorg.libXext}/lib:/usr/lib/ + # !!! Hack: load the schemas for Metacity. + GCONF_CONFIG_SOURCE=xml::~/.gconf ${gnome.GConf}/bin/gconftool-2 \ + --makefile-install-rule ${gnome.metacity}/etc/gconf/schemas/*.schemas # */ + ${gnome.metacity}/bin/metacity & + waitPID=$! + ''; + }; + + environment.systemPackages = [ gnome.metacity ]; + + }; + +} diff --git a/nixos/modules/services/x11/window-managers/none.nix b/nixos/modules/services/x11/window-managers/none.nix new file mode 100644 index 0000000000000..84cf1d7707768 --- /dev/null +++ b/nixos/modules/services/x11/window-managers/none.nix @@ -0,0 +1,12 @@ +{ + services = { + xserver = { + windowManager = { + session = [{ + name = "none"; + start = ""; + }]; + }; + }; + }; +} diff --git a/nixos/modules/services/x11/window-managers/openbox.nix b/nixos/modules/services/x11/window-managers/openbox.nix new file mode 100644 index 0000000000000..ae34a938c4a04 --- /dev/null +++ b/nixos/modules/services/x11/window-managers/openbox.nix @@ -0,0 +1,30 @@ +{pkgs, config, ...}: + +let + inherit (pkgs.lib) mkOption mkIf; + cfg = config.services.xserver.windowManager.openbox; +in + +{ + options = { + services.xserver.windowManager.openbox = { + enable = mkOption { + default = false; + example = true; + description = "Enable the Openbox window manager."; + }; + }; + }; + + config = mkIf cfg.enable { + services.xserver.windowManager = { + session = [{ + name = "openbox"; + start = " + ${pkgs.openbox}/bin/openbox-session + "; + }]; + }; + environment.x11Packages = [ pkgs.openbox ]; + }; +} diff --git a/nixos/modules/services/x11/window-managers/twm.nix b/nixos/modules/services/x11/window-managers/twm.nix new file mode 100644 index 0000000000000..c1a99b97566f9 --- /dev/null +++ b/nixos/modules/services/x11/window-managers/twm.nix @@ -0,0 +1,42 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.windowManager.twm; + +in + +{ + + ###### interface + + options = { + + services.xserver.windowManager.twm.enable = mkOption { + default = false; + description = "Enable the twm window manager."; + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + services.xserver.windowManager.session = singleton + { name = "twm"; + start = + '' + ${pkgs.xorg.twm}/bin/twm & + waitPID=$! + ''; + }; + + environment.x11Packages = [ pkgs.xorg.twm ]; + + }; + +} diff --git a/nixos/modules/services/x11/window-managers/wmii.nix b/nixos/modules/services/x11/window-managers/wmii.nix new file mode 100644 index 0000000000000..b61521274fbaf --- /dev/null +++ b/nixos/modules/services/x11/window-managers/wmii.nix @@ -0,0 +1,47 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + cfg = config.services.xserver.windowManager.wmii; + +in + +{ + options = { + + services.xserver.windowManager.wmii.enable = mkOption { + default = false; + example = true; + description = "Enable the wmii window manager."; + }; + + }; + + config = mkIf cfg.enable { + + services.xserver.windowManager.session = singleton + # stop wmii by + # $wmiir xwrite /ctl quit + # this will cause wmii exiting with exit code 0 + # + # why this loop? + # wmii crashes once a month here. That doesn't matter that much + # wmii can recover very well. However without loop the x session terminates and then your workspace setup is + # lost and all applications running on X will terminate. + # Another use case is kill -9 wmii; after rotating screen. + # Note: we don't like kill for that purpose. But it works (-> subject "wmii and xrandr" on mailinglist) + { name = "wmii"; + start = '' + while :; do + ${pkgs.wmiiSnap}/bin/wmii && break + done + ''; + }; + + environment.systemPackages = [ pkgs.wmiiSnap ]; + + }; + +} diff --git a/nixos/modules/services/x11/window-managers/xbmc.nix b/nixos/modules/services/x11/window-managers/xbmc.nix new file mode 100644 index 0000000000000..46494202b404b --- /dev/null +++ b/nixos/modules/services/x11/window-managers/xbmc.nix @@ -0,0 +1,31 @@ +{pkgs, config, ...}: + +let + inherit (pkgs.lib) mkOption mkIf; + cfg = config.services.xserver.windowManager.xbmc; +in + +{ + options = { + services.xserver.windowManager.xbmc = { + enable = mkOption { + default = false; + example = true; + description = "Enable the xbmc multimedia center."; + }; + }; + }; + + config = mkIf cfg.enable { + services.xserver.windowManager = { + session = [{ + name = "xbmc"; + start = " + ${pkgs.xbmc}/bin/xbmc --lircdev /var/run/lirc/lircd --standalone & + waitPID=$! + "; + }]; + }; + environment.systemPackages = [ pkgs.xbmc ]; + }; +} diff --git a/nixos/modules/services/x11/window-managers/xmonad.nix b/nixos/modules/services/x11/window-managers/xmonad.nix new file mode 100644 index 0000000000000..2cbb5002d6cf7 --- /dev/null +++ b/nixos/modules/services/x11/window-managers/xmonad.nix @@ -0,0 +1,30 @@ +{pkgs, config, ...}: + +let + inherit (pkgs.lib) mkOption mkIf; + cfg = config.services.xserver.windowManager.xmonad; +in + +{ + options = { + services.xserver.windowManager.xmonad = { + enable = mkOption { + default = false; + example = true; + description = "Enable the xmonad window manager."; + }; + }; + }; + + config = { + services.xserver.windowManager = { + session = mkIf cfg.enable [{ + name = "xmonad"; + start = " + ${pkgs.haskellPackages.xmonad}/bin/xmonad & + waitPID=$! + "; + }]; + }; + }; +} diff --git a/nixos/modules/services/x11/xfs.conf b/nixos/modules/services/x11/xfs.conf new file mode 100644 index 0000000000000..13dcf803db294 --- /dev/null +++ b/nixos/modules/services/x11/xfs.conf @@ -0,0 +1,15 @@ +# font server configuration file +# $Xorg: config.cpp,v 1.3 2000/08/17 19:54:19 cpqbld Exp $ + +clone-self = on +use-syslog = off +error-file = /var/log/xfs.log +# in decipoints +default-point-size = 120 +default-resolutions = 75,75,100,100 + +# font cache control, specified in KB +cache-hi-mark = 2048 +cache-low-mark = 1433 +cache-balance = 70 +catalogue = /run/current-system/sw/share/X11-fonts/ diff --git a/nixos/modules/services/x11/xfs.nix b/nixos/modules/services/x11/xfs.nix new file mode 100644 index 0000000000000..f4a40dbb08fd9 --- /dev/null +++ b/nixos/modules/services/x11/xfs.nix @@ -0,0 +1,46 @@ +{ config, pkgs, ... }: + +with pkgs.lib; + +let + + configFile = ./xfs.conf; + +in + +{ + + ###### interface + + options = { + + services.xfs = { + + enable = mkOption { + default = false; + description = "Whether to enable the X Font Server."; + }; + + }; + + }; + + + ###### implementation + + config = mkIf config.services.xfs.enable ( + mkAssert config.fonts.enableFontDir " + Please enable fontDir (fonts.enableFontDir) to use xfs. + " { + + jobs.xfs = + { description = "X Font Server"; + + startOn = "started networking"; + + exec = "${pkgs.xorg.xfs}/bin/xfs -config ${configFile}"; + }; + + }); + +} diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix new file mode 100644 index 0000000000000..d42d7caaa06b0 --- /dev/null +++ b/nixos/modules/services/x11/xserver.nix @@ -0,0 +1,641 @@ +{ config, pkgs, pkgs_i686, ... }: + +with pkgs.lib; + +let + + kernelPackages = config.boot.kernelPackages; + + # Abbreviations. + cfg = config.services.xserver; + xorg = pkgs.xorg; + + + # Map video driver names to driver packages. + knownVideoDrivers = { + ati_unfree = { modules = [ kernelPackages.ati_drivers_x11 ]; driverName = "fglrx"; }; + nouveau = { modules = [ pkgs.xf86_video_nouveau ]; }; + nvidia = { modules = [ kernelPackages.nvidia_x11 ]; }; + nvidiaLegacy96 = { modules = [ kernelPackages.nvidia_x11_legacy96 ]; driverName = "nvidia"; }; + nvidiaLegacy173 = { modules = [ kernelPackages.nvidia_x11_legacy173 ]; driverName = "nvidia"; }; + nvidiaLegacy304 = { modules = [ kernelPackages.nvidia_x11_legacy304 ]; driverName = "nvidia"; }; + unichrome = { modules = [ pkgs.xorgVideoUnichrome ]; }; + virtualbox = { modules = [ kernelPackages.virtualboxGuestAdditions ]; driverName = "vboxvideo"; }; + }; + + driverNames = + optional (cfg.videoDriver != null) cfg.videoDriver ++ cfg.videoDrivers; + + drivers = flip map driverNames + (name: { inherit name; driverName = name; } // + attrByPath [name] (if (hasAttr ("xf86video" + name) xorg) then { modules = [(getAttr ("xf86video" + name) xorg) ]; } else throw "unknown video driver `${name}'") knownVideoDrivers); + + fontsForXServer = + config.fonts.fonts ++ + # 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 + ]; + + + # Just enumerate all heads without discarding XRandR output information. + xrandrHeads = let + mkHead = num: output: { + name = "multihead${toString num}"; + inherit output; + }; + in imap mkHead cfg.xrandrHeads; + + xrandrDeviceSection = flip concatMapStrings xrandrHeads (h: '' + Option "monitor-${h.output}" "${h.name}" + ''); + + # Here we chain every monitor from the left to right, so we have: + # m4 right of m3 right of m2 right of m1 .----.----.----.----. + # Which will end up in reverse ----------> | m1 | m2 | m3 | m4 | + # `----^----^----^----' + xrandrMonitorSections = let + mkMonitor = previous: current: previous ++ singleton { + inherit (current) name; + value = '' + Section "Monitor" + Identifier "${current.name}" + ${optionalString (previous != []) '' + Option "RightOf" "${(head previous).name}" + ''} + EndSection + ''; + }; + monitors = foldl mkMonitor [] xrandrHeads; + in concatMapStrings (getAttr "value") monitors; + + + configFile = pkgs.stdenv.mkDerivation { + name = "xserver.conf"; + + xfs = optionalString (cfg.useXFS != false) + ''FontPath "${toString cfg.useXFS}"''; + + inherit (cfg) config; + + buildCommand = + '' + echo 'Section "Files"' >> $out + echo $xfs >> $out + + for i in ${toString fontsForXServer}; do + if test "''${i:0:''${#NIX_STORE}}" == "$NIX_STORE"; then + for j in $(find $i -name fonts.dir); do + echo " FontPath \"$(dirname $j)\"" >> $out + done + fi + done + + for i in $(find ${toString cfg.modules} -type d); do + if test $(echo $i/*.so* | wc -w) -ne 0; then + echo " ModulePath \"$i\"" >> $out + fi + done + + echo 'EndSection' >> $out + + echo "$config" >> $out + ''; # */ + }; + + + checkAgent = mkAssert (!(cfg.startOpenSSHAgent && cfg.startGnuPGAgent)) + '' + The OpenSSH agent and GnuPG agent cannot be started both. + Choose between `startOpenSSHAgent' and `startGnuPGAgent'. + ''; + + checkPolkit = mkAssert config.security.polkit.enable + "X11 requires Polkit to be enabled (‘security.polkit.enable = true’)."; + + +in + +{ + + imports = + [ ./display-managers/default.nix + ./window-managers/default.nix + ./desktop-managers/default.nix + ]; + + + ###### interface + + options = { + + services.xserver = { + + enable = mkOption { + default = false; + description = '' + Whether to enable the X server. + ''; + }; + + autorun = mkOption { + default = true; + description = '' + Whether to start the X server automatically. + ''; + }; + + exportConfiguration = mkOption { + default = false; + description = '' + Whether to symlink the X server configuration under + <filename>/etc/X11/xorg.conf</filename>. + ''; + }; + + enableTCP = mkOption { + default = false; + description = '' + Whether to allow the X server to accept TCP connections. + ''; + }; + + modules = mkOption { + default = []; + example = [ pkgs.xf86_input_wacom ]; + description = "Packages to be added to the module search path of the X server."; + }; + + resolutions = mkOption { + default = []; + example = [ { x = 1600; y = 1200; } { x = 1024; y = 786; } ]; + description = '' + The screen resolutions for the X server. The first element + is the default resolution. If this list is empty, the X + server will automatically configure the resolution. + ''; + }; + + videoDriver = mkOption { + default = null; + example = "i810"; + description = '' + The name of the video driver for your graphics card. This + option is obsolete; please set the + <option>videoDrivers</option> instead. + ''; + }; + + videoDrivers = mkOption { + # !!! We'd like "nv" here, but it segfaults the X server. + default = [ "ati" "cirrus" "intel" "vesa" "vmware" ]; + example = [ "vesa" ]; + description = '' + The names of the video drivers that the X server should + support. The X server will try all of the drivers listed + here until it finds one that supports your video card. + ''; + }; + + vaapiDrivers = mkOption { + default = [ ]; + defaultText = "[ pkgs.vaapiIntel pkgs.vaapiVdpau ]"; + example = "[ pkgs.vaapiIntel pkgs.vaapiVdpau ]"; + description = '' + Packages providing libva acceleration drivers. + ''; + }; + + driSupport = mkOption { + default = true; + description = '' + Whether to enable accelerated OpenGL rendering through the + Direct Rendering Interface (DRI). + ''; + }; + + driSupport32Bit = mkOption { + default = false; + description = '' + On 64-bit systems, whether to support Direct Rendering for + 32-bit applications (such as Wine). This is currently only + supported for the <literal>nvidia</literal> driver and for + <literal>mesa</literal>. + ''; + }; + + startOpenSSHAgent = mkOption { + default = true; + description = '' + Whether to start the OpenSSH agent when you log in. The OpenSSH agent + remembers private keys for you so that you don't have to type in + passphrases every time you make an SSH connection. Use + <command>ssh-add</command> to add a key to the agent. + ''; + }; + + startGnuPGAgent = mkOption { + default = false; + description = '' + Whether to start the GnuPG agent when you log in. The GnuPG agent + remembers private keys for you so that you don't have to type in + passphrases every time you make an SSH connection or sign/encrypt + data. Use <command>ssh-add</command> to add a key to the agent. + ''; + }; + + layout = mkOption { + default = "us"; + description = '' + Keyboard layout. + ''; + }; + + xkbModel = mkOption { + default = "pc104"; + example = "presario"; + description = '' + Keyboard model. + ''; + }; + + xkbOptions = mkOption { + default = "terminate:ctrl_alt_bksp"; + example = "grp:caps_toggle, grp_led:scroll"; + description = '' + X keyboard options; layout switching goes here. + ''; + }; + + xkbVariant = mkOption { + default = ""; + example = "colemak"; + description = '' + X keyboard variant. + ''; + }; + + config = mkOption { + description = '' + The contents of the configuration file of the X server + (<filename>xorg.conf</filename>). + ''; + }; + + deviceSection = mkOption { + default = ""; + example = "VideoRAM 131072"; + description = "Contents of the first Device section of the X server configuration file."; + }; + + screenSection = mkOption { + default = ""; + example = '' + Option "RandRRotation" "on" + ''; + description = "Contents of the first Screen section of the X server configuration file."; + }; + + monitorSection = mkOption { + default = ""; + example = "HorizSync 28-49"; + description = "Contents of the first Monitor section of the X server configuration file."; + }; + + xrandrHeads = mkOption { + default = []; + example = [ "HDMI-0" "DVI-0" ]; + type = with types; listOf string; + description = '' + Simple multiple monitor configuration, just specify a list of XRandR + outputs which will be mapped from left to right in the order of the + list. + + Be careful using this option with multiple graphic adapters or with + drivers that have poor support for XRandR, unexpected things might + happen with those. + ''; + }; + + moduleSection = mkOption { + default = ""; + example = + '' + SubSection "extmod" + EndSubsection + ''; + description = "Contents of the Module section of the X server configuration file."; + }; + + serverLayoutSection = mkOption { + default = ""; + example = + '' + Option "AIGLX" "true" + ''; + description = "Contents of the ServerLayout section of the X server configuration file."; + }; + + extraDisplaySettings = mkOption { + default = ""; + example = "Virtual 2048 2048"; + description = "Lines to be added to every Display subsection of the Screen section."; + }; + + defaultDepth = mkOption { + default = 0; + example = 8; + description = "Default colour depth."; + }; + + useXFS = mkOption { + default = false; + example = "unix/:7100"; + description = "Determines how to connect to the X Font Server."; + }; + + 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."; + }; + + virtualScreen = mkOption { + default = null; + example = { x = 2048; y = 2048; }; + description = '' + Virtual screen size for Xrandr. + ''; + }; + + }; + + environment.x11Packages = mkOption { + default = []; + type = types.listOf types.package; + description = '' + List of packages added to the system when the X server is + activated (<option>services.xserver.enable</option>). + ''; + }; + + }; + + + + ###### implementation + + config = mkIf cfg.enable (checkAgent (checkPolkit { + + boot.extraModulePackages = + optional (elem "nvidia" driverNames) kernelPackages.nvidia_x11 ++ + optional (elem "nvidiaLegacy96" driverNames) kernelPackages.nvidia_x11_legacy96 ++ + optional (elem "nvidiaLegacy173" driverNames) kernelPackages.nvidia_x11_legacy173 ++ + optional (elem "nvidiaLegacy304" driverNames) kernelPackages.nvidia_x11_legacy304 ++ + optional (elem "virtualbox" driverNames) kernelPackages.virtualboxGuestAdditions ++ + optional (elem "ati_unfree" driverNames) kernelPackages.ati_drivers_x11; + + boot.blacklistedKernelModules = + optionals (elem "nvidia" driverNames) [ "nouveau" "nvidiafb" ]; + + environment.variables.LD_LIBRARY_PATH = + [ "/run/opengl-driver/lib" "/run/opengl-driver-32/lib" ]; + + environment.etc = + (optionals 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"; + } + ]) + ++ (optionals (elem "ati_unfree" driverNames) [ + + # according toiive on #ati you don't need the pcs, it is like registry... keeps old stuff to make your + # life harder ;) Still it seems to be required + { source = "${kernelPackages.ati_drivers_x11}/etc/ati"; + target = "ati"; + } + ]) + ++ (optionals (elem "nvidia" driverNames) [ + + { source = "${kernelPackages.nvidia_x11}/lib/vendors/nvidia.icd"; + target = "OpenCL/vendors/nvidia.icd"; + } + ]); + + environment.x11Packages = + [ xorg.xorgserver + xorg.xrandr + xorg.xrdb + xorg.setxkbmap + xorg.iceauth # required for KDE applications (it's called by dcopserver) + xorg.xlsclients + xorg.xset + xorg.xsetroot + xorg.xinput + xorg.xprop + pkgs.xterm + pkgs.xdg_utils + ] + ++ optional (elem "nvidia" driverNames) kernelPackages.nvidia_x11 + ++ optional (elem "nvidiaLegacy96" driverNames) kernelPackages.nvidia_x11_legacy96 + ++ optional (elem "nvidiaLegacy173" driverNames) kernelPackages.nvidia_x11_legacy173 + ++ optional (elem "nvidiaLegacy304" driverNames) kernelPackages.nvidia_x11_legacy304 + ++ optional (elem "virtualbox" driverNames) xorg.xrefresh + ++ optional (elem "ati_unfree" driverNames) kernelPackages.ati_drivers_x11; + + environment.systemPackages = config.environment.x11Packages; + + environment.pathsToLink = + [ "/etc/xdg" "/share/xdg" "/share/applications" "/share/icons" "/share/pixmaps" ]; + + systemd.defaultUnit = mkIf cfg.autorun "graphical.target"; + + systemd.services."display-manager" = + { description = "X11 Server"; + + after = [ "systemd-udev-settle.service" "local-fs.target" ]; + + restartIfChanged = false; + + environment = + { FONTCONFIG_FILE = "/etc/fonts/fonts.conf"; # !!! cleanup + XKB_BINDIR = "${xorg.xkbcomp}/bin"; # Needed for the Xkb extension. + XORG_DRI_DRIVER_PATH = "/run/opengl-driver/lib/dri"; # !!! Depends on the driver selected at runtime. + } // optionalAttrs (elem "nvidia" driverNames) { + LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.nvidia_x11}/lib"; + } // optionalAttrs (elem "nvidiaLegacy96" driverNames) { + LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.nvidia_x11_legacy96}/lib"; + } // optionalAttrs (elem "nvidiaLegacy173" driverNames) { + LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.nvidia_x11_legacy173}/lib"; + } // optionalAttrs (elem "nvidiaLegacy304" driverNames) { + LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.nvidia_x11_legacy304}/lib"; + } // optionalAttrs (elem "ati_unfree" driverNames) { + LD_LIBRARY_PATH = "${xorg.libX11}/lib:${xorg.libXext}/lib:${kernelPackages.ati_drivers_x11}/lib:${kernelPackages.ati_drivers_x11}/X11R6/lib64/modules/linux"; + #XORG_DRI_DRIVER_PATH = "${kernelPackages.ati_drivers_x11}/lib/dri"; # is ignored because ati drivers ship their own unpatched libglx.so ! + } // cfg.displayManager.job.environment; + + preStart = + '' + rm -f /run/opengl-driver{,-32} + ${optionalString (!cfg.driSupport32Bit) "ln -sf opengl-driver /run/opengl-driver-32"} + + ${# !!! The OpenGL driver depends on what's detected at runtime. + if elem "nvidia" driverNames then + '' + ln -sf ${kernelPackages.nvidia_x11} /run/opengl-driver + ${optionalString cfg.driSupport32Bit + "ln -sf ${pkgs_i686.linuxPackages.nvidia_x11.override { libsOnly = true; kernelDev = null; } } /run/opengl-driver-32"} + '' + else if elem "nvidiaLegacy96" driverNames then + "ln -sf ${kernelPackages.nvidia_x11_legacy96} /run/opengl-driver" + else if elem "nvidiaLegacy173" driverNames then + "ln -sf ${kernelPackages.nvidia_x11_legacy173} /run/opengl-driver" + else if elem "nvidiaLegacy304" driverNames then + '' + ln -sf ${kernelPackages.nvidia_x11_legacy304} /run/opengl-driver + ${optionalString cfg.driSupport32Bit + "ln -sf ${pkgs_i686.linuxPackages.nvidia_x11_legacy304.override { libsOnly = true; kernelDev = null; } } /run/opengl-driver-32"} + '' + else if elem "ati_unfree" driverNames then + "ln -sf ${kernelPackages.ati_drivers_x11} /run/opengl-driver" + else + '' + ${optionalString cfg.driSupport "ln -sf ${pkgs.mesa_drivers} /run/opengl-driver"} + ${optionalString cfg.driSupport32Bit + "ln -sf ${pkgs_i686.mesa_drivers} /run/opengl-driver-32"} + '' + } + + ${cfg.displayManager.job.preStart} + + rm -f /tmp/.X0-lock + ''; + + script = "${cfg.displayManager.job.execCmd}"; + }; + + 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.enableTCP) "-nolisten tcp"; + + services.xserver.modules = + concatLists (catAttrs "modules" drivers) ++ + [ xorg.xorgserver + xorg.xf86inputevdev + ]; + + services.xserver.config = + '' + Section "ServerFlags" + Option "AllowMouseOpenFail" "on" + EndSection + + Section "Module" + ${cfg.moduleSection} + EndSection + + Section "Monitor" + Identifier "Monitor[0]" + ${cfg.monitorSection} + EndSection + + Section "InputClass" + Identifier "Keyboard catchall" + MatchIsKeyboard "on" + Option "XkbRules" "base" + Option "XkbModel" "${cfg.xkbModel}" + Option "XkbLayout" "${cfg.layout}" + Option "XkbOptions" "${cfg.xkbOptions}" + Option "XkbVariant" "${cfg.xkbVariant}" + EndSection + + Section "ServerLayout" + Identifier "Layout[all]" + ${cfg.serverLayoutSection} + # Reference the Screen sections for each driver. This will + # cause the X server to try each in turn. + ${flip concatMapStrings drivers (d: '' + Screen "Screen-${d.name}[0]" + '')} + EndSection + + # For each supported driver, add a "Device" and "Screen" + # section. + ${flip concatMapStrings drivers (driver: '' + + Section "Device" + Identifier "Device-${driver.name}[0]" + Driver "${driver.driverName}" + ${cfg.deviceSection} + ${xrandrDeviceSection} + EndSection + + Section "Screen" + Identifier "Screen-${driver.name}[0]" + Device "Device-${driver.name}[0]" + ${optionalString (cfg.monitorSection != "") '' + Monitor "Monitor[0]" + ''} + + ${cfg.screenSection} + + ${optionalString (cfg.defaultDepth != 0) '' + DefaultDepth ${toString cfg.defaultDepth} + ''} + + ${optionalString (driver.name == "nvidia") '' + Option "RandRRotation" "on" + ''} + + ${optionalString + (driver.name != "virtualbox" && + (cfg.resolutions != [] || + cfg.extraDisplaySettings != "" || + cfg.virtualScreen != null)) + (let + f = depth: + '' + SubSection "Display" + Depth ${toString depth} + ${optionalString (cfg.resolutions != []) + "Modes ${concatMapStrings (res: ''"${toString res.x}x${toString res.y}"'') cfg.resolutions}"} + ${cfg.extraDisplaySettings} + ${optionalString (cfg.virtualScreen != null) + "Virtual ${toString cfg.virtualScreen.x} ${toString cfg.virtualScreen.y}"} + EndSubSection + ''; + in concatMapStrings f [8 16 24] + )} + + EndSection + '')} + + ${xrandrMonitorSections} + ''; + + })); + +} + |