aboutsummaryrefslogtreecommitdiff
path: root/nixpkgs/nixos/modules/services/x11
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/nixos/modules/services/x11')
-rw-r--r--nixpkgs/nixos/modules/services/x11/clight.nix115
-rw-r--r--nixpkgs/nixos/modules/services/x11/colord.nix41
-rw-r--r--nixpkgs/nixos/modules/services/x11/compton.nix287
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/default.nix113
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/enlightenment.nix100
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix352
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix30
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/lumina.nix45
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix67
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix110
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/maxx.nix31
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/none.nix7
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix218
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix266
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/surf-display.nix127
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix123
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/xfce4-14.nix156
-rw-r--r--nixpkgs/nixos/modules/services/x11/desktop-managers/xterm.nix38
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/auto.nix68
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/default.nix377
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix294
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix140
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix173
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix95
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix42
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix290
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix298
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/slim.nix156
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/startx.nix44
-rw-r--r--nixpkgs/nixos/modules/services/x11/display-managers/xpra.nix252
-rw-r--r--nixpkgs/nixos/modules/services/x11/extra-layouts.nix168
-rw-r--r--nixpkgs/nixos/modules/services/x11/fractalart.nix36
-rw-r--r--nixpkgs/nixos/modules/services/x11/gdk-pixbuf.nix45
-rw-r--r--nixpkgs/nixos/modules/services/x11/hardware/cmt.nix54
-rw-r--r--nixpkgs/nixos/modules/services/x11/hardware/libinput.nix247
-rw-r--r--nixpkgs/nixos/modules/services/x11/hardware/multitouch.nix94
-rw-r--r--nixpkgs/nixos/modules/services/x11/hardware/synaptics.nix213
-rw-r--r--nixpkgs/nixos/modules/services/x11/hardware/wacom.nix47
-rw-r--r--nixpkgs/nixos/modules/services/x11/redshift.nix129
-rw-r--r--nixpkgs/nixos/modules/services/x11/terminal-server.nix56
-rw-r--r--nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix58
-rw-r--r--nixpkgs/nixos/modules/services/x11/unclutter.nix74
-rw-r--r--nixpkgs/nixos/modules/services/x11/urxvtd.nix48
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/2bwm.nix37
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/afterstep.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix66
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix77
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix24
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/default.nix79
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix37
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/evilwm.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix54
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/fluxbox.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/fvwm.nix41
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix38
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/i3.nix78
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix27
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/jwm.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/leftwm.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/metacity.nix30
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/mwm.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/none.nix12
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/notion.nix26
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/openbox.nix24
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/oroborus.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/pekwm.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/ratpoison.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/sawfish.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/spectrwm.nix27
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/stumpwm.nix24
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/twm.nix37
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/windowlab.nix22
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/windowmaker.nix25
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/wmii.nix39
-rw-r--r--nixpkgs/nixos/modules/services/x11/window-managers/xmonad.nix97
-rw-r--r--nixpkgs/nixos/modules/services/x11/xautolock.nix140
-rw-r--r--nixpkgs/nixos/modules/services/x11/xbanish.nix31
-rw-r--r--nixpkgs/nixos/modules/services/x11/xfs.conf15
-rw-r--r--nixpkgs/nixos/modules/services/x11/xfs.nix46
-rw-r--r--nixpkgs/nixos/modules/services/x11/xserver.nix822
81 files changed, 7974 insertions, 0 deletions
diff --git a/nixpkgs/nixos/modules/services/x11/clight.nix b/nixpkgs/nixos/modules/services/x11/clight.nix
new file mode 100644
index 00000000000..4daf6d8d9db
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/clight.nix
@@ -0,0 +1,115 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+ cfg = config.services.clight;
+
+ toConf = v:
+ if builtins.isFloat v then toString v
+ else if isInt v then toString v
+ else if isBool v then boolToString v
+ else if isString v then ''"${escape [''"''] v}"''
+ else if isList v then "[ " + concatMapStringsSep ", " toConf v + " ]"
+ else abort "clight.toConf: unexpected type (v = ${v})";
+
+ clightConf = pkgs.writeText "clight.conf"
+ (concatStringsSep "\n" (mapAttrsToList
+ (name: value: "${toString name} = ${toConf value};")
+ (filterAttrs
+ (_: value: value != null)
+ cfg.settings)));
+in {
+ options.services.clight = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable clight or not.
+ '';
+ };
+
+ temperature = {
+ day = mkOption {
+ type = types.int;
+ default = 5500;
+ description = ''
+ Colour temperature to use during the day, between
+ <literal>1000</literal> and <literal>25000</literal> K.
+ '';
+ };
+ night = mkOption {
+ type = types.int;
+ default = 3700;
+ description = ''
+ Colour temperature to use at night, between
+ <literal>1000</literal> and <literal>25000</literal> K.
+ '';
+ };
+ };
+
+ settings = let
+ validConfigTypes = with types; either int (either str (either bool float));
+ in mkOption {
+ type = with types; attrsOf (nullOr (either validConfigTypes (listOf validConfigTypes)));
+ default = {};
+ example = { captures = 20; gamma_long_transition = true; ac_capture_timeouts = [ 120 300 60 ]; };
+ description = ''
+ Additional configuration to extend clight.conf. See
+ <link xlink:href="https://github.com/FedeDP/Clight/blob/master/Extra/clight.conf"/> for a
+ sample configuration file.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ boot.kernelModules = [ "i2c_dev" ];
+ environment.systemPackages = with pkgs; [ clight clightd ];
+ services.dbus.packages = with pkgs; [ clight clightd ];
+ services.upower.enable = true;
+
+ services.clight.settings = {
+ gamma_temp = with cfg.temperature; mkDefault [ day night ];
+ } // (optionalAttrs (config.location.provider == "manual") {
+ latitude = mkDefault config.location.latitude;
+ longitude = mkDefault config.location.longitude;
+ });
+
+ services.geoclue2.appConfig.clightc = {
+ isAllowed = true;
+ isSystem = true;
+ };
+
+ systemd.services.clightd = {
+ requires = [ "polkit.service" ];
+ wantedBy = [ "multi-user.target" ];
+
+ description = "Bus service to manage various screen related properties (gamma, dpms, backlight)";
+ serviceConfig = {
+ Type = "dbus";
+ BusName = "org.clightd.clightd";
+ Restart = "on-failure";
+ RestartSec = 5;
+ ExecStart = ''
+ ${pkgs.clightd}/bin/clightd
+ '';
+ };
+ };
+
+ systemd.user.services.clight = {
+ after = [ "upower.service" "clightd.service" ];
+ wants = [ "upower.service" "clightd.service" ];
+ partOf = [ "graphical-session.target" ];
+ wantedBy = [ "graphical-session.target" ];
+
+ description = "C daemon to adjust screen brightness to match ambient brightness, as computed capturing frames from webcam";
+ serviceConfig = {
+ Restart = "on-failure";
+ RestartSec = 5;
+ ExecStart = ''
+ ${pkgs.clight}/bin/clight --conf-file ${clightConf}
+ '';
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/colord.nix b/nixpkgs/nixos/modules/services/x11/colord.nix
new file mode 100644
index 00000000000..cf113ad2af8
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/colord.nix
@@ -0,0 +1,41 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.colord;
+
+in {
+
+ options = {
+
+ services.colord = {
+ enable = mkEnableOption "colord, the color management daemon";
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+
+ environment.systemPackages = [ pkgs.colord ];
+
+ services.dbus.packages = [ pkgs.colord ];
+
+ services.udev.packages = [ pkgs.colord ];
+
+ systemd.packages = [ pkgs.colord ];
+
+ environment.etc."tmpfiles.d/colord.conf".source = "${pkgs.colord}/lib/tmpfiles.d/colord.conf";
+
+ users.users.colord = {
+ isSystemUser = true;
+ home = "/var/lib/colord";
+ group = "colord";
+ };
+
+ users.groups.colord = {};
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/compton.nix b/nixpkgs/nixos/modules/services/x11/compton.nix
new file mode 100644
index 00000000000..a94a76ff0c0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/compton.nix
@@ -0,0 +1,287 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+with builtins;
+
+let
+
+ cfg = config.services.compton;
+
+ pairOf = x: with types; addCheck (listOf x) (y: length y == 2);
+
+ floatBetween = a: b: with lib; with types;
+ addCheck str (x: versionAtLeast x a && versionOlder x b);
+
+ toConf = attrs: concatStringsSep "\n"
+ (mapAttrsToList
+ (k: v: let
+ sep = if isAttrs v then ":" else "=";
+ # Basically a tinkered lib.generators.mkKeyValueDefault
+ mkValueString = v:
+ if isBool v then boolToString v
+ else if isInt v then toString v
+ else if isFloat v then toString v
+ else if isString v then ''"${escape [ ''"'' ] v}"''
+ else if isList v then "[ "
+ + concatMapStringsSep " , " mkValueString v
+ + " ]"
+ else if isAttrs v then "{ "
+ + concatStringsSep " "
+ (mapAttrsToList
+ (key: value: "${toString key}=${mkValueString value};")
+ v)
+ + " }"
+ else abort "compton.mkValueString: unexpected type (v = ${v})";
+ in "${escape [ sep ] k}${sep}${mkValueString v};")
+ attrs);
+
+ configFile = pkgs.writeText "compton.conf" (toConf cfg.settings);
+
+in {
+
+ options.services.compton = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether of not to enable Compton as the X.org composite manager.
+ '';
+ };
+
+ fade = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Fade windows in and out.
+ '';
+ };
+
+ fadeDelta = mkOption {
+ type = types.addCheck types.int (x: x > 0);
+ default = 10;
+ example = 5;
+ description = ''
+ Time between fade animation step (in ms).
+ '';
+ };
+
+ fadeSteps = mkOption {
+ type = pairOf (floatBetween "0.01" "1.01");
+ default = [ "0.028" "0.03" ];
+ example = [ "0.04" "0.04" ];
+ description = ''
+ Opacity change between fade steps (in and out).
+ (numbers in range 0.01 - 1.0)
+ '';
+ };
+
+ fadeExclude = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [
+ "window_type *= 'menu'"
+ "name ~= 'Firefox$'"
+ "focused = 1"
+ ];
+ description = ''
+ List of conditions of windows that should not be faded.
+ See <literal>compton(1)</literal> man page for more examples.
+ '';
+ };
+
+ shadow = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Draw window shadows.
+ '';
+ };
+
+ shadowOffsets = mkOption {
+ type = pairOf types.int;
+ default = [ (-15) (-15) ];
+ example = [ (-10) (-15) ];
+ description = ''
+ Left and right offset for shadows (in pixels).
+ '';
+ };
+
+ shadowOpacity = mkOption {
+ type = floatBetween "0.0" "1.01";
+ default = "0.75";
+ example = "0.8";
+ description = ''
+ Window shadows opacity (number in range 0.0 - 1.0).
+ '';
+ };
+
+ shadowExclude = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [
+ "window_type *= 'menu'"
+ "name ~= 'Firefox$'"
+ "focused = 1"
+ ];
+ description = ''
+ List of conditions of windows that should have no shadow.
+ See <literal>compton(1)</literal> man page for more examples.
+ '';
+ };
+
+ activeOpacity = mkOption {
+ type = floatBetween "0.0" "1.01";
+ default = "1.0";
+ example = "0.8";
+ description = ''
+ Opacity of active windows (number in range 0.0 - 1.0).
+ '';
+ };
+
+ inactiveOpacity = mkOption {
+ type = floatBetween "0.1" "1.01";
+ default = "1.0";
+ example = "0.8";
+ description = ''
+ Opacity of inactive windows (number in range 0.1 - 1.0).
+ '';
+ };
+
+ menuOpacity = mkOption {
+ type = floatBetween "0.0" "1.01";
+ default = "1.0";
+ example = "0.8";
+ description = ''
+ Opacity of dropdown and popup menu (number in range 0.0 - 1.0).
+ '';
+ };
+
+ wintypes = mkOption {
+ type = types.attrs;
+ default = { popup_menu = { opacity = cfg.menuOpacity; }; dropdown_menu = { opacity = cfg.menuOpacity; }; };
+ example = {};
+ description = ''
+ Rules for specific window types.
+ '';
+ };
+
+ opacityRules = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [
+ "95:class_g = 'URxvt' && !_NET_WM_STATE@:32a"
+ "0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'"
+ ];
+ description = ''
+ Rules that control the opacity of windows, in format PERCENT:PATTERN.
+ '';
+ };
+
+ backend = mkOption {
+ type = types.enum [ "glx" "xrender" "xr_glx_hybrid" ];
+ default = "xrender";
+ description = ''
+ Backend to use: <literal>glx</literal>, <literal>xrender</literal> or <literal>xr_glx_hybrid</literal>.
+ '';
+ };
+
+ vSync = mkOption {
+ type = with types; either bool
+ (enum [ "none" "drm" "opengl" "opengl-oml" "opengl-swc" "opengl-mswc" ]);
+ default = false;
+ apply = x:
+ let
+ res = x != "none";
+ msg = "The type of services.compton.vSync has changed to bool:"
+ + " interpreting ${x} as ${boolToString res}";
+ in
+ if isBool x then x
+ else warn msg res;
+
+ description = ''
+ Enable vertical synchronization. Chooses the best method
+ (drm, opengl, opengl-oml, opengl-swc, opengl-mswc) automatically.
+ The bool value should be used, the others are just for backwards compatibility.
+ '';
+ };
+
+ refreshRate = mkOption {
+ type = types.addCheck types.int (x: x >= 0);
+ default = 0;
+ example = 60;
+ description = ''
+ Screen refresh rate (0 = automatically detect).
+ '';
+ };
+
+ settings = let
+ configTypes = with types; oneOf [ bool int float str ];
+ # types.loaOf converts lists to sets
+ loaOf = t: with types; either (listOf t) (attrsOf t);
+ in mkOption {
+ type = loaOf (types.either configTypes (loaOf (types.either configTypes (loaOf configTypes))));
+ default = {};
+ description = ''
+ Additional Compton configuration.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.compton.settings = let
+ # Hard conversion to float, literally lib.toInt but toFloat
+ toFloat = str: let
+ may_be_float = builtins.fromJSON str;
+ in if builtins.isFloat may_be_float
+ then may_be_float
+ else throw "Could not convert ${str} to float.";
+ in {
+ # fading
+ fading = mkDefault cfg.fade;
+ fade-delta = mkDefault cfg.fadeDelta;
+ fade-in-step = mkDefault (toFloat (elemAt cfg.fadeSteps 0));
+ fade-out-step = mkDefault (toFloat (elemAt cfg.fadeSteps 1));
+ fade-exclude = mkDefault cfg.fadeExclude;
+
+ # shadows
+ shadow = mkDefault cfg.shadow;
+ shadow-offset-x = mkDefault (elemAt cfg.shadowOffsets 0);
+ shadow-offset-y = mkDefault (elemAt cfg.shadowOffsets 1);
+ shadow-opacity = mkDefault (toFloat cfg.shadowOpacity);
+ shadow-exclude = mkDefault cfg.shadowExclude;
+
+ # opacity
+ active-opacity = mkDefault (toFloat cfg.activeOpacity);
+ inactive-opacity = mkDefault (toFloat cfg.inactiveOpacity);
+
+ wintypes = mkDefault cfg.wintypes;
+
+ opacity-rule = mkDefault cfg.opacityRules;
+
+ # other options
+ backend = mkDefault cfg.backend;
+ vsync = mkDefault cfg.vSync;
+ refresh-rate = mkDefault cfg.refreshRate;
+ };
+
+ systemd.user.services.compton = {
+ description = "Compton composite manager";
+ wantedBy = [ "graphical-session.target" ];
+ partOf = [ "graphical-session.target" ];
+
+ # Temporarily fixes corrupt colours with Mesa 18
+ environment = mkIf (cfg.backend == "glx") {
+ allow_rgb10_configs = "false";
+ };
+
+ serviceConfig = {
+ ExecStart = "${pkgs.compton}/bin/compton --config ${configFile}";
+ RestartSec = 3;
+ Restart = "always";
+ };
+ };
+
+ environment.systemPackages = [ pkgs.compton ];
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/default.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/default.nix
new file mode 100644
index 00000000000..dfb84113e13
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/default.nix
@@ -0,0 +1,113 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ xcfg = config.services.xserver;
+ cfg = xcfg.desktopManager;
+
+ # If desktop manager `d' isn't capable of setting a background and
+ # the xserver is enabled, `feh' or `xsetroot' are used as a fallback.
+ needBGCond = d: ! (d ? bgSupport && d.bgSupport) && xcfg.enable;
+
+in
+
+{
+ # Note: the order in which desktop manager modules are imported here
+ # determines the default: later modules (if enabled) are preferred.
+ # E.g., if Plasma 5 is enabled, it supersedes xterm.
+ imports = [
+ ./none.nix ./xterm.nix ./xfce.nix ./xfce4-14.nix ./plasma5.nix ./lumina.nix
+ ./lxqt.nix ./enlightenment.nix ./gnome3.nix ./kodi.nix ./maxx.nix
+ ./mate.nix ./pantheon.nix ./surf-display.nix
+ ];
+
+ options = {
+
+ services.xserver.desktopManager = {
+
+ wallpaper = {
+ mode = mkOption {
+ type = types.enum [ "center" "fill" "max" "scale" "tile" ];
+ default = "scale";
+ example = "fill";
+ description = ''
+ The file <filename>~/.background-image</filename> is used as a background image.
+ This option specifies the placement of this image onto your desktop.
+
+ Possible values:
+ <literal>center</literal>: Center the image on the background. If it is too small, it will be surrounded by a black border.
+ <literal>fill</literal>: Like <literal>scale</literal>, but preserves aspect ratio by zooming the image until it fits. Either a horizontal or a vertical part of the image will be cut off.
+ <literal>max</literal>: Like <literal>fill</literal>, but scale the image to the maximum size that fits the screen with black borders on one side.
+ <literal>scale</literal>: Fit the file into the background without repeating it, cutting off stuff or using borders. But the aspect ratio is not preserved either.
+ <literal>tile</literal>: Tile (repeat) the image in case it is too small for the screen.
+ '';
+ };
+
+ combineScreens = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ When set to <literal>true</literal> the wallpaper will stretch across all screens.
+ When set to <literal>false</literal> the wallpaper is duplicated to all screens.
+ '';
+ };
+ };
+
+ session = mkOption {
+ internal = true;
+ 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 [ -e $HOME/.background-image ]; then
+ ${pkgs.feh}/bin/feh --bg-${cfg.wallpaper.mode} ${optionalString cfg.wallpaper.combineScreens "--no-xinerama"} $HOME/.background-image
+ else
+ # Use a solid black background as fallback
+ ${pkgs.xorg.xsetroot}/bin/xsetroot -solid black
+ fi
+ '';
+ }) list;
+ needBGPackages = [] != filter needBGCond list;
+ };
+ };
+
+ default = mkOption {
+ type = types.str;
+ default = "";
+ example = "none";
+ description = "Default desktop manager loaded if none have been chosen.";
+ 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
+ builtins.trace ''
+ Default desktop manager (${defaultDM}) not found at evaluation time.
+ These are the known valid session names:
+ ${concatMapStringsSep "\n " (w: "services.xserver.desktopManager.default = \"${w.name}\";") cfg.session.list}
+ It's also possible the default can be found in one of these packages:
+ ${concatMapStringsSep "\n " (p: p.name) config.services.xserver.displayManager.extraSessionFilePackages}
+ '' defaultDM;
+ };
+
+ };
+
+ };
+
+ config.services.xserver.displayManager.session = cfg.session.list;
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/enlightenment.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/enlightenment.nix
new file mode 100644
index 00000000000..3745069f6ea
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/enlightenment.nix
@@ -0,0 +1,100 @@
+{ config, pkgs, lib, ... }:
+
+with lib;
+
+let
+
+ e = pkgs.enlightenment;
+ xcfg = config.services.xserver;
+ cfg = xcfg.desktopManager.enlightenment;
+ GST_PLUGIN_PATH = lib.makeSearchPathOutput "lib" "lib/gstreamer-1.0" [
+ pkgs.gst_all_1.gst-plugins-base
+ pkgs.gst_all_1.gst-plugins-good
+ pkgs.gst_all_1.gst-plugins-bad
+ pkgs.gst_all_1.gst-libav ];
+
+in
+
+{
+ options = {
+
+ services.xserver.desktopManager.enlightenment.enable = mkOption {
+ default = false;
+ description = "Enable the Enlightenment desktop environment.";
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+
+ environment.systemPackages = [
+ e.efl e.enlightenment
+ e.terminology e.econnman
+ pkgs.xorg.xauth # used by kdesu
+ pkgs.gtk2 # To get GTK's themes.
+ pkgs.tango-icon-theme
+
+ pkgs.gnome2.gnome_icon_theme
+ pkgs.xorg.xcursorthemes
+ ];
+
+ environment.pathsToLink = [
+ "/etc/enlightenment"
+ "/share/enlightenment"
+ "/share/elementary"
+ "/share/locale"
+ ];
+
+ services.xserver.desktopManager.session = [
+ { name = "Enlightenment";
+ start = ''
+ export XDG_MENU_PREFIX=e-
+
+ export GST_PLUGIN_PATH="${GST_PLUGIN_PATH}"
+
+ # make available for D-BUS user services
+ #export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}:${config.system.path}/share:${e.efl}/share
+
+ # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
+ ${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
+
+ exec ${e.enlightenment}/bin/enlightenment_start
+ '';
+ }];
+
+ security.wrappers = (import "${e.enlightenment}/e-wrappers.nix").security.wrappers;
+
+ environment.etc = singleton
+ { source = xcfg.xkbDir;
+ target = "X11/xkb";
+ };
+
+ fonts.fonts = [ pkgs.dejavu_fonts pkgs.ubuntu_font_family ];
+
+ services.udisks2.enable = true;
+ services.upower.enable = config.powerManagement.enable;
+
+ services.dbus.packages = [ e.efl ];
+
+ systemd.user.services.efreet =
+ { enable = true;
+ description = "org.enlightenment.Efreet";
+ serviceConfig =
+ { ExecStart = "${e.efl}/bin/efreetd";
+ StandardOutput = "null";
+ };
+ };
+
+ systemd.user.services.ethumb =
+ { enable = true;
+ description = "org.enlightenment.Ethumb";
+ serviceConfig =
+ { ExecStart = "${e.efl}/bin/ethumbd";
+ StandardOutput = "null";
+ };
+ };
+
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix
new file mode 100644
index 00000000000..30c5250221c
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/gnome3.nix
@@ -0,0 +1,352 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.desktopManager.gnome3;
+ serviceCfg = config.services.gnome3;
+
+ # Prioritize nautilus by default when opening directories
+ mimeAppsList = pkgs.writeTextFile {
+ name = "gnome-mimeapps";
+ destination = "/share/applications/mimeapps.list";
+ text = ''
+ [Default Applications]
+ inode/directory=nautilus.desktop;org.gnome.Nautilus.desktop
+ '';
+ };
+
+ nixos-gsettings-desktop-schemas = let
+ defaultPackages = with pkgs; [ gsettings-desktop-schemas gnome3.gnome-shell ];
+ in
+ pkgs.runCommand "nixos-gsettings-desktop-schemas" { preferLocalBuild = true; }
+ ''
+ mkdir -p $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas
+
+ ${concatMapStrings
+ (pkg: "cp -rf ${pkg}/share/gsettings-schemas/*/glib-2.0/schemas/*.xml $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas\n")
+ (defaultPackages ++ cfg.extraGSettingsOverridePackages)}
+
+ chmod -R a+w $out/share/gsettings-schemas/nixos-gsettings-overrides
+ cat - > $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/nixos-defaults.gschema.override <<- EOF
+ [org.gnome.desktop.background]
+ picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray}/share/artwork/gnome/nix-wallpaper-simple-dark-gray.png'
+
+ [org.gnome.desktop.screensaver]
+ picture-uri='file://${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bottom.png'
+
+ [org.gnome.shell]
+ favorite-apps=[ 'org.gnome.Epiphany.desktop', 'org.gnome.Geary.desktop', 'org.gnome.Music.desktop', 'org.gnome.Photos.desktop', 'org.gnome.Nautilus.desktop', 'org.gnome.Software.desktop' ]
+
+ ${cfg.extraGSettingsOverrides}
+ EOF
+
+ ${pkgs.glib.dev}/bin/glib-compile-schemas $out/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas/
+ '';
+
+ flashbackEnabled = cfg.flashback.enableMetacity || length cfg.flashback.customSessions > 0;
+
+in
+
+{
+
+ options = {
+
+ services.gnome3 = {
+ core-os-services.enable = mkEnableOption "essential services for GNOME3";
+ core-shell.enable = mkEnableOption "GNOME Shell services";
+ core-utilities.enable = mkEnableOption "GNOME core utilities";
+ games.enable = mkEnableOption "GNOME games";
+ };
+
+ services.xserver.desktopManager.gnome3 = {
+ enable = mkOption {
+ default = false;
+ description = "Enable Gnome 3 desktop manager.";
+ };
+
+ sessionPath = mkOption {
+ default = [];
+ example = literalExample "[ pkgs.gnome3.gpaste ]";
+ description = ''
+ Additional list of packages to be added to the session search path.
+ Useful for GNOME Shell extensions or GSettings-conditional autostart.
+
+ Note that this should be a last resort; patching the package is preferred (see GPaste).
+ '';
+ apply = list: list ++ [ pkgs.gnome3.gnome-shell pkgs.gnome3.gnome-shell-extensions ];
+ };
+
+ extraGSettingsOverrides = mkOption {
+ default = "";
+ type = types.lines;
+ description = "Additional gsettings overrides.";
+ };
+
+ extraGSettingsOverridePackages = mkOption {
+ default = [];
+ type = types.listOf types.path;
+ description = "List of packages for which gsettings are overridden.";
+ };
+
+ debug = mkEnableOption "gnome-session debug messages";
+
+ flashback = {
+ enableMetacity = mkEnableOption "the standard GNOME Flashback session with Metacity";
+
+ customSessions = mkOption {
+ type = types.listOf (types.submodule {
+ options = {
+ wmName = mkOption {
+ type = types.str;
+ description = "The filename-compatible name of the window manager to use.";
+ example = "xmonad";
+ };
+
+ wmLabel = mkOption {
+ type = types.str;
+ description = "The pretty name of the window manager to use.";
+ example = "XMonad";
+ };
+
+ wmCommand = mkOption {
+ type = types.str;
+ description = "The executable of the window manager to use.";
+ example = "\${pkgs.haskellPackages.xmonad}/bin/xmonad";
+ };
+ };
+ });
+ default = [];
+ description = "Other GNOME Flashback sessions to enable.";
+ };
+ };
+ };
+
+ environment.gnome3.excludePackages = mkOption {
+ default = [];
+ example = literalExample "[ pkgs.gnome3.totem ]";
+ type = types.listOf types.package;
+ description = "Which packages gnome should exclude from the default environment";
+ };
+
+ };
+
+ config = mkMerge [
+ (mkIf (cfg.enable || flashbackEnabled) {
+ services.gnome3.core-os-services.enable = true;
+ services.gnome3.core-shell.enable = true;
+ services.gnome3.core-utilities.enable = mkDefault true;
+
+ services.xserver.displayManager.extraSessionFilePackages = [ pkgs.gnome3.gnome-session ];
+
+ environment.extraInit = ''
+ ${concatMapStrings (p: ''
+ if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
+ export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
+ fi
+
+ if [ -d "${p}/lib/girepository-1.0" ]; then
+ export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
+ fi
+ '') cfg.sessionPath}
+ '';
+
+ environment.systemPackages = cfg.sessionPath;
+
+ environment.variables.GNOME_SESSION_DEBUG = mkIf cfg.debug "1";
+
+ # Override GSettings schemas
+ environment.variables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
+
+ # If gnome3 is installed, build vim for gtk3 too.
+ nixpkgs.config.vim.gui = "gtk3";
+ })
+
+ (mkIf flashbackEnabled {
+ services.xserver.displayManager.extraSessionFilePackages = map
+ (wm: pkgs.gnome3.gnome-flashback.mkSessionForWm {
+ inherit (wm) wmName wmLabel wmCommand;
+ }) (optional cfg.flashback.enableMetacity {
+ wmName = "metacity";
+ wmLabel = "Metacity";
+ wmCommand = "${pkgs.gnome3.metacity}/bin/metacity";
+ } ++ cfg.flashback.customSessions);
+
+ security.pam.services.gnome-screensaver = {
+ enableGnomeKeyring = true;
+ };
+
+ services.dbus.packages = [
+ pkgs.gnome3.gnome-screensaver
+ ];
+ })
+
+ (mkIf serviceCfg.core-os-services.enable {
+ hardware.bluetooth.enable = mkDefault true;
+ hardware.pulseaudio.enable = mkDefault true;
+ programs.dconf.enable = true;
+ security.polkit.enable = true;
+ services.accounts-daemon.enable = true;
+ services.dleyna-renderer.enable = mkDefault true;
+ services.dleyna-server.enable = mkDefault true;
+ services.gnome3.at-spi2-core.enable = true;
+ services.gnome3.evolution-data-server.enable = true;
+ services.gnome3.gnome-keyring.enable = true;
+ services.gnome3.gnome-online-accounts.enable = mkDefault true;
+ services.gnome3.gnome-online-miners.enable = true;
+ services.gnome3.tracker-miners.enable = mkDefault true;
+ services.gnome3.tracker.enable = mkDefault true;
+ services.hardware.bolt.enable = mkDefault true;
+ services.packagekit.enable = mkDefault true;
+ services.udisks2.enable = true;
+ services.upower.enable = config.powerManagement.enable;
+ services.xserver.libinput.enable = mkDefault true; # for controlling touchpad settings via gnome control center
+
+ xdg.portal.enable = true;
+ xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
+
+ networking.networkmanager.enable = mkDefault true;
+
+ # Use the correct gnome3 packageSet
+ networking.networkmanager.basePackages = {
+ inherit (pkgs) networkmanager modemmanager wpa_supplicant crda;
+ inherit (pkgs.gnome3) networkmanager-openvpn networkmanager-vpnc
+ networkmanager-openconnect networkmanager-fortisslvpn
+ networkmanager-iodine networkmanager-l2tp;
+ };
+
+ services.xserver.updateDbusEnvironment = true;
+
+ # Needed for themes and backgrounds
+ environment.pathsToLink = [
+ "/share" # TODO: https://github.com/NixOS/nixpkgs/issues/47173
+ ];
+ })
+
+ (mkIf serviceCfg.core-shell.enable {
+ services.colord.enable = mkDefault true;
+ services.gnome3.chrome-gnome-shell.enable = mkDefault true;
+ services.gnome3.glib-networking.enable = true;
+ services.gnome3.gnome-remote-desktop.enable = mkDefault true;
+ services.gnome3.gnome-settings-daemon.enable = true;
+ services.gnome3.gnome-user-share.enable = mkDefault true;
+ services.gnome3.rygel.enable = mkDefault true;
+ services.gvfs.enable = true;
+ services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
+ services.telepathy.enable = mkDefault true;
+ systemd.packages = [ pkgs.gnome3.vino ];
+
+ services.avahi.enable = mkDefault true;
+
+ xdg.portal.extraPortals = [ pkgs.gnome3.gnome-shell ];
+
+ services.geoclue2.enable = mkDefault true;
+ services.geoclue2.enableDemoAgent = false; # GNOME has its own geoclue agent
+
+ services.geoclue2.appConfig.gnome-datetime-panel = {
+ isAllowed = true;
+ isSystem = true;
+ };
+ services.geoclue2.appConfig.gnome-color-panel = {
+ isAllowed = true;
+ isSystem = true;
+ };
+ services.geoclue2.appConfig."org.gnome.Shell" = {
+ isAllowed = true;
+ isSystem = true;
+ };
+
+ fonts.fonts = with pkgs; [
+ cantarell-fonts
+ dejavu_fonts
+ source-code-pro # Default monospace font in 3.32
+ source-sans-pro
+ ];
+
+ # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/gnome-3-32/elements/core/meta-gnome-core-shell.bst
+ environment.systemPackages = with pkgs.gnome3; [
+ adwaita-icon-theme
+ gnome-backgrounds
+ gnome-bluetooth
+ gnome-color-manager
+ gnome-control-center
+ gnome-getting-started-docs
+ gnome-shell
+ gnome-shell-extensions
+ gnome-themes-extra
+ gnome-user-docs
+ pkgs.orca
+ pkgs.glib # for gsettings
+ pkgs.gnome-menus
+ pkgs.gtk3.out # for gtk-launch
+ pkgs.hicolor-icon-theme
+ pkgs.shared-mime-info # for update-mime-database
+ pkgs.xdg-user-dirs # Update user dirs as described in http://freedesktop.org/wiki/Software/xdg-user-dirs/
+ vino
+ ];
+ })
+
+ # Adapt from https://gitlab.gnome.org/GNOME/gnome-build-meta/blob/gnome-3-32/elements/core/meta-gnome-core-utilities.bst
+ (mkIf serviceCfg.core-utilities.enable {
+ environment.systemPackages = (with pkgs.gnome3; removePackagesByName [
+ baobab
+ cheese
+ eog
+ epiphany
+ geary
+ gedit
+ gnome-calculator
+ gnome-calendar
+ gnome-characters
+ gnome-clocks
+ gnome-contacts
+ gnome-font-viewer
+ gnome-logs
+ gnome-maps
+ gnome-music
+ gnome-photos
+ gnome-screenshot
+ gnome-software
+ gnome-system-monitor
+ gnome-weather
+ nautilus
+ simple-scan
+ totem
+ yelp
+ # Unsure if sensible for NixOS
+ /* gnome-boxes */
+ ] config.environment.gnome3.excludePackages);
+
+ # Enable default programs
+ programs.evince.enable = mkDefault true;
+ programs.file-roller.enable = mkDefault true;
+ programs.gnome-disks.enable = mkDefault true;
+ programs.gnome-terminal.enable = mkDefault true;
+ programs.seahorse.enable = mkDefault true;
+ services.gnome3.sushi.enable = mkDefault true;
+
+ # Let nautilus find extensions
+ # TODO: Create nautilus-with-extensions package
+ environment.variables.NAUTILUS_EXTENSION_DIR = "${config.system.path}/lib/nautilus/extensions-3.0";
+
+ # Override default mimeapps for nautilus
+ environment.variables.XDG_DATA_DIRS = [ "${mimeAppsList}/share" ];
+
+ environment.pathsToLink = [
+ "/share/nautilus-python/extensions"
+ ];
+ })
+
+ (mkIf serviceCfg.games.enable {
+ environment.systemPackages = (with pkgs.gnome3; removePackagesByName [
+ aisleriot atomix five-or-more four-in-a-row gnome-chess gnome-klotski
+ gnome-mahjongg gnome-mines gnome-nibbles gnome-robots gnome-sudoku
+ gnome-taquin gnome-tetravex hitori iagno lightsoff quadrapassel
+ swell-foop tali
+ ] config.environment.gnome3.excludePackages);
+ })
+ ];
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix
new file mode 100644
index 00000000000..65a7b9c628e
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/kodi.nix
@@ -0,0 +1,30 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.desktopManager.kodi;
+in
+
+{
+ options = {
+ services.xserver.desktopManager.kodi = {
+ enable = mkOption {
+ default = false;
+ description = "Enable the kodi multimedia center.";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.desktopManager.session = [{
+ name = "kodi";
+ start = ''
+ ${pkgs.kodi}/bin/kodi --lircdev /run/lirc/lircd --standalone &
+ waitPID=$!
+ '';
+ }];
+
+ environment.systemPackages = [ pkgs.kodi ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/lumina.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/lumina.nix
new file mode 100644
index 00000000000..2224bcd5a2a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/lumina.nix
@@ -0,0 +1,45 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ xcfg = config.services.xserver;
+ cfg = xcfg.desktopManager.lumina;
+
+in
+
+{
+ options = {
+
+ services.xserver.desktopManager.lumina.enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable the Lumina desktop manager";
+ };
+
+ };
+
+
+ config = mkIf cfg.enable {
+
+ services.xserver.desktopManager.session = singleton {
+ name = "lumina";
+ start = ''
+ exec ${pkgs.lumina.lumina}/bin/start-lumina-desktop
+ '';
+ };
+
+ environment.systemPackages =
+ pkgs.lumina.preRequisitePackages ++
+ pkgs.lumina.corePackages;
+
+ # Link some extra directories in /run/current-system/software/share
+ environment.pathsToLink = [
+ "/share/lumina"
+ # FIXME: modules should link subdirs of `/share` rather than relying on this
+ "/share"
+ ];
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix
new file mode 100644
index 00000000000..bf53082b267
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/lxqt.nix
@@ -0,0 +1,67 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ xcfg = config.services.xserver;
+ cfg = xcfg.desktopManager.lxqt;
+
+in
+
+{
+ options = {
+
+ services.xserver.desktopManager.lxqt.enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable the LXQt desktop manager";
+ };
+
+ environment.lxqt.excludePackages = mkOption {
+ default = [];
+ example = literalExample "[ pkgs.lxqt.qterminal ]";
+ type = types.listOf types.package;
+ description = "Which LXQt packages to exclude from the default environment";
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+
+ services.xserver.desktopManager.session = singleton {
+ name = "lxqt";
+ bgSupport = true;
+ start = ''
+ # Upstream installs default configuration files in
+ # $prefix/share/lxqt instead of $prefix/etc/xdg, (arguably)
+ # giving distributors freedom to ship custom default
+ # configuration files more easily. In order to let the session
+ # manager find them the share subdirectory is added to the
+ # XDG_CONFIG_DIRS environment variable.
+ #
+ # For an explanation see
+ # https://github.com/lxqt/lxqt/issues/1521#issuecomment-405097453
+ #
+ export XDG_CONFIG_DIRS=$XDG_CONFIG_DIRS''${XDG_CONFIG_DIRS:+:}${config.system.path}/share
+
+ exec ${pkgs.lxqt.lxqt-session}/bin/startlxqt
+ '';
+ };
+
+ environment.systemPackages =
+ pkgs.lxqt.preRequisitePackages ++
+ pkgs.lxqt.corePackages ++
+ (pkgs.gnome3.removePackagesByName
+ pkgs.lxqt.optionalPackages
+ config.environment.lxqt.excludePackages);
+
+ # Link some extra directories in /run/current-system/software/share
+ environment.pathsToLink = [ "/share" ];
+
+ services.gvfs.enable = true;
+ services.gvfs.package = pkgs.gvfs;
+
+ services.upower.enable = config.powerManagement.enable;
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
new file mode 100644
index 00000000000..4563583e070
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/mate.nix
@@ -0,0 +1,110 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ addToXDGDirs = p: ''
+ if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
+ export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
+ fi
+
+ if [ -d "${p}/lib/girepository-1.0" ]; then
+ export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
+ fi
+ '';
+
+ xcfg = config.services.xserver;
+ cfg = xcfg.desktopManager.mate;
+
+in
+
+{
+ options = {
+
+ services.xserver.desktopManager.mate = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable the MATE desktop environment";
+ };
+
+ debug = mkEnableOption "mate-session debug messages";
+ };
+
+ environment.mate.excludePackages = mkOption {
+ default = [];
+ example = literalExample "[ pkgs.mate.mate-terminal pkgs.mate.pluma ]";
+ type = types.listOf types.package;
+ description = "Which MATE packages to exclude from the default environment";
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+
+ services.xserver.desktopManager.session = singleton {
+ name = "mate";
+ bgSupport = true;
+ start = ''
+ export XDG_MENU_PREFIX=mate-
+
+ # Let caja find extensions
+ export CAJA_EXTENSION_DIRS=$CAJA_EXTENSION_DIRS''${CAJA_EXTENSION_DIRS:+:}${config.system.path}/lib/caja/extensions-2.0
+
+ # Let caja extensions find gsettings schemas
+ ${concatMapStrings (p: ''
+ if [ -d "${p}/lib/caja/extensions-2.0" ]; then
+ ${addToXDGDirs p}
+ fi
+ '')
+ config.environment.systemPackages
+ }
+
+ # Let mate-panel find applets
+ export MATE_PANEL_APPLETS_DIR=$MATE_PANEL_APPLETS_DIR''${MATE_PANEL_APPLETS_DIR:+:}${config.system.path}/share/mate-panel/applets
+ export MATE_PANEL_EXTRA_MODULES=$MATE_PANEL_EXTRA_MODULES''${MATE_PANEL_EXTRA_MODULES:+:}${config.system.path}/lib/mate-panel/applets
+
+ # Add mate-control-center paths to some XDG variables because its schemas are needed by mate-settings-daemon, and mate-settings-daemon is a dependency for mate-control-center (that is, they are mutually recursive)
+ ${addToXDGDirs pkgs.mate.mate-control-center}
+
+ ${pkgs.mate.mate-session-manager}/bin/mate-session ${optionalString cfg.debug "--debug"} &
+ waitPID=$!
+ '';
+ };
+
+ environment.systemPackages =
+ pkgs.mate.basePackages ++
+ (pkgs.gnome3.removePackagesByName
+ pkgs.mate.extraPackages
+ config.environment.mate.excludePackages) ++
+ [
+ pkgs.desktop-file-utils
+ pkgs.glib
+ pkgs.gtk3.out
+ pkgs.shared-mime-info
+ pkgs.xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
+ ];
+
+ programs.dconf.enable = true;
+ # Shell integration for VTE terminals
+ programs.bash.vteIntegration = mkDefault true;
+ programs.zsh.vteIntegration = mkDefault true;
+
+ # Mate uses this for printing
+ programs.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
+
+ services.gnome3.at-spi2-core.enable = true;
+ services.gnome3.gnome-keyring.enable = true;
+ services.gnome3.gnome-settings-daemon.enable = true;
+ services.gnome3.gnome-settings-daemon.package = pkgs.mate.mate-settings-daemon;
+ services.gvfs.enable = true;
+ services.upower.enable = config.powerManagement.enable;
+
+ security.pam.services.mate-screensaver.unixAuth = true;
+
+ environment.pathsToLink = [ "/share" ];
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/maxx.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/maxx.nix
new file mode 100644
index 00000000000..1c04104df41
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/maxx.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ xcfg = config.services.xserver;
+ cfg = xcfg.desktopManager.maxx;
+in {
+ options.services.xserver.desktopManager.maxx = {
+ enable = mkEnableOption "MaXX desktop environment";
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = [ pkgs.maxx ];
+
+ # there is hardcoded path in binaries
+ system.activationScripts.setup-maxx = ''
+ mkdir -p /opt
+ ln -sfn ${pkgs.maxx}/opt/MaXX /opt
+ '';
+
+ services.xserver.desktopManager.session = [
+ { name = "MaXX";
+ start = ''
+ exec ${pkgs.maxx}/opt/MaXX/etc/skel/Xsession.dt
+ '';
+ }];
+ };
+
+ meta.maintainers = [ maintainers.gnidorah ];
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/none.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/none.nix
new file mode 100644
index 00000000000..af7a376ae02
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/none.nix
@@ -0,0 +1,7 @@
+{
+ services.xserver.desktopManager.session =
+ [ { name = "none";
+ start = "";
+ }
+ ];
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
new file mode 100644
index 00000000000..d80ea9a53e8
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/pantheon.nix
@@ -0,0 +1,218 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.desktopManager.pantheon;
+
+ nixos-gsettings-desktop-schemas = pkgs.pantheon.elementary-gsettings-schemas.override {
+ extraGSettingsOverridePackages = cfg.extraGSettingsOverridePackages;
+ extraGSettingsOverrides = cfg.extraGSettingsOverrides;
+ };
+
+in
+
+{
+
+ meta.maintainers = pkgs.pantheon.maintainers;
+
+ options = {
+
+ services.xserver.desktopManager.pantheon = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable the pantheon desktop manager";
+ };
+
+ sessionPath = mkOption {
+ default = [];
+ example = literalExample "[ pkgs.gnome3.gpaste ]";
+ description = ''
+ Additional list of packages to be added to the session search path.
+ Useful for GSettings-conditional autostart.
+
+ Note that this should be a last resort; patching the package is preferred (see GPaste).
+ '';
+ apply = list: list ++
+ [
+ pkgs.pantheon.pantheon-agent-geoclue2
+ ];
+ };
+
+ extraGSettingsOverrides = mkOption {
+ default = "";
+ type = types.lines;
+ description = "Additional gsettings overrides.";
+ };
+
+ extraGSettingsOverridePackages = mkOption {
+ default = [];
+ type = types.listOf types.path;
+ description = "List of packages for which gsettings are overridden.";
+ };
+
+ debug = mkEnableOption "gnome-session debug messages";
+
+ };
+
+ environment.pantheon.excludePackages = mkOption {
+ default = [];
+ example = literalExample "[ pkgs.pantheon.elementary-camera ]";
+ type = types.listOf types.package;
+ description = "Which packages pantheon should exclude from the default environment";
+ };
+
+ };
+
+
+ config = mkIf cfg.enable {
+
+ services.xserver.displayManager.extraSessionFilePackages = [ pkgs.pantheon.elementary-session-settings ];
+
+ # Ensure lightdm is used when Pantheon is enabled
+ # Without it screen locking will be nonfunctional because of the use of lightlocker
+
+ warnings = optional (config.services.xserver.displayManager.lightdm.enable != true)
+ ''
+ Using Pantheon without LightDM as a displayManager will break screenlocking from the UI.
+ '';
+
+ services.xserver.displayManager.lightdm.greeters.pantheon.enable = mkDefault true;
+
+ # If not set manually Pantheon session cannot be started
+ # Known issue of https://github.com/NixOS/nixpkgs/pull/43992
+ services.xserver.desktopManager.default = mkForce "pantheon";
+
+ services.xserver.displayManager.sessionCommands = ''
+ if test "$XDG_CURRENT_DESKTOP" = "Pantheon"; then
+ ${concatMapStrings (p: ''
+ if [ -d "${p}/share/gsettings-schemas/${p.name}" ]; then
+ export XDG_DATA_DIRS=$XDG_DATA_DIRS''${XDG_DATA_DIRS:+:}${p}/share/gsettings-schemas/${p.name}
+ fi
+
+ if [ -d "${p}/lib/girepository-1.0" ]; then
+ export GI_TYPELIB_PATH=$GI_TYPELIB_PATH''${GI_TYPELIB_PATH:+:}${p}/lib/girepository-1.0
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH''${LD_LIBRARY_PATH:+:}${p}/lib
+ fi
+ '') cfg.sessionPath}
+ fi
+ '';
+
+ hardware.bluetooth.enable = mkDefault true;
+ hardware.pulseaudio.enable = mkDefault true;
+ security.polkit.enable = true;
+ services.accounts-daemon.enable = true;
+ services.bamf.enable = true;
+ services.colord.enable = mkDefault true;
+ services.pantheon.files.enable = mkDefault true;
+ services.tumbler.enable = mkDefault true;
+ services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
+ services.dbus.packages = [
+ pkgs.pantheon.switchboard-plug-power
+ ];
+ services.pantheon.contractor.enable = mkDefault true;
+ services.gnome3.at-spi2-core.enable = true;
+ services.gnome3.evolution-data-server.enable = true;
+ services.gnome3.glib-networking.enable = true;
+ # TODO: gnome-keyring's xdg autostarts will still be in the environment (from elementary-session-settings) if disabled forcefully
+ services.gnome3.gnome-keyring.enable = true;
+ services.gnome3.gnome-settings-daemon.enable = true;
+ services.gnome3.gnome-settings-daemon.package = pkgs.pantheon.elementary-settings-daemon;
+ services.gvfs.enable = true;
+ services.gnome3.rygel.enable = mkDefault true;
+ services.gsignond.enable = mkDefault true;
+ services.gsignond.plugins = with pkgs.gsignondPlugins; [ lastfm mail oauth ];
+ services.udisks2.enable = true;
+ services.upower.enable = config.powerManagement.enable;
+ services.xserver.libinput.enable = mkDefault true;
+ services.xserver.updateDbusEnvironment = true;
+ services.zeitgeist.enable = mkDefault true;
+ services.geoclue2.enable = mkDefault true;
+ # pantheon has pantheon-agent-geoclue2
+ services.geoclue2.enableDemoAgent = false;
+ services.geoclue2.appConfig."io.elementary.desktop.agent-geoclue2" = {
+ isAllowed = true;
+ isSystem = true;
+ };
+
+ programs.dconf.enable = true;
+ programs.evince.enable = mkDefault true;
+ programs.file-roller.enable = mkDefault true;
+ # Otherwise you can't store NetworkManager Secrets with
+ # "Store the password only for this user"
+ programs.nm-applet.enable = true;
+
+ # Shell integration for VTE terminals
+ programs.bash.vteIntegration = mkDefault true;
+ programs.zsh.vteIntegration = mkDefault true;
+
+ # Harmonize Qt5 applications under Pantheon
+ qt5.enable = true;
+ qt5.platformTheme = "gnome";
+ qt5.style = "adwaita";
+
+ networking.networkmanager.enable = mkDefault true;
+ networking.networkmanager.basePackages =
+ { inherit (pkgs) networkmanager modemmanager wpa_supplicant crda;
+ inherit (pkgs.gnome3) networkmanager-openvpn networkmanager-vpnc
+ networkmanager-openconnect networkmanager-fortisslvpn
+ networkmanager-iodine networkmanager-l2tp; };
+
+ # Override GSettings schemas
+ environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-desktop-schemas}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
+
+ environment.sessionVariables.GNOME_SESSION_DEBUG = optionalString cfg.debug "1";
+
+ # Settings from elementary-default-settings
+ environment.sessionVariables.GTK_CSD = "1";
+ environment.sessionVariables.GTK_MODULES = "pantheon-filechooser-module";
+ environment.etc."gtk-3.0/settings.ini".source = "${pkgs.pantheon.elementary-default-settings}/etc/gtk-3.0/settings.ini";
+
+ environment.pathsToLink = [
+ # FIXME: modules should link subdirs of `/share` rather than relying on this
+ "/share"
+ ];
+
+ environment.systemPackages =
+ pkgs.pantheon.artwork ++ pkgs.pantheon.desktop ++ pkgs.pantheon.services ++ cfg.sessionPath
+ ++ (with pkgs; gnome3.removePackagesByName
+ ([
+ gnome3.geary
+ gnome3.epiphany
+ gnome3.gnome-font-viewer
+ ] ++ pantheon.apps) config.environment.pantheon.excludePackages)
+ ++ (with pkgs;
+ [
+ adwaita-qt
+ desktop-file-utils
+ glib
+ glib-networking
+ gnome-menus
+ gnome3.adwaita-icon-theme
+ gtk3.out
+ hicolor-icon-theme
+ lightlocker
+ onboard
+ plank
+ qgnomeplatform
+ shared-mime-info
+ sound-theme-freedesktop
+ xdg-user-dirs
+ ]);
+
+ fonts.fonts = with pkgs; [
+ open-sans
+ roboto-mono
+ pantheon.elementary-redacted-script # needed by screenshot-tool
+ ];
+
+ fonts.fontconfig.defaultFonts = {
+ monospace = [ "Roboto Mono" ];
+ sansSerif = [ "Open Sans" ];
+ };
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
new file mode 100644
index 00000000000..b10755df4dc
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/plasma5.nix
@@ -0,0 +1,266 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ xcfg = config.services.xserver;
+ cfg = xcfg.desktopManager.plasma5;
+
+ inherit (pkgs) kdeApplications plasma5 libsForQt5 qt5;
+
+in
+
+{
+ options = {
+
+ services.xserver.desktopManager.plasma5 = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable the Plasma 5 (KDE 5) desktop environment.";
+ };
+
+ phononBackend = mkOption {
+ type = types.enum [ "gstreamer" "vlc" ];
+ default = "gstreamer";
+ example = "vlc";
+ description = "Phonon audio backend to install.";
+ };
+
+ enableQt4Support = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Enable support for Qt 4-based applications. Particularly, install a
+ default backend for Phonon.
+ '';
+ };
+
+ };
+
+ };
+
+
+ config = mkMerge [
+ (mkIf cfg.enable {
+ services.xserver.desktopManager.session = singleton {
+ name = "plasma5";
+ bgSupport = true;
+ start = ''
+ # Load PulseAudio module for routing support.
+ # See http://colin.guthr.ie/2009/10/so-how-does-the-kde-pulseaudio-support-work-anyway/
+ ${optionalString config.hardware.pulseaudio.enable ''
+ ${getBin config.hardware.pulseaudio.package}/bin/pactl load-module module-device-manager "do_routing=1"
+ ''}
+
+ if [ -f "$HOME/.config/kdeglobals" ]
+ then
+ # Remove extraneous font style names.
+ # See also: https://phabricator.kde.org/D9070
+ ${getBin pkgs.gnused}/bin/sed -i "$HOME/.config/kdeglobals" \
+ -e '/^fixed=/ s/,Regular$//' \
+ -e '/^font=/ s/,Regular$//' \
+ -e '/^menuFont=/ s/,Regular$//' \
+ -e '/^smallestReadableFont=/ s/,Regular$//' \
+ -e '/^toolBarFont=/ s/,Regular$//'
+ fi
+
+ exec "${getBin plasma5.plasma-workspace}/bin/startkde"
+ '';
+ };
+
+ security.wrappers = {
+ kcheckpass.source = "${lib.getBin plasma5.kscreenlocker}/libexec/kcheckpass";
+ start_kdeinit.source = "${lib.getBin pkgs.kinit}/libexec/kf5/start_kdeinit";
+ kwin_wayland = {
+ source = "${lib.getBin plasma5.kwin}/bin/kwin_wayland";
+ capabilities = "cap_sys_nice+ep";
+ };
+ };
+
+ environment.systemPackages = with pkgs; with qt5; with libsForQt5; with plasma5; with kdeApplications;
+ [
+ frameworkintegration
+ kactivities
+ kauth
+ kcmutils
+ kconfig
+ kconfigwidgets
+ kcoreaddons
+ kdoctools
+ kdbusaddons
+ kdeclarative
+ kded
+ kdesu
+ kdnssd
+ kemoticons
+ kfilemetadata
+ kglobalaccel
+ kguiaddons
+ kiconthemes
+ kidletime
+ kimageformats
+ kinit
+ kio
+ kjobwidgets
+ knewstuff
+ knotifications
+ knotifyconfig
+ kpackage
+ kparts
+ kpeople
+ krunner
+ kservice
+ ktextwidgets
+ kwallet
+ kwallet-pam
+ kwalletmanager
+ kwayland
+ kwidgetsaddons
+ kxmlgui
+ kxmlrpcclient
+ plasma-framework
+ solid
+ sonnet
+ threadweaver
+
+ breeze-qt5
+ kactivitymanagerd
+ kde-cli-tools
+ kdecoration
+ kdeplasma-addons
+ kgamma5
+ khotkeys
+ kinfocenter
+ kmenuedit
+ kscreen
+ kscreenlocker
+ ksysguard
+ kwayland
+ kwin
+ kwrited
+ libkscreen
+ libksysguard
+ milou
+ plasma-integration
+ polkit-kde-agent
+ systemsettings
+
+ plasma-desktop
+ plasma-workspace
+ plasma-workspace-wallpapers
+
+ dolphin
+ dolphin-plugins
+ ffmpegthumbs
+ kdegraphics-thumbnailers
+ khelpcenter
+ kio-extras
+ konsole
+ oxygen
+ print-manager
+
+ breeze-icons
+ pkgs.hicolor-icon-theme
+
+ kde-gtk-config breeze-gtk
+
+ qtvirtualkeyboard
+
+ xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
+ ]
+
+ # Phonon audio backend
+ ++ lib.optional (cfg.phononBackend == "gstreamer") libsForQt5.phonon-backend-gstreamer
+ ++ lib.optional (cfg.phononBackend == "gstreamer" && cfg.enableQt4Support) pkgs.phonon-backend-gstreamer
+ ++ lib.optional (cfg.phononBackend == "vlc") libsForQt5.phonon-backend-vlc
+ ++ lib.optional (cfg.phononBackend == "vlc" && cfg.enableQt4Support) pkgs.phonon-backend-vlc
+
+ # Optional hardware support features
+ ++ lib.optionals config.hardware.bluetooth.enable [ bluedevil bluez-qt ]
+ ++ lib.optional config.networking.networkmanager.enable plasma-nm
+ ++ lib.optional config.hardware.pulseaudio.enable plasma-pa
+ ++ lib.optional config.powerManagement.enable powerdevil
+ ++ lib.optional config.services.colord.enable colord-kde
+ ++ lib.optionals config.services.samba.enable [ kdenetwork-filesharing pkgs.samba ];
+
+ environment.pathsToLink = [
+ # FIXME: modules should link subdirs of `/share` rather than relying on this
+ "/share"
+ ];
+
+ environment.etc = singleton {
+ source = xcfg.xkbDir;
+ target = "X11/xkb";
+ };
+
+ # Enable GTK applications to load SVG icons
+ services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
+
+ fonts.fonts = with pkgs; [ noto-fonts hack-font ];
+ fonts.fontconfig.defaultFonts = {
+ monospace = [ "Hack" "Noto Mono" ];
+ sansSerif = [ "Noto Sans" ];
+ serif = [ "Noto Serif" ];
+ };
+
+ programs.ssh.askPassword = mkDefault "${plasma5.ksshaskpass.out}/bin/ksshaskpass";
+
+ # Enable helpful DBus services.
+ services.udisks2.enable = true;
+ services.upower.enable = config.powerManagement.enable;
+ services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
+ services.xserver.libinput.enable = mkDefault true;
+
+ # Extra UDEV rules used by Solid
+ services.udev.packages = [
+ pkgs.libmtp
+ pkgs.media-player-info
+ ];
+
+ services.xserver.displayManager.sddm = {
+ theme = mkDefault "breeze";
+ };
+
+ security.pam.services.kde = { allowNullPassword = true; };
+
+ # Doing these one by one seems silly, but we currently lack a better
+ # construct for handling common pam configs.
+ security.pam.services.gdm.enableKwallet = true;
+ security.pam.services.kdm.enableKwallet = true;
+ security.pam.services.lightdm.enableKwallet = true;
+ security.pam.services.sddm.enableKwallet = true;
+ security.pam.services.slim.enableKwallet = true;
+
+ xdg.portal.enable = true;
+ xdg.portal.extraPortals = [ pkgs.xdg-desktop-portal-kde ];
+
+ # Update the start menu for each user that is currently logged in
+ system.userActivationScripts.plasmaSetup = ''
+ # 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/.cache/icon-cache.kcache
+
+ # xdg-desktop-settings generates this empty file but
+ # it makes kbuildsyscoca5 fail silently. To fix this
+ # remove that menu if it exists.
+ rm -fv $HOME/.config/menus/applications-merged/xdg-desktop-menu-dummy.menu
+
+ # Remove the kbuildsyscoca5 cache. It will be regenerated
+ # immediately after. This is necessary for kbuildsyscoca5 to
+ # recognize that software that has been removed.
+ rm -fv $HOME/.cache/ksycoca*
+
+ ${pkgs.libsForQt5.kservice}/bin/kbuildsycoca5
+ '';
+ })
+ ];
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/surf-display.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/surf-display.nix
new file mode 100644
index 00000000000..140dde828da
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/surf-display.nix
@@ -0,0 +1,127 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.desktopManager.surf-display;
+
+ surfDisplayConf = ''
+ # Surf Kiosk Display: Wrap around surf browser and turn your
+ # system into a browser screen in KIOSK-mode.
+
+ # default download URI for all display screens if not configured individually
+ DEFAULT_WWW_URI="${cfg.defaultWwwUri}"
+
+ # Enforce fixed resolution for all displays (default: not set):
+ #DEFAULT_RESOLUTION="1920x1080"
+
+ # HTTP proxy URL, if needed (default: not set).
+ #HTTP_PROXY_URL="http://webcache:3128"
+
+ # Setting for internal inactivity timer to restart surf-display
+ # if the user goes inactive/idle.
+ INACTIVITY_INTERVAL="${builtins.toString cfg.inactivityInterval}"
+
+ # log to syslog instead of .xsession-errors
+ LOG_TO_SYSLOG="yes"
+
+ # Launch pulseaudio daemon if not already running.
+ WITH_PULSEAUDIO="yes"
+
+ # screensaver settings, see "man 1 xset" for possible options
+ SCREENSAVER_SETTINGS="${cfg.screensaverSettings}"
+
+ # disable right and middle pointer device click in browser sessions while keeping
+ # scrolling wheels' functionality intact... (consider "pointer" subcommand on
+ # xmodmap man page for details).
+ POINTER_BUTTON_MAP="${cfg.pointerButtonMap}"
+
+ # Hide idle mouse pointer.
+ HIDE_IDLE_POINTER="${cfg.hideIdlePointer}"
+
+ ${cfg.extraConfig}
+ '';
+
+in {
+ options = {
+ services.xserver.desktopManager.surf-display = {
+ enable = mkEnableOption "surf-display as a kiosk browser session";
+
+ defaultWwwUri = mkOption {
+ type = types.str;
+ default = "${pkgs.surf-display}/share/surf-display/empty-page.html";
+ example = "https://www.example.com/";
+ description = "Default URI to display.";
+ };
+
+ inactivityInterval = mkOption {
+ type = types.int;
+ default = 300;
+ example = "0";
+ description = ''
+ Setting for internal inactivity timer to restart surf-display if the
+ user goes inactive/idle to get a fresh session for the next user of
+ the kiosk.
+
+ If this value is set to zero, the whole feature of restarting due to
+ inactivity is disabled.
+ '';
+ };
+
+ screensaverSettings = mkOption {
+ type = types.separatedString " ";
+ default = "";
+ description = ''
+ Screensaver settings, see <literal>man 1 xset</literal> for possible options.
+ '';
+ };
+
+ pointerButtonMap = mkOption {
+ type = types.str;
+ default = "1 0 0 4 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0";
+ description = ''
+ Disable right and middle pointer device click in browser sessions
+ while keeping scrolling wheels' functionality intact. See pointer
+ subcommand on <literal>man xmodmap</literal> for details.
+ '';
+ };
+
+ hideIdlePointer = mkOption {
+ type = types.str;
+ default = "yes";
+ example = "no";
+ description = "Hide idle mouse pointer.";
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ # Enforce fixed resolution for all displays (default: not set):
+ DEFAULT_RESOLUTION="1920x1080"
+
+ # HTTP proxy URL, if needed (default: not set).
+ HTTP_PROXY_URL="http://webcache:3128"
+
+ # Configure individual display screens with host specific parameters:
+ DISPLAYS['display-host-0']="www_uri=https://www.displayserver.comany.net/display-1/index.html"
+ DISPLAYS['display-host-1']="www_uri=https://www.displayserver.comany.net/display-2/index.html"
+ DISPLAYS['display-host-2']="www_uri=https://www.displayserver.comany.net/display-3/index.html|res=1920x1280"
+ DISPLAYS['display-host-3']="www_uri=https://www.displayserver.comany.net/display-4/index.html"|res=1280x1024"
+ DISPLAYS['display-host-local-file']="www_uri=file:///usr/share/doc/surf-display/empty-page.html"
+ '';
+ description = ''
+ Extra configuration options to append to <literal>/etc/default/surf-display</literal>.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.displayManager.extraSessionFilePackages = [
+ pkgs.surf-display
+ ];
+
+ environment.etc."default/surf-display".text = surfDisplayConf;
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
new file mode 100644
index 00000000000..6965c6d2646
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce.nix
@@ -0,0 +1,123 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.desktopManager.xfce;
+in
+
+{
+ options = {
+ services.xserver.desktopManager.xfce = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable the Xfce desktop environment.";
+ };
+
+ thunarPlugins = mkOption {
+ default = [];
+ type = types.listOf types.package;
+ example = literalExample "[ pkgs.xfce.thunar-archive-plugin ]";
+ description = ''
+ A list of plugin that should be installed with Thunar.
+ '';
+ };
+
+ noDesktop = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Don't install XFCE desktop components (xfdesktop, panel and notification daemon).";
+ };
+
+ extraSessionCommands = mkOption {
+ default = "";
+ type = types.lines;
+ description = ''
+ Shell commands executed just before XFCE is started.
+ '';
+ };
+
+ enableXfwm = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Enable the XFWM (default) window manager.";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs.xfce // pkgs; [
+ # Get GTK themes and gtk-update-icon-cache
+ gtk2.out
+
+ # Supplies some abstract icons such as:
+ # utilities-terminal, accessories-text-editor
+ gnome3.adwaita-icon-theme
+
+ hicolor-icon-theme
+ tango-icon-theme
+ xfce4-icon-theme
+
+ # Needed by Xfce's xinitrc script
+ # TODO: replace with command -v
+ which
+
+ exo
+ garcon
+ gtk-xfce-engine
+ libxfce4ui
+ tumbler
+ xfconf
+
+ mousepad
+ ristretto
+ xfce4-appfinder
+ xfce4-screenshooter
+ xfce4-session
+ xfce4-settings
+ xfce4-terminal
+
+ (thunar.override { thunarPlugins = cfg.thunarPlugins; })
+ thunar-volman # TODO: drop
+ ] ++ (if config.hardware.pulseaudio.enable
+ then [ xfce4-mixer-pulse xfce4-volumed-pulse ]
+ else [ xfce4-mixer xfce4-volumed ])
+ # TODO: NetworkManager doesn't belong here
+ ++ optionals config.networking.networkmanager.enable [ networkmanagerapplet ]
+ ++ optionals config.powerManagement.enable [ xfce4-power-manager ]
+ ++ optionals cfg.enableXfwm [ xfwm4 ]
+ ++ optionals (!cfg.noDesktop) [
+ xfce4-panel
+ xfce4-notifyd
+ xfdesktop
+ ];
+
+ environment.pathsToLink = [
+ "/share/xfce4"
+ "/share/themes"
+ "/share/gtksourceview-2.0"
+ ];
+
+ services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
+
+ services.xserver.desktopManager.session = [{
+ name = "xfce";
+ bgSupport = true;
+ start = ''
+ ${cfg.extraSessionCommands}
+
+ ${pkgs.runtimeShell} ${pkgs.xfce.xinitrc} &
+ waitPID=$!
+ '';
+ }];
+
+ services.xserver.updateDbusEnvironment = true;
+
+ # Enable helpful DBus services.
+ services.udisks2.enable = true;
+ services.upower.enable = config.powerManagement.enable;
+ services.gvfs.enable = true;
+ services.gvfs.package = pkgs.xfce.gvfs;
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce4-14.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce4-14.nix
new file mode 100644
index 00000000000..130e865a1fb
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/xfce4-14.nix
@@ -0,0 +1,156 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.desktopManager.xfce4-14;
+in
+
+{
+ # added 2019-08-18
+ # needed to preserve some semblance of UI familarity
+ # with original XFCE module
+ imports = [
+ (mkRenamedOptionModule
+ [ "services" "xserver" "desktopManager" "xfce4-14" "extraSessionCommands" ]
+ [ "services" "xserver" "displayManager" "sessionCommands" ])
+ ];
+
+ options = {
+ services.xserver.desktopManager.xfce4-14 = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable the Xfce desktop environment.";
+ };
+
+ # TODO: support thunar plugins
+ # thunarPlugins = mkOption {
+ # default = [];
+ # type = types.listOf types.package;
+ # example = literalExample "[ pkgs.xfce4-14.thunar-archive-plugin ]";
+ # description = ''
+ # A list of plugin that should be installed with Thunar.
+ # '';
+ # };
+
+ noDesktop = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Don't install XFCE desktop components (xfdesktop, panel and notification daemon).";
+ };
+
+ enableXfwm = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Enable the XFWM (default) window manager.";
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs.xfce4-14 // pkgs; [
+ glib # for gsettings
+ gtk3.out # gtk-update-icon-cache
+
+ gnome3.gnome-themes-extra
+ gnome3.adwaita-icon-theme
+ hicolor-icon-theme
+ tango-icon-theme
+ xfce4-icon-theme
+
+ desktop-file-utils
+ shared-mime-info # for update-mime-database
+
+ # For a polkit authentication agent
+ polkit_gnome
+
+ # Needed by Xfce's xinitrc script
+ xdg-user-dirs # Update user dirs as described in https://freedesktop.org/wiki/Software/xdg-user-dirs/
+
+ exo
+ garcon
+ libxfce4ui
+ xfconf
+
+ mousepad
+ parole
+ ristretto
+ xfce4-appfinder
+ xfce4-screenshooter
+ xfce4-session
+ xfce4-settings
+ xfce4-taskmanager
+ xfce4-terminal
+
+ # TODO: resync patch for plugins
+ #(thunar.override { thunarPlugins = cfg.thunarPlugins; })
+ thunar
+ ] # TODO: NetworkManager doesn't belong here
+ ++ optional config.networking.networkmanager.enable networkmanagerapplet
+ ++ optional config.powerManagement.enable xfce4-power-manager
+ ++ optionals config.hardware.pulseaudio.enable [
+ pavucontrol
+ xfce4-pulseaudio-plugin
+ ] ++ optionals cfg.enableXfwm [
+ xfwm4
+ xfwm4-themes
+ ] ++ optionals (!cfg.noDesktop) [
+ xfce4-notifyd
+ xfce4-panel
+ xfdesktop
+ ];
+
+ environment.pathsToLink = [
+ "/share/xfce4"
+ "/lib/xfce4"
+ "/share/gtksourceview-3.0"
+ "/share/gtksourceview-4.0"
+ ];
+
+ # Use the correct gnome3 packageSet
+ networking.networkmanager.basePackages = mkIf config.networking.networkmanager.enable {
+ inherit (pkgs) networkmanager modemmanager wpa_supplicant crda;
+ inherit (pkgs.gnome3) networkmanager-openvpn networkmanager-vpnc
+ networkmanager-openconnect networkmanager-fortisslvpn
+ networkmanager-iodine networkmanager-l2tp;
+ };
+
+ services.xserver.desktopManager.session = [{
+ name = "xfce4-14";
+ bgSupport = true;
+ start = ''
+ ${pkgs.runtimeShell} ${pkgs.xfce4-14.xinitrc} &
+ waitPID=$!
+ '';
+ }];
+
+ services.xserver.updateDbusEnvironment = true;
+ services.xserver.gdk-pixbuf.modulePackages = [ pkgs.librsvg ];
+
+ # Enable helpful DBus services.
+ services.udisks2.enable = true;
+ security.polkit.enable = true;
+ services.accounts-daemon.enable = true;
+ services.upower.enable = config.powerManagement.enable;
+ services.gnome3.glib-networking.enable = true;
+ services.gvfs.enable = true;
+ services.gvfs.package = pkgs.xfce.gvfs;
+ services.tumbler.enable = true;
+ services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
+ services.xserver.libinput.enable = mkDefault true; # used in xfce4-settings-manager
+
+ # Enable default programs
+ programs.dconf.enable = true;
+
+ # Shell integration for VTE terminals
+ programs.bash.vteIntegration = mkDefault true;
+ programs.zsh.vteIntegration = mkDefault true;
+
+ # Systemd services
+ systemd.packages = with pkgs.xfce4-14; [
+ thunar
+ ] ++ optional (!cfg.noDesktop) xfce4-notifyd;
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/desktop-managers/xterm.nix b/nixpkgs/nixos/modules/services/x11/desktop-managers/xterm.nix
new file mode 100644
index 00000000000..f76db278a92
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/desktop-managers/xterm.nix
@@ -0,0 +1,38 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.desktopManager.xterm;
+ xSessionEnabled = config.services.xserver.enable;
+
+in
+
+{
+ options = {
+
+ services.xserver.desktopManager.xterm.enable = mkOption {
+ type = types.bool;
+ default = (versionOlder config.system.stateVersion "19.09") && xSessionEnabled;
+ defaultText = if versionOlder config.system.stateVersion "19.09" then "config.services.xserver.enable" else "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/nixpkgs/nixos/modules/services/x11/display-managers/auto.nix b/nixpkgs/nixos/modules/services/x11/display-managers/auto.nix
new file mode 100644
index 00000000000..1068a344e0c
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/auto.nix
@@ -0,0 +1,68 @@
+{ config, lib, ... }:
+
+with 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.lightdm = {
+ enable = true;
+ autoLogin = {
+ enable = true;
+ user = cfg.user;
+ };
+ };
+
+ # lightdm by default doesn't allow auto login for root, which is
+ # required by some nixos tests. Override it here.
+ security.pam.services.lightdm-autologin.text = lib.mkForce ''
+ auth requisite pam_nologin.so
+ auth required pam_succeed_if.so quiet
+ auth required pam_permit.so
+
+ account include lightdm
+
+ password include lightdm
+
+ session include lightdm
+ '';
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/default.nix b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
new file mode 100644
index 00000000000..bf6b048654b
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/default.nix
@@ -0,0 +1,377 @@
+# This module declares the options to define a *display manager*, the
+# program responsible for handling X logins (such as xdm, 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, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver;
+ xorg = pkgs.xorg;
+
+ fontconfig = config.fonts.fontconfig;
+ xresourcesXft = pkgs.writeText "Xresources-Xft" ''
+ ${optionalString (fontconfig.dpi != 0) ''Xft.dpi: ${toString fontconfig.dpi}''}
+ Xft.antialias: ${if fontconfig.antialias then "1" else "0"}
+ Xft.rgba: ${fontconfig.subpixel.rgba}
+ Xft.lcdfilter: lcd${fontconfig.subpixel.lcdfilter}
+ Xft.hinting: ${if fontconfig.hinting.enable then "1" else "0"}
+ Xft.autohint: ${if fontconfig.hinting.autohint then "1" else "0"}
+ Xft.hintstyle: hintslight
+ '';
+
+ mkCases = session:
+ concatStrings (
+ mapAttrsToList (name: starts: ''
+ (${name})
+ ${concatMapStringsSep "\n " (n: n.start) starts}
+ ;;
+ '') (lib.groupBy (n: n.name) session)
+ );
+
+ # file provided by services.xserver.displayManager.session.wrapper
+ xsessionWrapper = pkgs.writeScript "xsession-wrapper"
+ ''
+ #! ${pkgs.bash}/bin/bash
+
+ # Shared environment setup for graphical sessions.
+
+ . /etc/profile
+ cd "$HOME"
+
+ ${optionalString cfg.startDbusSession ''
+ if test -z "$DBUS_SESSION_BUS_ADDRESS"; then
+ exec ${pkgs.dbus.dbus-launch} --exit-with-session "$0" "$@"
+ fi
+ ''}
+
+ ${optionalString cfg.displayManager.job.logToJournal ''
+ if [ -z "$_DID_SYSTEMD_CAT" ]; then
+ export _DID_SYSTEMD_CAT=1
+ exec ${config.systemd.package}/bin/systemd-cat -t xsession "$0" "$@"
+ fi
+ ''}
+
+ ${optionalString cfg.displayManager.job.logToFile ''
+ exec &> >(tee ~/.xsession-errors)
+ ''}
+
+ # Start PulseAudio if enabled.
+ ${optionalString (config.hardware.pulseaudio.enable) ''
+ # Publish access credentials in the root window.
+ if ${config.hardware.pulseaudio.package.out}/bin/pulseaudio --dump-modules | grep module-x11-publish &> /dev/null; then
+ ${config.hardware.pulseaudio.package.out}/bin/pactl load-module module-x11-publish "display=$DISPLAY"
+ fi
+ ''}
+
+ # Tell systemd about our $DISPLAY and $XAUTHORITY.
+ # This is needed by the ssh-agent unit.
+ #
+ # Also tell systemd about the dbus session bus address.
+ # This is required by user units using the session bus.
+ ${config.systemd.package}/bin/systemctl --user import-environment DISPLAY XAUTHORITY DBUS_SESSION_BUS_ADDRESS
+
+ # Load X defaults. This should probably be safe on wayland too.
+ ${xorg.xrdb}/bin/xrdb -merge ${xresourcesXft}
+ if test -e ~/.Xresources; then
+ ${xorg.xrdb}/bin/xrdb -merge ~/.Xresources
+ elif test -e ~/.Xdefaults; then
+ ${xorg.xrdb}/bin/xrdb -merge ~/.Xdefaults
+ fi
+
+ # 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"
+
+ # Work around KDE errors when a user first logs in and
+ # .local/share doesn't exist yet.
+ mkdir -p "$HOME/.local/share"
+
+ unset _DID_SYSTEMD_CAT
+
+ ${cfg.displayManager.sessionCommands}
+
+ # Allow the user to execute commands at the beginning of the X session.
+ if test -f ~/.xprofile; then
+ source ~/.xprofile
+ fi
+
+ # Start systemd user services for graphical sessions
+ ${config.systemd.package}/bin/systemctl --user start graphical-session.target
+
+ # Allow the user to setup a custom session type.
+ if test -x ~/.xsession; then
+ eval exec ~/.xsession "$@"
+ fi
+
+ if test "$1"; then
+ # Run the supplied session command. Remove any double quotes with eval.
+ eval exec "$@"
+ else
+ # Fall back to the default window/desktopManager
+ exec ${cfg.displayManager.session.script}
+ fi
+ '';
+
+ # file provided by services.xserver.displayManager.session.script
+ xsession = wm: dm: pkgs.writeScript "xsession"
+ ''
+ #! ${pkgs.bash}/bin/bash
+
+ # Legacy session script used to construct .desktop files from
+ # `services.xserver.displayManager.session` entries. Called from
+ # `sessionWrapper`.
+
+ # Expected parameters:
+ # $1 = <desktop-manager>+<window-manager>
+
+ # The first argument of this script is the session type.
+ sessionType="$1"
+ if [ "$sessionType" = default ]; then sessionType=""; fi
+
+ # The session type is "<desktop-manager>+<window-manager>", so
+ # extract those (see:
+ # http://wiki.bash-hackers.org/syntax/pe#substring_removal).
+ windowManager="''${sessionType##*+}"
+ : ''${windowManager:=${cfg.windowManager.default}}
+ desktopManager="''${sessionType%%+*}"
+ : ''${desktopManager:=${cfg.desktopManager.default}}
+
+ # Start the window manager.
+ case "$windowManager" in
+ ${mkCases wm}
+ (*) echo "$0: Window manager '$windowManager' not found.";;
+ esac
+
+ # Start the desktop manager.
+ case "$desktopManager" in
+ ${mkCases dm}
+ (*) echo "$0: Desktop manager '$desktopManager' not found.";;
+ esac
+
+ ${optionalString cfg.updateDbusEnvironment ''
+ ${lib.getBin pkgs.dbus}/bin/dbus-update-activation-environment --systemd --all
+ ''}
+
+ test -n "$waitPID" && wait "$waitPID"
+
+ ${config.systemd.package}/bin/systemctl --user stop graphical-session.target
+
+ exit 0
+ '';
+
+ # Desktop Entry Specification:
+ # - https://standards.freedesktop.org/desktop-entry-spec/latest/
+ # - https://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html
+ mkDesktops = names: pkgs.runCommand "desktops"
+ { # trivial derivation
+ preferLocalBuild = true;
+ allowSubstitutes = false;
+ }
+ ''
+ mkdir -p "$out/share/xsessions"
+ ${concatMapStrings (n: ''
+ cat - > "$out/share/xsessions/${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}
+
+ ${concatMapStrings (pkg: ''
+ if test -d ${pkg}/share/xsessions; then
+ ${xorg.lndir}/bin/lndir ${pkg}/share/xsessions $out/share/xsessions
+ fi
+ '') cfg.displayManager.extraSessionFilePackages}
+
+
+ ${concatMapStrings (pkg: ''
+ if test -d ${pkg}/share/wayland-sessions; then
+ mkdir -p "$out/share/wayland-sessions"
+ ${xorg.lndir}/bin/lndir ${pkg}/share/wayland-sessions $out/share/wayland-sessions
+ fi
+ '') cfg.displayManager.extraSessionFilePackages}
+ '';
+
+in
+
+{
+
+ options = {
+
+ services.xserver.displayManager = {
+
+ xauthBin = mkOption {
+ internal = true;
+ default = "${xorg.xauth}/bin/xauth";
+ description = "Path to the <command>xauth</command> program used by display managers.";
+ };
+
+ xserverBin = mkOption {
+ type = types.path;
+ description = "Path to the X server used by display managers.";
+ };
+
+ xserverArgs = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "-ac" "-logverbose" "-verbose" "-nolisten tcp" ];
+ description = "List of arguments for the X server.";
+ };
+
+ setupCommands = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Shell commands executed just after the X server has started.
+
+ This option is only effective for display managers for which this feature
+ is supported; currently these are LightDM, GDM and SDDM.
+ '';
+ };
+
+ sessionCommands = mkOption {
+ type = types.lines;
+ default = "";
+ example =
+ ''
+ xmessage "Hello World!" &
+ '';
+ description = ''
+ Shell commands executed just before the window or desktop manager is
+ started. These commands are not currently sourced for Wayland sessions.
+ '';
+ };
+
+ hiddenUsers = mkOption {
+ type = types.listOf types.str;
+ default = [ "nobody" ];
+ description = ''
+ A list of users which will not be shown in the display manager.
+ '';
+ };
+
+ extraSessionFilePackages = mkOption {
+ type = types.listOf types.package;
+ default = [];
+ description = ''
+ A list of packages containing xsession files to be passed to the display manager.
+ '';
+ };
+
+ session = mkOption {
+ default = [];
+ example = literalExample
+ ''
+ [ { 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 window 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;
+ wrapper = xsessionWrapper;
+ };
+ };
+
+ job = {
+
+ preStart = mkOption {
+ type = types.lines;
+ default = "";
+ example = "rm -f /var/log/my-display-manager.log";
+ description = "Script executed before the display manager is started.";
+ };
+
+ execCmd = mkOption {
+ type = types.str;
+ example = literalExample ''
+ "''${pkgs.slim}/bin/slim"
+ '';
+ description = "Command to start the display manager.";
+ };
+
+ environment = mkOption {
+ type = types.attrsOf types.unspecified;
+ default = {};
+ example = { SLIM_CFGFILE = "/etc/slim.conf"; };
+ description = "Additional environment variables needed by the display manager.";
+ };
+
+ logToFile = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether the display manager redirects the output of the
+ session script to <filename>~/.xsession-errors</filename>.
+ '';
+ };
+
+ logToJournal = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether the display manager redirects the output of the
+ session script to the systemd journal.
+ '';
+ };
+
+ };
+
+ };
+
+ };
+
+ config = {
+ services.xserver.displayManager.xserverBin = "${xorg.xorgserver.out}/bin/X";
+
+ systemd.user.targets.graphical-session = {
+ unitConfig = {
+ RefuseManualStart = false;
+ StopWhenUnneeded = false;
+ };
+ };
+ };
+
+ imports = [
+ (mkRemovedOptionModule [ "services" "xserver" "displayManager" "desktopManagerHandlesLidAndPower" ]
+ "The option is no longer necessary because all display managers have already delegated lid management to systemd.")
+ ];
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
new file mode 100644
index 00000000000..0a5d52e319e
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/gdm.nix
@@ -0,0 +1,294 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.displayManager;
+ gdm = pkgs.gnome3.gdm;
+
+ xSessionWrapper = if (cfg.setupCommands == "") then null else
+ pkgs.writeScript "gdm-x-session-wrapper" ''
+ #!${pkgs.bash}/bin/bash
+ ${cfg.setupCommands}
+ exec "$@"
+ '';
+
+ # Solves problems like:
+ # https://wiki.archlinux.org/index.php/Talk:Bluetooth_headset#GDMs_pulseaudio_instance_captures_bluetooth_headset
+ # Instead of blacklisting plugins, we use Fedora's PulseAudio configuration for GDM:
+ # https://src.fedoraproject.org/rpms/gdm/blob/master/f/default.pa-for-gdm
+ pulseConfig = pkgs.writeText "default.pa" ''
+ load-module module-device-restore
+ load-module module-card-restore
+ load-module module-udev-detect
+ load-module module-native-protocol-unix
+ load-module module-default-device-restore
+ load-module module-rescue-streams
+ load-module module-always-sink
+ load-module module-intended-roles
+ load-module module-suspend-on-idle
+ load-module module-position-event-sounds
+ '';
+
+in
+
+{
+
+ ###### interface
+
+ options = {
+
+ services.xserver.displayManager.gdm = {
+
+ enable = mkEnableOption ''
+ GDM as the display manager.
+ <emphasis>GDM in NixOS is not well-tested with desktops other
+ than GNOME, so use with caution, as it could render the
+ system unusable.</emphasis>
+ '';
+
+ debug = mkEnableOption ''
+ debugging messages in GDM
+ '';
+
+ autoLogin = mkOption {
+ default = {};
+ description = ''
+ Auto login configuration attrset.
+ '';
+
+ type = types.submodule {
+ options = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Automatically log in as the sepecified <option>autoLogin.user</option>.
+ '';
+ };
+
+ user = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ User to be used for the autologin.
+ '';
+ };
+
+ delay = mkOption {
+ type = types.int;
+ default = 0;
+ description = ''
+ Seconds of inactivity after which the autologin will be performed.
+ '';
+ };
+
+ };
+ };
+ };
+
+ wayland = mkOption {
+ default = true;
+ description = ''
+ Allow GDM run on Wayland instead of Xserver
+ '';
+ type = types.bool;
+ };
+
+ autoSuspend = mkOption {
+ default = true;
+ description = ''
+ Suspend the machine after inactivity.
+ '';
+ type = types.bool;
+ };
+
+ };
+
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.gdm.enable {
+
+ assertions = [
+ { assertion = cfg.gdm.autoLogin.enable -> cfg.gdm.autoLogin.user != null;
+ message = "GDM auto-login requires services.xserver.displayManager.gdm.autoLogin.user to be set";
+ }
+ ];
+
+ services.xserver.displayManager.lightdm.enable = false;
+
+ users.users.gdm =
+ { name = "gdm";
+ uid = config.ids.uids.gdm;
+ group = "gdm";
+ home = "/run/gdm";
+ description = "GDM user";
+ };
+
+ users.groups.gdm.gid = config.ids.gids.gdm;
+
+ # GDM needs different xserverArgs, presumable because using wayland by default.
+ services.xserver.tty = null;
+ services.xserver.display = null;
+ services.xserver.verbose = null;
+
+ services.xserver.displayManager.job =
+ {
+ environment = {
+ GDM_X_SERVER_EXTRA_ARGS = toString
+ (filter (arg: arg != "-terminate") cfg.xserverArgs);
+ XDG_DATA_DIRS = "${cfg.session.desktops}/share/";
+ } // optionalAttrs (xSessionWrapper != null) {
+ # Make GDM use this wrapper before running the session, which runs the
+ # configured setupCommands. This relies on a patched GDM which supports
+ # this environment variable.
+ GDM_X_SESSION_WRAPPER = "${xSessionWrapper}";
+ };
+ execCmd = "exec ${gdm}/bin/gdm";
+ preStart = optionalString config.hardware.pulseaudio.enable ''
+ mkdir -p /run/gdm/.config/pulse
+ ln -sf ${pulseConfig} /run/gdm/.config/pulse/default.pa
+ chown -R gdm:gdm /run/gdm/.config
+ '';
+ };
+
+ # Because sd_login_monitor_new requires /run/systemd/machines
+ systemd.services.display-manager.wants = [ "systemd-machined.service" ];
+ systemd.services.display-manager.after = [
+ "rc-local.service"
+ "systemd-machined.service"
+ "systemd-user-sessions.service"
+ ];
+
+ systemd.services.display-manager.serviceConfig = {
+ # Restart = "always"; - already defined in xserver.nix
+ KillMode = "mixed";
+ IgnoreSIGPIPE = "no";
+ BusName = "org.gnome.DisplayManager";
+ StandardOutput = "syslog";
+ StandardError = "inherit";
+ };
+
+ systemd.services.display-manager.path = [ pkgs.gnome3.gnome-session ];
+
+ # Allow choosing an user account
+ services.accounts-daemon.enable = true;
+
+ services.dbus.packages = [ gdm ];
+
+ systemd.user.services.dbus.wantedBy = [ "default.target" ];
+
+ programs.dconf.profiles.gdm =
+ let
+ customDconf = pkgs.writeTextFile {
+ name = "gdm-dconf";
+ destination = "/dconf/gdm-custom";
+ text = ''
+ ${optionalString (!cfg.gdm.autoSuspend) ''
+ [org/gnome/settings-daemon/plugins/power]
+ sleep-inactive-ac-type='nothing'
+ sleep-inactive-battery-type='nothing'
+ sleep-inactive-ac-timeout=0
+ sleep-inactive-battery-timeout=0
+ ''}
+ '';
+ };
+
+ customDconfDb = pkgs.stdenv.mkDerivation {
+ name = "gdm-dconf-db";
+ buildCommand = ''
+ ${pkgs.gnome3.dconf}/bin/dconf compile $out ${customDconf}/dconf
+ '';
+ };
+ in pkgs.stdenv.mkDerivation {
+ name = "dconf-gdm-profile";
+ buildCommand = ''
+ # Check that the GDM profile starts with what we expect.
+ if [ $(head -n 1 ${gdm}/share/dconf/profile/gdm) != "user-db:user" ]; then
+ echo "GDM dconf profile changed, please update gdm.nix"
+ exit 1
+ fi
+ # Insert our custom DB behind it.
+ sed '2ifile-db:${customDconfDb}' ${gdm}/share/dconf/profile/gdm > $out
+ '';
+ };
+
+ # Use AutomaticLogin if delay is zero, because it's immediate.
+ # Otherwise with TimedLogin with zero seconds the prompt is still
+ # presented and there's a little delay.
+ environment.etc."gdm/custom.conf".text = ''
+ [daemon]
+ WaylandEnable=${if cfg.gdm.wayland then "true" else "false"}
+ ${optionalString cfg.gdm.autoLogin.enable (
+ if cfg.gdm.autoLogin.delay > 0 then ''
+ TimedLoginEnable=true
+ TimedLogin=${cfg.gdm.autoLogin.user}
+ TimedLoginDelay=${toString cfg.gdm.autoLogin.delay}
+ '' else ''
+ AutomaticLoginEnable=true
+ AutomaticLogin=${cfg.gdm.autoLogin.user}
+ '')
+ }
+
+ [security]
+
+ [xdmcp]
+
+ [greeter]
+
+ [chooser]
+
+ [debug]
+ ${optionalString cfg.gdm.debug "Enable=true"}
+ '';
+
+ environment.etc."gdm/Xsession".source = config.services.xserver.displayManager.session.wrapper;
+
+ # GDM LFS PAM modules, adapted somehow to NixOS
+ security.pam.services = {
+ gdm-launch-environment.text = ''
+ auth required pam_succeed_if.so audit quiet_success user = gdm
+ auth optional pam_permit.so
+
+ account required pam_succeed_if.so audit quiet_success user = gdm
+ account sufficient pam_unix.so
+
+ password required pam_deny.so
+
+ session required pam_succeed_if.so audit quiet_success user = gdm
+ session required pam_env.so conffile=${config.system.build.pamEnvironment} readenv=0
+ session optional ${pkgs.systemd}/lib/security/pam_systemd.so
+ session optional pam_keyinit.so force revoke
+ session optional pam_permit.so
+ '';
+
+ gdm-password.text = ''
+ auth substack login
+ account include login
+ password substack login
+ session include login
+ '';
+
+ gdm-autologin.text = ''
+ auth requisite pam_nologin.so
+
+ auth required pam_succeed_if.so uid >= 1000 quiet
+ auth required pam_permit.so
+
+ account sufficient pam_unix.so
+
+ password requisite pam_unix.so nullok sha512
+
+ session optional pam_keyinit.so revoke
+ session include login
+ '';
+
+ };
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix
new file mode 100644
index 00000000000..129df139c61
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/enso-os.nix
@@ -0,0 +1,140 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ dmcfg = config.services.xserver.displayManager;
+ ldmcfg = dmcfg.lightdm;
+ cfg = ldmcfg.greeters.enso;
+
+ theme = cfg.theme.package;
+ icons = cfg.iconTheme.package;
+ cursors = cfg.cursorTheme.package;
+
+ ensoGreeterConf = pkgs.writeText "lightdm-enso-os-greeter.conf" ''
+ [greeter]
+ default-wallpaper=${ldmcfg.background}
+ gtk-theme=${cfg.theme.name}
+ icon-theme=${cfg.iconTheme.name}
+ cursor-theme=${cfg.cursorTheme.name}
+ blur=${toString cfg.blur}
+ brightness=${toString cfg.brightness}
+ ${cfg.extraConfig}
+ '';
+in {
+ options = {
+ services.xserver.displayManager.lightdm.greeters.enso = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable enso-os-greeter as the lightdm greeter
+ '';
+ };
+
+ theme = {
+ package = mkOption {
+ type = types.package;
+ default = pkgs.gnome3.gnome-themes-extra;
+ defaultText = "pkgs.gnome3.gnome-themes-extra";
+ description = ''
+ The package path that contains the theme given in the name option.
+ '';
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "Adwaita";
+ description = ''
+ Name of the theme to use for the lightdm-enso-os-greeter
+ '';
+ };
+ };
+
+ iconTheme = {
+ package = mkOption {
+ type = types.package;
+ default = pkgs.papirus-icon-theme;
+ defaultText = "pkgs.papirus-icon-theme";
+ description = ''
+ The package path that contains the icon theme given in the name option.
+ '';
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "ePapirus";
+ description = ''
+ Name of the icon theme to use for the lightdm-enso-os-greeter
+ '';
+ };
+ };
+
+ cursorTheme = {
+ package = mkOption {
+ type = types.package;
+ default = pkgs.capitaine-cursors;
+ defaultText = "pkgs.capitaine-cursors";
+ description = ''
+ The package path that contains the cursor theme given in the name option.
+ '';
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "capitane-cursors";
+ description = ''
+ Name of the cursor theme to use for the lightdm-enso-os-greeter
+ '';
+ };
+ };
+
+ blur = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether or not to enable blur
+ '';
+ };
+
+ brightness = mkOption {
+ type = types.int;
+ default = 7;
+ description = ''
+ Brightness
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra configuration that should be put in the greeter.conf
+ configuration file
+ '';
+ };
+ };
+ };
+
+ config = mkIf (ldmcfg.enable && cfg.enable) {
+ environment.etc."lightdm/greeter.conf".source = ensoGreeterConf;
+
+ environment.systemPackages = [
+ cursors
+ icons
+ theme
+ ];
+
+ services.xserver.displayManager.lightdm = {
+ greeter = mkDefault {
+ package = pkgs.lightdm-enso-os-greeter.xgreeters;
+ name = "pantheon-greeter";
+ };
+
+ greeters = {
+ gtk = {
+ enable = mkDefault false;
+ };
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
new file mode 100644
index 00000000000..de932e6e840
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/gtk.nix
@@ -0,0 +1,173 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ dmcfg = config.services.xserver.displayManager;
+ ldmcfg = dmcfg.lightdm;
+ xcfg = config.services.xserver;
+ cfg = ldmcfg.greeters.gtk;
+
+ inherit (pkgs) writeText;
+
+ theme = cfg.theme.package;
+ icons = cfg.iconTheme.package;
+ cursors = cfg.cursorTheme.package;
+
+ gtkGreeterConf = writeText "lightdm-gtk-greeter.conf"
+ ''
+ [greeter]
+ theme-name = ${cfg.theme.name}
+ icon-theme-name = ${cfg.iconTheme.name}
+ cursor-theme-name = ${cfg.cursorTheme.name}
+ cursor-theme-size = ${toString cfg.cursorTheme.size}
+ background = ${ldmcfg.background}
+ ${optionalString (cfg.clock-format != null) "clock-format = ${cfg.clock-format}"}
+ ${optionalString (cfg.indicators != null) "indicators = ${concatStringsSep ";" cfg.indicators}"}
+ ${optionalString (xcfg.dpi != null) "xft-dpi=${toString xcfg.dpi}"}
+ ${cfg.extraConfig}
+ '';
+
+in
+{
+ options = {
+
+ services.xserver.displayManager.lightdm.greeters.gtk = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to enable lightdm-gtk-greeter as the lightdm greeter.
+ '';
+ };
+
+ theme = {
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.gnome3.gnome-themes-extra;
+ defaultText = "pkgs.gnome3.gnome-themes-extra";
+ description = ''
+ The package path that contains the theme given in the name option.
+ '';
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "Adwaita";
+ description = ''
+ Name of the theme to use for the lightdm-gtk-greeter.
+ '';
+ };
+
+ };
+
+ iconTheme = {
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.gnome3.adwaita-icon-theme;
+ defaultText = "pkgs.gnome3.adwaita-icon-theme";
+ description = ''
+ The package path that contains the icon theme given in the name option.
+ '';
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "Adwaita";
+ description = ''
+ Name of the icon theme to use for the lightdm-gtk-greeter.
+ '';
+ };
+
+ };
+
+ cursorTheme = {
+
+ package = mkOption {
+ default = pkgs.gnome3.adwaita-icon-theme;
+ defaultText = "pkgs.gnome3.adwaita-icon-theme";
+ description = ''
+ The package path that contains the cursor theme given in the name option.
+ '';
+ };
+
+ name = mkOption {
+ type = types.str;
+ default = "Adwaita";
+ description = ''
+ Name of the cursor theme to use for the lightdm-gtk-greeter.
+ '';
+ };
+
+ size = mkOption {
+ type = types.int;
+ default = 16;
+ description = ''
+ Size of the cursor theme to use for the lightdm-gtk-greeter.
+ '';
+ };
+ };
+
+ clock-format = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "%F";
+ description = ''
+ Clock format string (as expected by strftime, e.g. "%H:%M")
+ to use with the lightdm gtk greeter panel.
+
+ If set to null the default clock format is used.
+ '';
+ };
+
+ indicators = mkOption {
+ type = types.nullOr (types.listOf types.str);
+ default = null;
+ example = [ "~host" "~spacer" "~clock" "~spacer" "~session" "~language" "~a11y" "~power" ];
+ description = ''
+ List of allowed indicator modules to use for the lightdm gtk
+ greeter panel.
+
+ Built-in indicators include "~a11y", "~language", "~session",
+ "~power", "~clock", "~host", "~spacer". Unity indicators can be
+ represented by short name (e.g. "sound", "power"), service file name,
+ or absolute path.
+
+ If set to null the default indicators are used.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra configuration that should be put in the lightdm-gtk-greeter.conf
+ configuration file.
+ '';
+ };
+
+ };
+
+ };
+
+ config = mkIf (ldmcfg.enable && cfg.enable) {
+
+ services.xserver.displayManager.lightdm.greeter = mkDefault {
+ package = pkgs.lightdm_gtk_greeter.xgreeters;
+ name = "lightdm-gtk-greeter";
+ };
+
+ environment.systemPackages = [
+ cursors
+ icons
+ theme
+ ];
+
+ environment.etc."lightdm/lightdm-gtk-greeter.conf".source = gtkGreeterConf;
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix
new file mode 100644
index 00000000000..fa9445af32e
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/mini.nix
@@ -0,0 +1,95 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ dmcfg = config.services.xserver.displayManager;
+ ldmcfg = dmcfg.lightdm;
+ cfg = ldmcfg.greeters.mini;
+
+ miniGreeterConf = pkgs.writeText "lightdm-mini-greeter.conf"
+ ''
+ [greeter]
+ user = ${cfg.user}
+ show-password-label = true
+ password-label-text = Password:
+ show-input-cursor = true
+
+ [greeter-hotkeys]
+ mod-key = meta
+ shutdown-key = s
+ restart-key = r
+ hibernate-key = h
+ suspend-key = u
+
+ [greeter-theme]
+ font = Sans
+ font-size = 1em
+ text-color = "#080800"
+ error-color = "#F8F8F0"
+ background-image = "${ldmcfg.background}"
+ background-color = "#1B1D1E"
+ window-color = "#F92672"
+ border-color = "#080800"
+ border-width = 2px
+ layout-space = 15
+ password-color = "#F8F8F0"
+ password-background-color = "#1B1D1E"
+
+ ${cfg.extraConfig}
+ '';
+
+in
+{
+ options = {
+
+ services.xserver.displayManager.lightdm.greeters.mini = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable lightdm-mini-greeter as the lightdm greeter.
+
+ Note that this greeter starts only the default X session.
+ You can configure the default X session by
+ <option>services.xserver.desktopManager.default</option> and
+ <option>services.xserver.windowManager.default</option>.
+ '';
+ };
+
+ user = mkOption {
+ type = types.str;
+ default = "root";
+ description = ''
+ The user to login as.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra configuration that should be put in the lightdm-mini-greeter.conf
+ configuration file.
+ '';
+ };
+
+ };
+
+ };
+
+ config = mkIf (ldmcfg.enable && cfg.enable) {
+
+ services.xserver.displayManager.lightdm.greeters.gtk.enable = false;
+
+ services.xserver.displayManager.lightdm.greeter = mkDefault {
+ package = pkgs.lightdm-mini-greeter.xgreeters;
+ name = "lightdm-mini-greeter";
+ };
+
+ environment.etc."lightdm/lightdm-mini-greeter.conf".source = miniGreeterConf;
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix
new file mode 100644
index 00000000000..29cb6ccbc06
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix
@@ -0,0 +1,42 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ dmcfg = config.services.xserver.displayManager;
+ ldmcfg = dmcfg.lightdm;
+ cfg = ldmcfg.greeters.pantheon;
+
+in
+{
+ options = {
+
+ services.xserver.displayManager.lightdm.greeters.pantheon = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable elementary-greeter as the lightdm greeter.
+ '';
+ };
+
+ };
+
+ };
+
+ config = mkIf (ldmcfg.enable && cfg.enable) {
+
+ services.xserver.displayManager.lightdm.greeters.gtk.enable = false;
+
+ services.xserver.displayManager.lightdm.greeter = mkDefault {
+ package = pkgs.pantheon.elementary-greeter.xgreeters;
+ name = "io.elementary.greeter";
+ };
+
+ environment.etc."lightdm/io.elementary.greeter.conf".source = "${pkgs.pantheon.elementary-greeter}/etc/lightdm/io.elementary.greeter.conf";
+ environment.etc."wingpanel.d/io.elementary.greeter.whitelist".source = "${pkgs.pantheon.elementary-default-settings}/etc/wingpanel.d/io.elementary.greeter.whitelist";
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
new file mode 100644
index 00000000000..f105cb496e6
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/lightdm.nix
@@ -0,0 +1,290 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ xcfg = config.services.xserver;
+ dmcfg = xcfg.displayManager;
+ xEnv = config.systemd.services.display-manager.environment;
+ cfg = dmcfg.lightdm;
+
+ dmDefault = xcfg.desktopManager.default;
+ wmDefault = xcfg.windowManager.default;
+ hasDefaultUserSession = dmDefault != "none" || wmDefault != "none";
+
+ inherit (pkgs) lightdm writeScript writeText;
+
+ # lightdm runs with clearenv(), but we need a few things in the environment for X to startup
+ xserverWrapper = writeScript "xserver-wrapper"
+ ''
+ #! ${pkgs.bash}/bin/bash
+ ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)}
+
+ display=$(echo "$@" | xargs -n 1 | grep -P ^:\\d\$ | head -n 1 | sed s/^://)
+ if [ -z "$display" ]
+ then additionalArgs=":0 -logfile /var/log/X.0.log"
+ else additionalArgs="-logfile /var/log/X.$display.log"
+ fi
+
+ exec ${dmcfg.xserverBin} ${toString dmcfg.xserverArgs} $additionalArgs "$@"
+ '';
+
+ usersConf = writeText "users.conf"
+ ''
+ [UserList]
+ minimum-uid=500
+ hidden-users=${concatStringsSep " " dmcfg.hiddenUsers}
+ hidden-shells=/run/current-system/sw/bin/nologin
+ '';
+
+ lightdmConf = writeText "lightdm.conf"
+ ''
+ [LightDM]
+ ${optionalString cfg.greeter.enable ''
+ greeter-user = ${config.users.users.lightdm.name}
+ greeters-directory = ${cfg.greeter.package}
+ ''}
+ sessions-directory = ${dmcfg.session.desktops}/share/xsessions
+ ${cfg.extraConfig}
+
+ [Seat:*]
+ xserver-command = ${xserverWrapper}
+ session-wrapper = ${dmcfg.session.wrapper}
+ ${optionalString cfg.greeter.enable ''
+ greeter-session = ${cfg.greeter.name}
+ ''}
+ ${optionalString cfg.autoLogin.enable ''
+ autologin-user = ${cfg.autoLogin.user}
+ autologin-user-timeout = ${toString cfg.autoLogin.timeout}
+ autologin-session = ${defaultSessionName}
+ ''}
+ ${optionalString hasDefaultUserSession ''
+ user-session=${defaultSessionName}
+ ''}
+ ${optionalString (dmcfg.setupCommands != "") ''
+ display-setup-script=${pkgs.writeScript "lightdm-display-setup" ''
+ #!${pkgs.bash}/bin/bash
+ ${dmcfg.setupCommands}
+ ''}
+ ''}
+ ${cfg.extraSeatDefaults}
+ '';
+
+ defaultSessionName = dmDefault + optionalString (wmDefault != "none") ("+" + wmDefault);
+in
+{
+ # Note: the order in which lightdm greeter modules are imported
+ # here determines the default: later modules (if enable) are
+ # preferred.
+ imports = [
+ ./lightdm-greeters/gtk.nix
+ ./lightdm-greeters/mini.nix
+ ./lightdm-greeters/enso-os.nix
+ ./lightdm-greeters/pantheon.nix
+ ];
+
+ options = {
+
+ services.xserver.displayManager.lightdm = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable lightdm as the display manager.
+ '';
+ };
+
+ greeter = {
+ enable = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ If set to false, run lightdm in greeterless mode. This only works if autologin
+ is enabled and autoLogin.timeout is zero.
+ '';
+ };
+ package = mkOption {
+ type = types.package;
+ description = ''
+ The LightDM greeter to login via. The package should be a directory
+ containing a .desktop file matching the name in the 'name' option.
+ '';
+
+ };
+ name = mkOption {
+ type = types.str;
+ description = ''
+ The name of a .desktop file in the directory specified
+ in the 'package' option.
+ '';
+ };
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ user-authority-in-system-dir = true
+ '';
+ description = "Extra lines to append to LightDM section.";
+ };
+
+ background = mkOption {
+ type = types.str;
+ default = "${pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom}/share/artwork/gnome/nix-wallpaper-simple-dark-gray_bottom.png";
+ description = ''
+ The background image or color to use.
+ '';
+ };
+
+ extraSeatDefaults = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ greeter-show-manual-login=true
+ '';
+ description = "Extra lines to append to SeatDefaults section.";
+ };
+
+ autoLogin = mkOption {
+ default = {};
+ description = ''
+ Configuration for automatic login.
+ '';
+
+ type = types.submodule {
+ options = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Automatically log in as the specified <option>autoLogin.user</option>.
+ '';
+ };
+
+ user = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ User to be used for the automatic login.
+ '';
+ };
+
+ timeout = mkOption {
+ type = types.int;
+ default = 0;
+ description = ''
+ Show the greeter for this many seconds before automatic login occurs.
+ '';
+ };
+ };
+ };
+ };
+
+ };
+ };
+
+ config = mkIf cfg.enable {
+
+ assertions = [
+ { assertion = xcfg.enable;
+ message = ''
+ LightDM requires services.xserver.enable to be true
+ '';
+ }
+ { assertion = cfg.autoLogin.enable -> cfg.autoLogin.user != null;
+ message = ''
+ LightDM auto-login requires services.xserver.displayManager.lightdm.autoLogin.user to be set
+ '';
+ }
+ { assertion = cfg.autoLogin.enable -> dmDefault != "none" || wmDefault != "none";
+ message = ''
+ LightDM auto-login requires that services.xserver.desktopManager.default and
+ services.xserver.windowManager.default are set to valid values. The current
+ default session: ${defaultSessionName} is not valid.
+ '';
+ }
+ { assertion = !cfg.greeter.enable -> (cfg.autoLogin.enable && cfg.autoLogin.timeout == 0);
+ message = ''
+ LightDM can only run without greeter if automatic login is enabled and the timeout for it
+ is set to zero.
+ '';
+ }
+ ];
+
+ # lightdm relaunches itself via just `lightdm`, so needs to be on the PATH
+ services.xserver.displayManager.job.execCmd = ''
+ export PATH=${lightdm}/sbin:$PATH
+ exec ${lightdm}/sbin/lightdm
+ '';
+
+ environment.etc."lightdm/lightdm.conf".source = lightdmConf;
+ environment.etc."lightdm/users.conf".source = usersConf;
+
+ services.dbus.enable = true;
+ services.dbus.packages = [ lightdm ];
+
+ # lightdm uses the accounts daemon to remember language/window-manager per user
+ services.accounts-daemon.enable = true;
+
+ # Enable the accounts daemon to find lightdm's dbus interface
+ environment.systemPackages = [ lightdm ];
+
+ security.pam.services.lightdm.text = ''
+ auth substack login
+ account include login
+ password substack login
+ session include login
+ '';
+
+ security.pam.services.lightdm-greeter.text = ''
+ auth required pam_succeed_if.so audit quiet_success user = lightdm
+ auth optional pam_permit.so
+
+ account required pam_succeed_if.so audit quiet_success user = lightdm
+ account sufficient pam_unix.so
+
+ password required pam_deny.so
+
+ session required pam_succeed_if.so audit quiet_success user = lightdm
+ session required pam_env.so conffile=${config.system.build.pamEnvironment} readenv=0
+ session optional ${pkgs.systemd}/lib/security/pam_systemd.so
+ session optional pam_keyinit.so force revoke
+ session optional pam_permit.so
+ '';
+
+ security.pam.services.lightdm-autologin.text = ''
+ auth requisite pam_nologin.so
+
+ auth required pam_succeed_if.so uid >= 1000 quiet
+ auth required pam_permit.so
+
+ account sufficient pam_unix.so
+
+ password requisite pam_unix.so nullok sha512
+
+ session optional pam_keyinit.so revoke
+ session include login
+ '';
+
+ users.users.lightdm = {
+ home = "/var/lib/lightdm";
+ group = "lightdm";
+ uid = config.ids.uids.lightdm;
+ };
+
+ systemd.tmpfiles.rules = [
+ "d /run/lightdm 0711 lightdm lightdm 0"
+ "d /var/cache/lightdm 0711 root lightdm -"
+ "d /var/lib/lightdm 1770 lightdm lightdm -"
+ "d /var/lib/lightdm-data 1775 lightdm lightdm -"
+ "d /var/log/lightdm 0711 root lightdm -"
+ ];
+
+ users.groups.lightdm.gid = config.ids.gids.lightdm;
+ services.xserver.tty = null; # We might start multiple X servers so let the tty increment themselves..
+ services.xserver.display = null; # We specify our own display (and logfile) in xserver-wrapper up there
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix b/nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix
new file mode 100644
index 00000000000..8847acb0c60
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/sddm.nix
@@ -0,0 +1,298 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ xcfg = config.services.xserver;
+ dmcfg = xcfg.displayManager;
+ cfg = dmcfg.sddm;
+ xEnv = config.systemd.services.display-manager.environment;
+
+ inherit (pkgs) sddm;
+
+ xserverWrapper = pkgs.writeScript "xserver-wrapper" ''
+ #!/bin/sh
+ ${concatMapStrings (n: "export ${n}=\"${getAttr n xEnv}\"\n") (attrNames xEnv)}
+ exec systemd-cat ${dmcfg.xserverBin} ${toString dmcfg.xserverArgs} "$@"
+ '';
+
+ Xsetup = pkgs.writeScript "Xsetup" ''
+ #!/bin/sh
+ ${cfg.setupScript}
+ ${dmcfg.setupCommands}
+ '';
+
+ Xstop = pkgs.writeScript "Xstop" ''
+ #!/bin/sh
+ ${cfg.stopScript}
+ '';
+
+ cfgFile = pkgs.writeText "sddm.conf" ''
+ [General]
+ HaltCommand=${pkgs.systemd}/bin/systemctl poweroff
+ RebootCommand=${pkgs.systemd}/bin/systemctl reboot
+ ${optionalString cfg.autoNumlock ''
+ Numlock=on
+ ''}
+
+ [Theme]
+ Current=${cfg.theme}
+ ThemeDir=/run/current-system/sw/share/sddm/themes
+ FacesDir=/run/current-system/sw/share/sddm/faces
+
+ [Users]
+ MaximumUid=${toString config.ids.uids.nixbld}
+ HideUsers=${concatStringsSep "," dmcfg.hiddenUsers}
+ HideShells=/run/current-system/sw/bin/nologin
+
+ [X11]
+ MinimumVT=${toString (if xcfg.tty != null then xcfg.tty else 7)}
+ ServerPath=${xserverWrapper}
+ XephyrPath=${pkgs.xorg.xorgserver.out}/bin/Xephyr
+ SessionCommand=${dmcfg.session.wrapper}
+ SessionDir=${dmcfg.session.desktops}/share/xsessions
+ XauthPath=${pkgs.xorg.xauth}/bin/xauth
+ DisplayCommand=${Xsetup}
+ DisplayStopCommand=${Xstop}
+ EnableHidpi=${if cfg.enableHidpi then "true" else "false"}
+
+ [Wayland]
+ EnableHidpi=${if cfg.enableHidpi then "true" else "false"}
+ SessionDir=${dmcfg.session.desktops}/share/wayland-sessions
+
+ ${optionalString cfg.autoLogin.enable ''
+ [Autologin]
+ User=${cfg.autoLogin.user}
+ Session=${defaultSessionName}.desktop
+ Relogin=${boolToString cfg.autoLogin.relogin}
+ ''}
+
+ ${cfg.extraConfig}
+ '';
+
+ defaultSessionName =
+ let
+ dm = xcfg.desktopManager.default;
+ wm = xcfg.windowManager.default;
+ in dm + optionalString (wm != "none") ("+" + wm);
+
+in
+{
+ options = {
+
+ services.xserver.displayManager.sddm = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable sddm as the display manager.
+ '';
+ };
+
+ enableHidpi = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to enable automatic HiDPI mode.
+ </para>
+ <para>
+ Versions up to 0.17 are broken so this only works from 0.18 onwards.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ [Autologin]
+ User=john
+ Session=plasma.desktop
+ '';
+ description = ''
+ Extra lines appended to the configuration of SDDM.
+ '';
+ };
+
+ theme = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ Greeter theme to use.
+ '';
+ };
+
+ autoNumlock = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Enable numlock at login.
+ '';
+ };
+
+ setupScript = mkOption {
+ type = types.str;
+ default = "";
+ example = ''
+ # workaround for using NVIDIA Optimus without Bumblebee
+ xrandr --setprovideroutputsource modesetting NVIDIA-0
+ xrandr --auto
+ '';
+ description = ''
+ A script to execute when starting the display server. DEPRECATED, please
+ use <option>services.xserver.displayManager.setupCommands</option>.
+ '';
+ };
+
+ stopScript = mkOption {
+ type = types.str;
+ default = "";
+ description = ''
+ A script to execute when stopping the display server.
+ '';
+ };
+
+ autoLogin = mkOption {
+ default = {};
+ description = ''
+ Configuration for automatic login.
+ '';
+
+ type = types.submodule {
+ options = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Automatically log in as <option>autoLogin.user</option>.
+ '';
+ };
+
+ user = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = ''
+ User to be used for the automatic login.
+ '';
+ };
+
+ relogin = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ If true automatic login will kick in again on session exit (logout), otherwise it
+ will only log in automatically when the display-manager is started.
+ '';
+ };
+ };
+ };
+ };
+
+ };
+
+ };
+
+ config = mkIf cfg.enable {
+
+ assertions = [
+ { assertion = xcfg.enable;
+ message = ''
+ SDDM requires services.xserver.enable to be true
+ '';
+ }
+ { assertion = cfg.autoLogin.enable -> cfg.autoLogin.user != null;
+ message = ''
+ SDDM auto-login requires services.xserver.displayManager.sddm.autoLogin.user to be set
+ '';
+ }
+ { assertion = cfg.autoLogin.enable -> elem defaultSessionName dmcfg.session.names;
+ message = ''
+ SDDM auto-login requires that services.xserver.desktopManager.default and
+ services.xserver.windowManager.default are set to valid values. The current
+ default session: ${defaultSessionName} is not valid.
+ '';
+ }
+ ];
+
+ services.xserver.displayManager.job = {
+ environment = {
+ # Load themes from system environment
+ QT_PLUGIN_PATH = "/run/current-system/sw/" + pkgs.qt5.qtbase.qtPluginPrefix;
+ QML2_IMPORT_PATH = "/run/current-system/sw/" + pkgs.qt5.qtbase.qtQmlPrefix;
+ };
+
+ execCmd = "exec /run/current-system/sw/bin/sddm";
+ };
+
+ security.pam.services = {
+ sddm = {
+ allowNullPassword = true;
+ startSession = true;
+ };
+
+ sddm-greeter.text = ''
+ auth required pam_succeed_if.so audit quiet_success user = sddm
+ auth optional pam_permit.so
+
+ account required pam_succeed_if.so audit quiet_success user = sddm
+ account sufficient pam_unix.so
+
+ password required pam_deny.so
+
+ session required pam_succeed_if.so audit quiet_success user = sddm
+ session required pam_env.so conffile=${config.system.build.pamEnvironment} readenv=0
+ session optional ${pkgs.systemd}/lib/security/pam_systemd.so
+ session optional pam_keyinit.so force revoke
+ session optional pam_permit.so
+ '';
+
+ sddm-autologin.text = ''
+ auth requisite pam_nologin.so
+ auth required pam_succeed_if.so uid >= 1000 quiet
+ auth required pam_permit.so
+
+ account include sddm
+
+ password include sddm
+
+ session include sddm
+ '';
+ };
+
+ users.users.sddm = {
+ createHome = true;
+ home = "/var/lib/sddm";
+ group = "sddm";
+ uid = config.ids.uids.sddm;
+ };
+
+ environment.etc."sddm.conf".source = cfgFile;
+ environment.pathsToLink = [
+ "/share/sddm"
+ ];
+
+ users.groups.sddm.gid = config.ids.gids.sddm;
+
+ environment.systemPackages = [ sddm ];
+ services.dbus.packages = [ sddm ];
+
+ # To enable user switching, allow sddm to allocate TTYs/displays dynamically.
+ services.xserver.tty = null;
+ services.xserver.display = null;
+
+ systemd.tmpfiles.rules = [
+ # Prior to Qt 5.9.2, there is a QML cache invalidation bug which sometimes
+ # strikes new Plasma 5 releases. If the QML cache is not invalidated, SDDM
+ # will segfault without explanation. We really tore our hair out for awhile
+ # before finding the bug:
+ # https://bugreports.qt.io/browse/QTBUG-62302
+ # We work around the problem by deleting the QML cache before startup.
+ # This was supposedly fixed in Qt 5.9.2 however it has been reported with
+ # 5.10 and 5.11 as well. The initial workaround was to delete the directory
+ # in the Xsetup script but that doesn't do anything.
+ # Instead we use tmpfiles.d to ensure it gets wiped.
+ # This causes a small but perceptible delay when SDDM starts.
+ "e ${config.users.users.sddm.home}/.cache - - - 0"
+ ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/slim.nix b/nixpkgs/nixos/modules/services/x11/display-managers/slim.nix
new file mode 100644
index 00000000000..124660a43f0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/slim.nix
@@ -0,0 +1,156 @@
+{ config, lib, pkgs, ... }:
+
+with 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 ${toString dmcfg.xserverArgs}
+ sessiondir ${dmcfg.session.desktops}/share/xsessions
+ login_cmd exec ${pkgs.runtimeShell} ${dmcfg.session.wrapper} "%session"
+ halt_cmd ${config.systemd.package}/sbin/shutdown -h now
+ reboot_cmd ${config.systemd.package}/sbin/shutdown -r now
+ logfile /dev/stderr
+ ${optionalString (cfg.defaultUser != null) ("default_user " + cfg.defaultUser)}
+ ${optionalString (cfg.defaultUser != null) ("focus_password yes")}
+ ${optionalString cfg.autoLogin "auto_login yes"}
+ ${optionalString (cfg.consoleCmd != null) "console_cmd ${cfg.consoleCmd}"}
+ ${cfg.extraConfig}
+ '';
+
+ # Unpack the SLiM theme, or use the default.
+ slimThemesDir =
+ let
+ unpackedTheme = pkgs.runCommand "slim-theme" { preferLocalBuild = true; }
+ ''
+ mkdir -p $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 {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable SLiM as the display manager.
+ '';
+ };
+
+ theme = mkOption {
+ type = types.nullOr types.path;
+ default = pkgs.fetchurl {
+ url = "https://github.com/jagajaga/nixos-slim-theme/archive/2.0.tar.gz";
+ sha256 = "0lldizhigx7bjhxkipii87y432hlf5wdvamnfxrryf9z7zkfypc8";
+ };
+ defaultText = ''pkgs.fetchurl {
+ url = "https://github.com/jagajaga/nixos-slim-theme/archive/2.0.tar.gz";
+ sha256 = "0lldizhigx7bjhxkipii87y432hlf5wdvamnfxrryf9z7zkfypc8";
+ }'';
+ example = literalExample ''
+ pkgs.fetchurl {
+ url = "mirror://sourceforge/slim.berlios/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. TODO: berlios shut down.
+ '';
+ };
+
+ defaultUser = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ 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 {
+ type = types.bool;
+ default = false;
+ description = ''
+ Automatically log in as the default user.
+ '';
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = ''
+ Extra configuration options for SLiM login manager. Do not
+ add options that can be configured directly.
+ '';
+ };
+
+ consoleCmd = mkOption {
+ type = types.nullOr types.str;
+ default = ''
+ ${pkgs.xterm}/bin/xterm -C -fg white -bg black +sb -T "Console login" -e ${pkgs.shadow}/bin/login
+ '';
+ defaultText = ''
+ ''${pkgs.xterm}/bin/xterm -C -fg white -bg black +sb -T "Console login" -e ''${pkgs.shadow}/bin/login
+ '';
+ description = ''
+ The command to run when "console" is given as the username.
+ '';
+ };
+ };
+
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.xserver.displayManager.job =
+ { environment =
+ { SLIM_CFGFILE = slimConfig;
+ SLIM_THEMESDIR = slimThemesDir;
+ };
+ execCmd = "exec ${pkgs.slim}/bin/slim";
+ };
+
+ services.xserver.displayManager.sessionCommands =
+ ''
+ # Export the config/themes for slimlock.
+ export SLIM_THEMESDIR=${slimThemesDir}
+ '';
+
+ # Allow null passwords so that the user can login as root on the
+ # installation CD.
+ security.pam.services.slim = { allowNullPassword = true; startSession = true; };
+
+ # Allow slimlock to work.
+ security.pam.services.slimlock = {};
+
+ environment.systemPackages = [ pkgs.slim ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/startx.nix b/nixpkgs/nixos/modules/services/x11/display-managers/startx.nix
new file mode 100644
index 00000000000..57046984358
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/startx.nix
@@ -0,0 +1,44 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.displayManager.startx;
+
+in
+
+{
+
+ ###### interface
+
+ options = {
+ services.xserver.displayManager.startx = {
+ enable = mkOption {
+ default = false;
+ description = ''
+ Whether to enable the dummy "startx" pseudo-display manager,
+ which allows users to start X manually via the "startx" command
+ from a vt shell. The X server runs under the user's id, not as root.
+ The user must provide a ~/.xinitrc file containing session startup
+ commands, see startx(1). This is not automatically generated
+ from the desktopManager and windowManager settings.
+ '';
+ };
+ };
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+ services.xserver = {
+ exportConfiguration = true;
+ displayManager.job.execCmd = "";
+ displayManager.lightdm.enable = lib.mkForce false;
+ };
+ systemd.services.display-manager.enable = false;
+ environment.systemPackages = with pkgs; [ xorg.xinit ];
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/display-managers/xpra.nix b/nixpkgs/nixos/modules/services/x11/display-managers/xpra.nix
new file mode 100644
index 00000000000..c23e479140f
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/display-managers/xpra.nix
@@ -0,0 +1,252 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.displayManager.xpra;
+ dmcfg = config.services.xserver.displayManager;
+
+in
+
+{
+ ###### interface
+
+ options = {
+ services.xserver.displayManager.xpra = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to enable xpra as display manager.";
+ };
+
+ bindTcp = mkOption {
+ default = "127.0.0.1:10000";
+ example = "0.0.0.0:10000";
+ type = types.nullOr types.str;
+ description = "Bind xpra to TCP";
+ };
+
+ auth = mkOption {
+ type = types.str;
+ default = "pam";
+ example = "password:value=mysecret";
+ description = "Authentication to use when connecting to xpra";
+ };
+
+ pulseaudio = mkEnableOption "pulseaudio audio streaming";
+
+ extraOptions = mkOption {
+ description = "Extra xpra options";
+ default = [];
+ type = types.listOf types.str;
+ };
+ };
+ };
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+ services.xserver.videoDrivers = ["dummy"];
+
+ services.xserver.monitorSection = ''
+ HorizSync 1.0 - 2000.0
+ VertRefresh 1.0 - 200.0
+ #To add your own modes here, use a modeline calculator, like:
+ # cvt:
+ # http://www.x.org/archive/X11R7.5/doc/man/man1/cvt.1.html
+ # xtiming:
+ # http://xtiming.sourceforge.net/cgi-bin/xtiming.pl
+ # gtf:
+ # http://gtf.sourceforge.net/
+ #This can be used to get a specific DPI, but only for the default resolution:
+ #DisplaySize 508 317
+ #NOTE: the highest modes will not work without increasing the VideoRam
+ # for the dummy video card.
+ #Modeline "16000x15000" 300.00 16000 16408 18000 20000 15000 15003 15013 15016
+ #Modeline "15000x15000" 281.25 15000 15376 16872 18744 15000 15003 15013 15016
+ #Modeline "16384x8192" 167.75 16384 16800 18432 20480 8192 8195 8205 8208
+ #Modeline "15360x8640" 249.00 15360 15752 17280 19200 8640 8643 8648 8651
+ Modeline "8192x4096" 193.35 8192 8224 8952 8984 4096 4196 4200 4301
+ Modeline "7680x4320" 208.00 7680 7880 8640 9600 4320 4323 4328 4335
+ Modeline "6400x4096" 151.38 6400 6432 7000 7032 4096 4196 4200 4301
+ Modeline "6400x2560" 91.59 6400 6432 6776 6808 2560 2623 2626 2689
+ Modeline "6400x2160" 160.51 6400 6432 7040 7072 2160 2212 2216 2269
+ Modeline "5760x2160" 149.50 5760 5768 6320 6880 2160 2161 2164 2173
+ Modeline "5680x1440" 142.66 5680 5712 6248 6280 1440 1474 1478 1513
+ Modeline "5496x1200" 199.13 5496 5528 6280 6312 1200 1228 1233 1261
+ Modeline "5280x2560" 75.72 5280 5312 5592 5624 2560 2623 2626 2689
+ Modeline "5280x1920" 56.04 5280 5312 5520 5552 1920 1967 1969 2017
+ Modeline "5280x1200" 191.40 5280 5312 6032 6064 1200 1228 1233 1261
+ Modeline "5280x1080" 169.96 5280 5312 5952 5984 1080 1105 1110 1135
+ Modeline "5120x3200" 199.75 5120 5152 5904 5936 3200 3277 3283 3361
+ Modeline "5120x2560" 73.45 5120 5152 5424 5456 2560 2623 2626 2689
+ Modeline "5120x2880" 185.50 5120 5256 5760 6400 2880 2883 2888 2899
+ Modeline "4800x1200" 64.42 4800 4832 5072 5104 1200 1229 1231 1261
+ Modeline "4720x3840" 227.86 4720 4752 5616 5648 3840 3933 3940 4033
+ Modeline "4400x2560" 133.70 4400 4432 4936 4968 2560 2622 2627 2689
+ Modeline "4480x1440" 72.94 4480 4512 4784 4816 1440 1475 1478 1513
+ Modeline "4240x1440" 69.09 4240 4272 4528 4560 1440 1475 1478 1513
+ Modeline "4160x1440" 67.81 4160 4192 4448 4480 1440 1475 1478 1513
+ Modeline "4096x2304" 249.25 4096 4296 4720 5344 2304 2307 2312 2333
+ Modeline "4096x2160" 111.25 4096 4200 4608 5120 2160 2163 2173 2176
+ Modeline "4000x1660" 170.32 4000 4128 4536 5072 1660 1661 1664 1679
+ Modeline "4000x1440" 145.00 4000 4088 4488 4976 1440 1441 1444 1457
+ Modeline "3904x1440" 63.70 3904 3936 4176 4208 1440 1475 1478 1513
+ Modeline "3840x2880" 133.43 3840 3872 4376 4408 2880 2950 2955 3025
+ Modeline "3840x2560" 116.93 3840 3872 4312 4344 2560 2622 2627 2689
+ Modeline "3840x2160" 104.25 3840 3944 4320 4800 2160 2163 2168 2175
+ Modeline "3840x2048" 91.45 3840 3872 4216 4248 2048 2097 2101 2151
+ Modeline "3840x1200" 108.89 3840 3872 4280 4312 1200 1228 1232 1261
+ Modeline "3840x1080" 100.38 3840 3848 4216 4592 1080 1081 1084 1093
+ Modeline "3864x1050" 94.58 3864 3896 4248 4280 1050 1074 1078 1103
+ Modeline "3600x1200" 106.06 3600 3632 3984 4368 1200 1201 1204 1214
+ Modeline "3600x1080" 91.02 3600 3632 3976 4008 1080 1105 1109 1135
+ Modeline "3520x1196" 99.53 3520 3552 3928 3960 1196 1224 1228 1256
+ Modeline "3360x2560" 102.55 3360 3392 3776 3808 2560 2622 2627 2689
+ Modeline "3360x1050" 293.75 3360 3576 3928 4496 1050 1053 1063 1089
+ Modeline "3288x1080" 39.76 3288 3320 3464 3496 1080 1106 1108 1135
+ Modeline "3200x1800" 233.00 3200 3384 3720 4240 1800 1803 1808 1834
+ Modeline "3200x1080" 236.16 3200 3232 4128 4160 1080 1103 1112 1135
+ Modeline "3120x2560" 95.36 3120 3152 3512 3544 2560 2622 2627 2689
+ Modeline "3120x1050" 272.75 3120 3320 3648 4176 1050 1053 1063 1089
+ Modeline "3072x2560" 93.92 3072 3104 3456 3488 2560 2622 2627 2689
+ Modeline "3008x1692" 130.93 3008 3112 3416 3824 1692 1693 1696 1712
+ Modeline "3000x2560" 91.77 3000 3032 3376 3408 2560 2622 2627 2689
+ Modeline "2880x1620" 396.25 2880 3096 3408 3936 1620 1623 1628 1679
+ Modeline "2728x1680" 148.02 2728 2760 3320 3352 1680 1719 1726 1765
+ Modeline "2560x2240" 151.55 2560 2688 2952 3344 2240 2241 2244 2266
+ Modeline "2560x1600" 47.12 2560 2592 2768 2800 1600 1639 1642 1681
+ Modeline "2560x1440" 42.12 2560 2592 2752 2784 1440 1475 1478 1513
+ Modeline "2560x1400" 267.86 2560 2592 3608 3640 1400 1429 1441 1471
+ Modeline "2048x2048" 49.47 2048 2080 2264 2296 2048 2097 2101 2151
+ Modeline "2048x1536" 80.06 2048 2104 2312 2576 1536 1537 1540 1554
+ Modeline "2048x1152" 197.97 2048 2184 2408 2768 1152 1153 1156 1192
+ Modeline "2048x1152" 165.92 2048 2080 2704 2736 1152 1176 1186 1210
+ Modeline "1920x1440" 69.47 1920 1960 2152 2384 1440 1441 1444 1457
+ Modeline "1920x1200" 26.28 1920 1952 2048 2080 1200 1229 1231 1261
+ Modeline "1920x1080" 23.53 1920 1952 2040 2072 1080 1106 1108 1135
+ Modeline "1728x1520" 205.42 1728 1760 2536 2568 1520 1552 1564 1597
+ Modeline "1680x1050" 20.08 1680 1712 1784 1816 1050 1075 1077 1103
+ Modeline "1600x1200" 22.04 1600 1632 1712 1744 1200 1229 1231 1261
+ Modeline "1600x900" 33.92 1600 1632 1760 1792 900 921 924 946
+ Modeline "1440x900" 30.66 1440 1472 1584 1616 900 921 924 946
+ Modeline "1400x900" 103.50 1400 1480 1624 1848 900 903 913 934
+ ModeLine "1366x768" 72.00 1366 1414 1446 1494 768 771 777 803
+ Modeline "1360x768" 24.49 1360 1392 1480 1512 768 786 789 807
+ Modeline "1280x1024" 31.50 1280 1312 1424 1456 1024 1048 1052 1076
+ Modeline "1280x800" 24.15 1280 1312 1400 1432 800 819 822 841
+ Modeline "1280x768" 23.11 1280 1312 1392 1424 768 786 789 807
+ Modeline "1280x720" 59.42 1280 1312 1536 1568 720 735 741 757
+ Modeline "1024x768" 18.71 1024 1056 1120 1152 768 786 789 807
+ Modeline "1024x640" 41.98 1024 1056 1208 1240 640 653 659 673
+ Modeline "1024x576" 46.50 1024 1064 1160 1296 576 579 584 599
+ Modeline "768x1024" 19.50 768 800 872 904 1024 1048 1052 1076
+ Modeline "960x540" 40.75 960 992 1088 1216 540 543 548 562
+ Modeline "864x486" 32.50 864 888 968 1072 486 489 494 506
+ Modeline "720x405" 22.50 720 744 808 896 405 408 413 422
+ Modeline "640x360" 14.75 640 664 720 800 360 363 368 374
+ #common resolutions for android devices (both orientations):
+ Modeline "800x1280" 25.89 800 832 928 960 1280 1310 1315 1345
+ Modeline "1280x800" 24.15 1280 1312 1400 1432 800 819 822 841
+ Modeline "720x1280" 30.22 720 752 864 896 1280 1309 1315 1345
+ Modeline "1280x720" 27.41 1280 1312 1416 1448 720 737 740 757
+ Modeline "768x1024" 24.93 768 800 888 920 1024 1047 1052 1076
+ Modeline "1024x768" 23.77 1024 1056 1144 1176 768 785 789 807
+ Modeline "600x1024" 19.90 600 632 704 736 1024 1047 1052 1076
+ Modeline "1024x600" 18.26 1024 1056 1120 1152 600 614 617 631
+ Modeline "536x960" 16.74 536 568 624 656 960 982 986 1009
+ Modeline "960x536" 15.23 960 992 1048 1080 536 548 551 563
+ Modeline "600x800" 15.17 600 632 688 720 800 818 822 841
+ Modeline "800x600" 14.50 800 832 880 912 600 614 617 631
+ Modeline "480x854" 13.34 480 512 560 592 854 873 877 897
+ Modeline "848x480" 12.09 848 880 920 952 480 491 493 505
+ Modeline "480x800" 12.43 480 512 552 584 800 818 822 841
+ Modeline "800x480" 11.46 800 832 872 904 480 491 493 505
+ #resolutions for android devices (both orientations)
+ #minus the status bar
+ #38px status bar (and width rounded up)
+ Modeline "800x1242" 25.03 800 832 920 952 1242 1271 1275 1305
+ Modeline "1280x762" 22.93 1280 1312 1392 1424 762 780 783 801
+ Modeline "720x1242" 29.20 720 752 856 888 1242 1271 1276 1305
+ Modeline "1280x682" 25.85 1280 1312 1408 1440 682 698 701 717
+ Modeline "768x986" 23.90 768 800 888 920 986 1009 1013 1036
+ Modeline "1024x730" 22.50 1024 1056 1136 1168 730 747 750 767
+ Modeline "600x986" 19.07 600 632 704 736 986 1009 1013 1036
+ Modeline "1024x562" 17.03 1024 1056 1120 1152 562 575 578 591
+ Modeline "536x922" 16.01 536 568 624 656 922 943 947 969
+ Modeline "960x498" 14.09 960 992 1040 1072 498 509 511 523
+ Modeline "600x762" 14.39 600 632 680 712 762 779 783 801
+ Modeline "800x562" 13.52 800 832 880 912 562 575 578 591
+ Modeline "480x810" 12.59 480 512 552 584 810 828 832 851
+ Modeline "848x442" 11.09 848 880 920 952 442 452 454 465
+ Modeline "480x762" 11.79 480 512 552 584 762 779 783 801
+ '';
+
+ services.xserver.resolutions = [
+ {x="8192"; y="4096";}
+ {x="5120"; y="3200";}
+ {x="3840"; y="2880";}
+ {x="3840"; y="2560";}
+ {x="3840"; y="2048";}
+ {x="3840"; y="2160";}
+ {x="2048"; y="2048";}
+ {x="2560"; y="1600";}
+ {x="1920"; y="1440";}
+ {x="1920"; y="1200";}
+ {x="1920"; y="1080";}
+ {x="1600"; y="1200";}
+ {x="1680"; y="1050";}
+ {x="1600"; y="900";}
+ {x="1400"; y="1050";}
+ {x="1440"; y="900";}
+ {x="1280"; y="1024";}
+ {x="1366"; y="768";}
+ {x="1280"; y="800";}
+ {x="1024"; y="768";}
+ {x="1024"; y="600";}
+ {x="800"; y="600";}
+ {x="320"; y="200";}
+ ];
+
+ services.xserver.serverFlagsSection = ''
+ Option "DontVTSwitch" "true"
+ Option "PciForceNone" "true"
+ Option "AutoEnableDevices" "false"
+ Option "AutoAddDevices" "false"
+ '';
+
+ services.xserver.deviceSection = ''
+ VideoRam 192000
+ '';
+
+ services.xserver.displayManager.job.execCmd = ''
+ ${optionalString (cfg.pulseaudio)
+ "export PULSE_COOKIE=/run/pulse/.config/pulse/cookie"}
+ exec ${pkgs.xpra}/bin/xpra start \
+ --daemon=off \
+ --log-dir=/var/log \
+ --log-file=xpra.log \
+ --opengl=on \
+ --clipboard=on \
+ --notifications=on \
+ --speaker=yes \
+ --mdns=no \
+ --pulseaudio=no \
+ ${optionalString (cfg.pulseaudio) "--sound-source=pulse"} \
+ --socket-dirs=/run/xpra \
+ --xvfb="xpra_Xdummy ${concatStringsSep " " dmcfg.xserverArgs}" \
+ ${optionalString (cfg.bindTcp != null) "--bind-tcp=${cfg.bindTcp}"} \
+ --auth=${cfg.auth} \
+ ${concatStringsSep " " cfg.extraOptions}
+ '';
+
+ services.xserver.terminateOnReset = false;
+
+ environment.systemPackages = [pkgs.xpra];
+
+ virtualisation.virtualbox.guest.x11 = false;
+ hardware.pulseaudio.enable = mkDefault cfg.pulseaudio;
+ hardware.pulseaudio.systemWide = mkDefault cfg.pulseaudio;
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/extra-layouts.nix b/nixpkgs/nixos/modules/services/x11/extra-layouts.nix
new file mode 100644
index 00000000000..1af98a1318b
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/extra-layouts.nix
@@ -0,0 +1,168 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ layouts = config.services.xserver.extraLayouts;
+
+ layoutOpts = {
+ options = {
+ description = mkOption {
+ type = types.str;
+ description = "A short description of the layout.";
+ };
+
+ languages = mkOption {
+ type = types.listOf types.str;
+ description =
+ ''
+ A list of languages provided by the layout.
+ (Use ISO 639-2 codes, for example: "eng" for english)
+ '';
+ };
+
+ compatFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ The path to the xkb compat file.
+ This file sets the compatibility state, used to preserve
+ compatibility with xkb-unaware programs.
+ It must contain a <literal>xkb_compat "name" { ... }</literal> block.
+ '';
+ };
+
+ geometryFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ The path to the xkb geometry file.
+ This (completely optional) file describes the physical layout of
+ keyboard, which maybe be used by programs to depict it.
+ It must contain a <literal>xkb_geometry "name" { ... }</literal> block.
+ '';
+ };
+
+ keycodesFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ The path to the xkb keycodes file.
+ This file specifies the range and the interpretation of the raw
+ keycodes sent by the keyboard.
+ It must contain a <literal>xkb_keycodes "name" { ... }</literal> block.
+ '';
+ };
+
+ symbolsFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ The path to the xkb symbols file.
+ This is the most important file: it defines which symbol or action
+ maps to each key and must contain a
+ <literal>xkb_symbols "name" { ... }</literal> block.
+ '';
+ };
+
+ typesFile = mkOption {
+ type = types.nullOr types.path;
+ default = null;
+ description = ''
+ The path to the xkb types file.
+ This file specifies the key types that can be associated with
+ the various keyboard keys.
+ It must contain a <literal>xkb_types "name" { ... }</literal> block.
+ '';
+ };
+
+ };
+ };
+
+in
+
+{
+
+ ###### interface
+
+ options.services.xserver = {
+ extraLayouts = mkOption {
+ type = types.attrsOf (types.submodule layoutOpts);
+ default = {};
+ example = literalExample
+ ''
+ {
+ mine = {
+ description = "My custom xkb layout.";
+ languages = [ "eng" ];
+ symbolsFile = /path/to/my/layout;
+ };
+ }
+ '';
+ description = ''
+ Extra custom layouts that will be included in the xkb configuration.
+ Information on how to create a new layout can be found here:
+ <link xlink:href="https://www.x.org/releases/current/doc/xorg-docs/input/XKB-Enhancing.html#Defining_New_Layouts"></link>.
+ For more examples see
+ <link xlink:href="https://wiki.archlinux.org/index.php/X_KeyBoard_extension#Basic_examples"></link>
+ '';
+ };
+
+ };
+
+ ###### implementation
+
+ config = mkIf (layouts != { }) {
+
+ # We don't override xkeyboard_config directly to
+ # reduce the amount of packages to be recompiled.
+ # Only the following packages are necessary to set
+ # a custom layout anyway:
+ nixpkgs.overlays = lib.singleton (self: super: {
+
+ xkb_patched = self.xorg.xkeyboardconfig_custom {
+ layouts = config.services.xserver.extraLayouts;
+ };
+
+ xorg = super.xorg // {
+ xorgserver = super.xorg.xorgserver.overrideAttrs (old: {
+ configureFlags = old.configureFlags ++ [
+ "--with-xkb-bin-directory=${self.xorg.xkbcomp}/bin"
+ "--with-xkb-path=${self.xkb_patched}/share/X11/xkb"
+ ];
+ });
+
+ setxkbmap = super.xorg.setxkbmap.overrideAttrs (old: {
+ postInstall =
+ ''
+ mkdir -p $out/share
+ ln -sfn ${self.xkb_patched}/etc/X11 $out/share/X11
+ '';
+ });
+
+ xkbcomp = super.xorg.xkbcomp.overrideAttrs (old: {
+ configureFlags = "--with-xkb-config-root=${self.xkb_patched}/share/X11/xkb";
+ });
+
+ };
+
+ ckbcomp = super.ckbcomp.override {
+ xkeyboard_config = self.xkb_patched;
+ };
+
+ xkbvalidate = super.xkbvalidate.override {
+ libxkbcommon = self.libxkbcommon.override {
+ xkeyboard_config = self.xkb_patched;
+ };
+ };
+
+ });
+
+ services.xserver = {
+ xkbDir = "${pkgs.xkb_patched}/etc/X11/xkb";
+ exportConfiguration = config.services.xserver.displayManager.startx.enable;
+ };
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/fractalart.nix b/nixpkgs/nixos/modules/services/x11/fractalart.nix
new file mode 100644
index 00000000000..448248a5879
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/fractalart.nix
@@ -0,0 +1,36 @@
+{ config, lib, pkgs, ... }:
+with lib;
+let
+ cfg = config.services.fractalart;
+in {
+ options.services.fractalart = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ example = true;
+ description = "Enable FractalArt for generating colorful wallpapers on login";
+ };
+
+ width = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ example = 1920;
+ description = "Screen width";
+ };
+
+ height = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ example = 1080;
+ description = "Screen height";
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = [ pkgs.haskellPackages.FractalArt ];
+ services.xserver.displayManager.sessionCommands =
+ "${pkgs.haskellPackages.FractalArt}/bin/FractalArt --no-bg -f .background-image"
+ + optionalString (cfg.width != null) " -w ${toString cfg.width}"
+ + optionalString (cfg.height != null) " -h ${toString cfg.height}";
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/gdk-pixbuf.nix b/nixpkgs/nixos/modules/services/x11/gdk-pixbuf.nix
new file mode 100644
index 00000000000..9ad926369ec
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/gdk-pixbuf.nix
@@ -0,0 +1,45 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.gdk-pixbuf;
+
+ # Get packages to generate the cache for. We always include gdk-pixbuf.
+ effectivePackages = unique ([pkgs.gdk-pixbuf] ++ cfg.modulePackages);
+
+ # Generate the cache file by running gdk-pixbuf-query-loaders for each
+ # package and concatenating the results.
+ loadersCache = pkgs.runCommand "gdk-pixbuf-loaders.cache" { preferLocalBuild = true; } ''
+ (
+ for package in ${concatStringsSep " " effectivePackages}; do
+ module_dir="$package/${pkgs.gdk-pixbuf.moduleDir}"
+ if [[ ! -d $module_dir ]]; then
+ echo "Warning (services.xserver.gdk-pixbuf): missing module directory $module_dir" 1>&2
+ continue
+ fi
+ GDK_PIXBUF_MODULEDIR="$module_dir" \
+ ${pkgs.gdk-pixbuf.dev}/bin/gdk-pixbuf-query-loaders
+ done
+ ) > "$out"
+ '';
+in
+
+{
+ options = {
+ services.xserver.gdk-pixbuf.modulePackages = mkOption {
+ type = types.listOf types.package;
+ default = [ ];
+ description = "Packages providing GDK-Pixbuf modules, for cache generation.";
+ };
+ };
+
+ # If there is any package configured in modulePackages, we generate the
+ # loaders.cache based on that and set the environment variable
+ # GDK_PIXBUF_MODULE_FILE to point to it.
+ config = mkIf (cfg.modulePackages != []) {
+ environment.variables = {
+ GDK_PIXBUF_MODULE_FILE = "${loadersCache}";
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/hardware/cmt.nix b/nixpkgs/nixos/modules/services/x11/hardware/cmt.nix
new file mode 100644
index 00000000000..95353e92098
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/hardware/cmt.nix
@@ -0,0 +1,54 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+cfg = config.services.xserver.cmt;
+etcPath = "X11/xorg.conf.d";
+
+in {
+
+ options = {
+
+ services.xserver.cmt = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enable chrome multitouch input (cmt). Touchpad drivers that are configured for chromebooks.";
+ };
+ models = mkOption {
+ type = types.enum [ "atlas" "banjo" "candy" "caroline" "cave" "celes" "clapper" "cyan" "daisy" "elan" "elm" "enguarde" "eve" "expresso" "falco" "gandof" "glimmer" "gnawty" "heli" "kevin" "kip" "leon" "lulu" "orco" "pbody" "peppy" "pi" "pit" "puppy" "quawks" "rambi" "samus" "snappy" "spring" "squawks" "swanky" "winky" "wolf" "auron_paine" "auron_yuna" "daisy_skate" "nyan_big" "nyan_blaze" "veyron_jaq" "veyron_jerry" "veyron_mighty" "veyron_minnie" "veyron_speedy" ];
+ example = "banjo";
+ description = ''
+ Which models to enable cmt for. Enter the Code Name for your Chromebook.
+ Code Name can be found at <link xlink:href="https://www.chromium.org/chromium-os/developer-information-for-chrome-os-devices" />.
+ '';
+ };
+ }; #closes services
+ }; #closes options
+
+ config = mkIf cfg.enable {
+
+ services.xserver.modules = [ pkgs.xf86_input_cmt ];
+
+ environment.etc = {
+ "${etcPath}/40-touchpad-cmt.conf" = {
+ source = "${pkgs.chromium-xorg-conf}/40-touchpad-cmt.conf";
+ };
+ "${etcPath}/50-touchpad-cmt-${cfg.models}.conf" = {
+ source = "${pkgs.chromium-xorg-conf}/50-touchpad-cmt-${cfg.models}.conf";
+ };
+ "${etcPath}/60-touchpad-cmt-${cfg.models}.conf" = {
+ source = "${pkgs.chromium-xorg-conf}/60-touchpad-cmt-${cfg.models}.conf";
+ };
+ };
+
+ assertions = [
+ {
+ assertion = !config.services.xserver.libinput.enable;
+ message = "cmt and libinput are incompatible, you cannot enable both (in services.xserver).";
+ }
+ ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/hardware/libinput.nix b/nixpkgs/nixos/modules/services/x11/hardware/libinput.nix
new file mode 100644
index 00000000000..bd289976532
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/hardware/libinput.nix
@@ -0,0 +1,247 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.xserver.libinput;
+ xorgBool = v: if v then "on" else "off";
+in {
+
+ options = {
+
+ services.xserver.libinput = {
+
+ enable = mkEnableOption "libinput";
+
+ dev = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "/dev/input/event0";
+ description =
+ ''
+ Path for touchpad device. Set to null to apply to any
+ auto-detected touchpad.
+ '';
+ };
+
+ accelProfile = mkOption {
+ type = types.enum [ "flat" "adaptive" ];
+ default = "adaptive";
+ example = "flat";
+ description =
+ ''
+ Sets the pointer acceleration profile to the given profile.
+ Permitted values are adaptive, flat.
+ Not all devices support this option or all profiles.
+ If a profile is unsupported, the default profile for this is used.
+ <literal>flat</literal>: Pointer motion is accelerated by a constant
+ (device-specific) factor, depending on the current speed.
+ <literal>adaptive</literal>: Pointer acceleration depends on the input speed.
+ This is the default profile for most devices.
+ '';
+ };
+
+ accelSpeed = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description = "Cursor acceleration (how fast speed increases from minSpeed to maxSpeed).";
+ };
+
+ buttonMapping = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description =
+ ''
+ Sets the logical button mapping for this device, see XSetPointerMapping(3). The string must
+ be a space-separated list of button mappings in the order of the logical buttons on the
+ device, starting with button 1. The default mapping is "1 2 3 ... 32". A mapping of 0 deac‐
+ tivates the button. Multiple buttons can have the same mapping. Invalid mapping strings are
+ discarded and the default mapping is used for all buttons. Buttons not specified in the
+ user's mapping use the default mapping. See section BUTTON MAPPING for more details.
+ '';
+ };
+
+ calibrationMatrix = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ description =
+ ''
+ A string of 9 space-separated floating point numbers. Sets the calibration matrix to the
+ 3x3 matrix where the first row is (abc), the second row is (def) and the third row is (ghi).
+ '';
+ };
+
+ clickMethod = mkOption {
+ type = types.nullOr (types.enum [ "none" "buttonareas" "clickfinger" ]);
+ default = null;
+ description =
+ ''
+ Enables a click method. Permitted values are <literal>none</literal>,
+ <literal>buttonareas</literal>, <literal>clickfinger</literal>.
+ Not all devices support all methods, if an option is unsupported,
+ the default click method for this device is used.
+ '';
+ };
+
+ leftHanded = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enables left-handed button orientation, i.e. swapping left and right buttons.";
+ };
+
+ middleEmulation = mkOption {
+ type = types.bool;
+ default = true;
+ description =
+ ''
+ Enables middle button emulation. When enabled, pressing the left and right buttons
+ simultaneously produces a middle mouse button click.
+ '';
+ };
+
+ naturalScrolling = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Enables or disables natural scrolling behavior.";
+ };
+
+ scrollButton = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ example = 1;
+ description =
+ ''
+ Designates a button as scroll button. If the ScrollMethod is button and the button is logically
+ held down, x/y axis movement is converted into scroll events.
+ '';
+ };
+
+ scrollMethod = mkOption {
+ type = types.enum [ "twofinger" "edge" "button" "none" ];
+ default = "twofinger";
+ example = "edge";
+ description =
+ ''
+ Specify the scrolling method: <literal>twofinger</literal>, <literal>edge</literal>,
+ or <literal>none</literal>
+ '';
+ };
+
+ horizontalScrolling = mkOption {
+ type = types.bool;
+ default = true;
+ description =
+ ''
+ Disables horizontal scrolling. When disabled, this driver will discard any horizontal scroll
+ events from libinput. Note that this does not disable horizontal scrolling, it merely
+ discards the horizontal axis from any scroll events.
+ '';
+ };
+
+ sendEventsMode = mkOption {
+ type = types.enum [ "disabled" "enabled" "disabled-on-external-mouse" ];
+ default = "enabled";
+ example = "disabled";
+ description =
+ ''
+ Sets the send events mode to <literal>disabled</literal>, <literal>enabled</literal>,
+ or <literal>disabled-on-external-mouse</literal>
+ '';
+ };
+
+ tapping = mkOption {
+ type = types.bool;
+ default = true;
+ description =
+ ''
+ Enables or disables tap-to-click behavior.
+ '';
+ };
+
+ tappingDragLock = mkOption {
+ type = types.bool;
+ default = true;
+ description =
+ ''
+ Enables or disables drag lock during tapping behavior. When enabled, a finger up during tap-
+ and-drag will not immediately release the button. If the finger is set down again within the
+ timeout, the draging process continues.
+ '';
+ };
+
+ disableWhileTyping = mkOption {
+ type = types.bool;
+ default = false;
+ description =
+ ''
+ Disable input method while typing.
+ '';
+ };
+
+ additionalOptions = mkOption {
+ type = types.lines;
+ default = "";
+ example =
+ ''
+ Option "DragLockButtons" "L1 B1 L2 B2"
+ '';
+ description = "Additional options for libinput touchpad driver.";
+ };
+
+ };
+
+ };
+
+
+ config = mkIf cfg.enable {
+
+ services.xserver.modules = [ pkgs.xorg.xf86inputlibinput ];
+
+ environment.systemPackages = [ pkgs.xorg.xf86inputlibinput ];
+
+ environment.etc = [
+ (let cfgPath = "X11/xorg.conf.d/40-libinput.conf"; in {
+ source = pkgs.xorg.xf86inputlibinput.out + "/share/" + cfgPath;
+ target = cfgPath;
+ })
+ ];
+
+ services.udev.packages = [ pkgs.libinput.out ];
+
+ services.xserver.config =
+ ''
+ # Automatically enable the libinput driver for all touchpads.
+ Section "InputClass"
+ Identifier "libinputConfiguration"
+ MatchIsTouchpad "on"
+ ${optionalString (cfg.dev != null) ''MatchDevicePath "${cfg.dev}"''}
+ Driver "libinput"
+ Option "AccelProfile" "${cfg.accelProfile}"
+ ${optionalString (cfg.accelSpeed != null) ''Option "AccelSpeed" "${cfg.accelSpeed}"''}
+ ${optionalString (cfg.buttonMapping != null) ''Option "ButtonMapping" "${cfg.buttonMapping}"''}
+ ${optionalString (cfg.calibrationMatrix != null) ''Option "CalibrationMatrix" "${cfg.calibrationMatrix}"''}
+ ${optionalString (cfg.clickMethod != null) ''Option "ClickMethod" "${cfg.clickMethod}"''}
+ Option "LeftHanded" "${xorgBool cfg.leftHanded}"
+ Option "MiddleEmulation" "${xorgBool cfg.middleEmulation}"
+ Option "NaturalScrolling" "${xorgBool cfg.naturalScrolling}"
+ ${optionalString (cfg.scrollButton != null) ''Option "ScrollButton" "${toString cfg.scrollButton}"''}
+ Option "ScrollMethod" "${cfg.scrollMethod}"
+ Option "HorizontalScrolling" "${xorgBool cfg.horizontalScrolling}"
+ Option "SendEventsMode" "${cfg.sendEventsMode}"
+ Option "Tapping" "${xorgBool cfg.tapping}"
+ Option "TappingDragLock" "${xorgBool cfg.tappingDragLock}"
+ Option "DisableWhileTyping" "${xorgBool cfg.disableWhileTyping}"
+ ${cfg.additionalOptions}
+ EndSection
+ '';
+
+ assertions = [
+ # already present in synaptics.nix
+ /* {
+ assertion = !config.services.xserver.synaptics.enable;
+ message = "Synaptics and libinput are incompatible, you cannot enable both (in services.xserver).";
+ } */
+ ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/hardware/multitouch.nix b/nixpkgs/nixos/modules/services/x11/hardware/multitouch.nix
new file mode 100644
index 00000000000..c03bb3b494f
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/hardware/multitouch.nix
@@ -0,0 +1,94 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.xserver.multitouch;
+ disabledTapConfig = ''
+ Option "MaxTapTime" "0"
+ Option "MaxTapMove" "0"
+ Option "TapButton1" "0"
+ Option "TapButton2" "0"
+ Option "TapButton3" "0"
+ '';
+in {
+
+ options = {
+
+ services.xserver.multitouch = {
+
+ enable = mkOption {
+ default = false;
+ description = "Whether to enable multitouch touchpad support.";
+ };
+
+ invertScroll = mkOption {
+ default = false;
+ type = types.bool;
+ description = "Whether to invert scrolling direction à la OSX Lion";
+ };
+
+ ignorePalm = mkOption {
+ default = false;
+ type = types.bool;
+ description = "Whether to ignore touches detected as being the palm (i.e when typing)";
+ };
+
+ tapButtons = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Whether to enable tap buttons.";
+ };
+
+ buttonsMap = mkOption {
+ type = types.listOf types.int;
+ default = [3 2 0];
+ example = [1 3 2];
+ description = "Remap touchpad buttons.";
+ apply = map toString;
+ };
+
+ additionalOptions = mkOption {
+ type = types.str;
+ default = "";
+ example = ''
+ Option "ScaleDistance" "50"
+ Option "RotateDistance" "60"
+ '';
+ description = ''
+ Additional options for mtrack touchpad driver.
+ '';
+ };
+
+ };
+
+ };
+
+ 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" "${boolToString cfg.ignorePalm}"
+ Option "ClickFinger1" "${builtins.elemAt cfg.buttonsMap 0}"
+ Option "ClickFinger2" "${builtins.elemAt cfg.buttonsMap 1}"
+ Option "ClickFinger3" "${builtins.elemAt cfg.buttonsMap 2}"
+ ${optionalString (!cfg.tapButtons) disabledTapConfig}
+ ${optionalString cfg.invertScroll ''
+ Option "ScrollUpButton" "5"
+ Option "ScrollDownButton" "4"
+ Option "ScrollLeftButton" "7"
+ Option "ScrollRightButton" "6"
+ ''}
+ ${cfg.additionalOptions}
+ EndSection
+ '';
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/hardware/synaptics.nix b/nixpkgs/nixos/modules/services/x11/hardware/synaptics.nix
new file mode 100644
index 00000000000..22af869f1f8
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/hardware/synaptics.nix
@@ -0,0 +1,213 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.xserver.synaptics;
+ tapConfig = if cfg.tapButtons then enabledTapConfig else disabledTapConfig;
+ enabledTapConfig = ''
+ Option "MaxTapTime" "180"
+ Option "MaxTapMove" "220"
+ Option "TapButton1" "${builtins.elemAt cfg.fingersMap 0}"
+ Option "TapButton2" "${builtins.elemAt cfg.fingersMap 1}"
+ Option "TapButton3" "${builtins.elemAt cfg.fingersMap 2}"
+ '';
+ disabledTapConfig = ''
+ Option "MaxTapTime" "0"
+ Option "MaxTapMove" "0"
+ Option "TapButton1" "0"
+ Option "TapButton2" "0"
+ Option "TapButton3" "0"
+ '';
+ pkg = pkgs.xorg.xf86inputsynaptics;
+ etcFile = "X11/xorg.conf.d/70-synaptics.conf";
+in {
+
+ options = {
+
+ services.xserver.synaptics = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to enable touchpad support. Deprecated: Consider services.xserver.libinput.enable.";
+ };
+
+ dev = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "/dev/input/event0";
+ description =
+ ''
+ Path for touchpad device. Set to null to apply to any
+ auto-detected touchpad.
+ '';
+ };
+
+ accelFactor = mkOption {
+ type = types.nullOr types.str;
+ default = "0.001";
+ description = "Cursor acceleration (how fast speed increases from minSpeed to maxSpeed).";
+ };
+
+ minSpeed = mkOption {
+ type = types.nullOr types.str;
+ default = "0.6";
+ description = "Cursor speed factor for precision finger motion.";
+ };
+
+ maxSpeed = mkOption {
+ type = types.nullOr types.str;
+ default = "1.0";
+ description = "Cursor speed factor for highest-speed finger motion.";
+ };
+
+ scrollDelta = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ example = 75;
+ description = "Move distance of the finger for a scroll event.";
+ };
+
+ twoFingerScroll = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to enable two-finger drag-scrolling. Overridden by horizTwoFingerScroll and vertTwoFingerScroll.";
+ };
+
+ horizTwoFingerScroll = mkOption {
+ type = types.bool;
+ default = cfg.twoFingerScroll;
+ description = "Whether to enable horizontal two-finger drag-scrolling.";
+ };
+
+ vertTwoFingerScroll = mkOption {
+ type = types.bool;
+ default = cfg.twoFingerScroll;
+ description = "Whether to enable vertical two-finger drag-scrolling.";
+ };
+
+ horizEdgeScroll = mkOption {
+ type = types.bool;
+ default = ! cfg.horizTwoFingerScroll;
+ description = "Whether to enable horizontal edge drag-scrolling.";
+ };
+
+ vertEdgeScroll = mkOption {
+ type = types.bool;
+ default = ! cfg.vertTwoFingerScroll;
+ description = "Whether to enable vertical edge drag-scrolling.";
+ };
+
+ tapButtons = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Whether to enable tap buttons.";
+ };
+
+ buttonsMap = mkOption {
+ type = types.listOf types.int;
+ default = [1 2 3];
+ example = [1 3 2];
+ description = "Remap touchpad buttons.";
+ apply = map toString;
+ };
+
+ fingersMap = mkOption {
+ type = types.listOf types.int;
+ default = [1 2 3];
+ example = [1 3 2];
+ description = "Remap several-fingers taps.";
+ apply = map toString;
+ };
+
+ palmDetect = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to enable palm detection (hardware support required)";
+ };
+
+ palmMinWidth = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ example = 5;
+ description = "Minimum finger width at which touch is considered a palm";
+ };
+
+ palmMinZ = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ example = 20;
+ description = "Minimum finger pressure at which touch is considered a palm";
+ };
+
+ horizontalScroll = mkOption {
+ type = types.bool;
+ default = true;
+ description = "Whether to enable horizontal scrolling (on touchpad)";
+ };
+
+ additionalOptions = mkOption {
+ type = types.str;
+ default = "";
+ example = ''
+ Option "RTCornerButton" "2"
+ Option "RBCornerButton" "3"
+ '';
+ description = ''
+ Additional options for synaptics touchpad driver.
+ '';
+ };
+
+ };
+
+ };
+
+
+ config = mkIf cfg.enable {
+
+ services.xserver.modules = [ pkg.out ];
+
+ environment.etc.${etcFile}.source =
+ "${pkg.out}/share/X11/xorg.conf.d/70-synaptics.conf";
+
+ environment.systemPackages = [ pkg ];
+
+ 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"
+ ${optionalString (cfg.minSpeed != null) ''Option "MinSpeed" "${cfg.minSpeed}"''}
+ ${optionalString (cfg.maxSpeed != null) ''Option "MaxSpeed" "${cfg.maxSpeed}"''}
+ ${optionalString (cfg.accelFactor != null) ''Option "AccelFactor" "${cfg.accelFactor}"''}
+ ${optionalString cfg.tapButtons tapConfig}
+ Option "ClickFinger1" "${builtins.elemAt cfg.buttonsMap 0}"
+ Option "ClickFinger2" "${builtins.elemAt cfg.buttonsMap 1}"
+ Option "ClickFinger3" "${builtins.elemAt cfg.buttonsMap 2}"
+ Option "VertTwoFingerScroll" "${if cfg.vertTwoFingerScroll then "1" else "0"}"
+ Option "HorizTwoFingerScroll" "${if cfg.horizTwoFingerScroll then "1" else "0"}"
+ Option "VertEdgeScroll" "${if cfg.vertEdgeScroll then "1" else "0"}"
+ Option "HorizEdgeScroll" "${if cfg.horizEdgeScroll then "1" else "0"}"
+ ${optionalString cfg.palmDetect ''Option "PalmDetect" "1"''}
+ ${optionalString (cfg.palmMinWidth != null) ''Option "PalmMinWidth" "${toString cfg.palmMinWidth}"''}
+ ${optionalString (cfg.palmMinZ != null) ''Option "PalmMinZ" "${toString cfg.palmMinZ}"''}
+ ${optionalString (cfg.scrollDelta != null) ''Option "VertScrollDelta" "${toString cfg.scrollDelta}"''}
+ ${if !cfg.horizontalScroll then ''Option "HorizScrollDelta" "0"''
+ else (optionalString (cfg.scrollDelta != null) ''Option "HorizScrollDelta" "${toString cfg.scrollDelta}"'')}
+ ${cfg.additionalOptions}
+ EndSection
+ '';
+
+ assertions = [
+ {
+ assertion = !config.services.xserver.libinput.enable;
+ message = "Synaptics and libinput are incompatible, you cannot enable both (in services.xserver).";
+ }
+ ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/hardware/wacom.nix b/nixpkgs/nixos/modules/services/x11/hardware/wacom.nix
new file mode 100644
index 00000000000..a27889c36a7
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/hardware/wacom.nix
@@ -0,0 +1,47 @@
+{ config, lib, pkgs, ... }:
+
+with 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/70-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/70-wacom.conf".source = "${pkgs.xf86_input_wacom}/share/X11/xorg.conf.d/70-wacom.conf";
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/redshift.nix b/nixpkgs/nixos/modules/services/x11/redshift.nix
new file mode 100644
index 00000000000..21b0b33553a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/redshift.nix
@@ -0,0 +1,129 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.redshift;
+ lcfg = config.location;
+
+in {
+
+ imports = [
+ (mkChangedOptionModule [ "services" "redshift" "latitude" ] [ "location" "latitude" ]
+ (config:
+ let value = getAttrFromPath [ "services" "redshift" "latitude" ] config;
+ in if value == null then
+ throw "services.redshift.latitude is set to null, you can remove this"
+ else builtins.fromJSON value))
+ (mkChangedOptionModule [ "services" "redshift" "longitude" ] [ "location" "longitude" ]
+ (config:
+ let value = getAttrFromPath [ "services" "redshift" "longitude" ] config;
+ in if value == null then
+ throw "services.redshift.longitude is set to null, you can remove this"
+ else builtins.fromJSON value))
+ (mkRenamedOptionModule [ "services" "redshift" "provider" ] [ "location" "provider" ])
+ ];
+
+ options.services.redshift = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Enable Redshift to change your screen's colour temperature depending on
+ the time of day.
+ '';
+ };
+
+ temperature = {
+ day = mkOption {
+ type = types.int;
+ default = 5500;
+ description = ''
+ Colour temperature to use during the day, between
+ <literal>1000</literal> and <literal>25000</literal> K.
+ '';
+ };
+ night = mkOption {
+ type = types.int;
+ default = 3700;
+ description = ''
+ Colour temperature to use at night, between
+ <literal>1000</literal> and <literal>25000</literal> K.
+ '';
+ };
+ };
+
+ brightness = {
+ day = mkOption {
+ type = types.str;
+ default = "1";
+ description = ''
+ Screen brightness to apply during the day,
+ between <literal>0.1</literal> and <literal>1.0</literal>.
+ '';
+ };
+ night = mkOption {
+ type = types.str;
+ default = "1";
+ description = ''
+ Screen brightness to apply during the night,
+ between <literal>0.1</literal> and <literal>1.0</literal>.
+ '';
+ };
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.redshift;
+ defaultText = "pkgs.redshift";
+ description = ''
+ redshift derivation to use.
+ '';
+ };
+
+ extraOptions = mkOption {
+ type = types.listOf types.str;
+ default = [];
+ example = [ "-v" "-m randr" ];
+ description = ''
+ Additional command-line arguments to pass to
+ <command>redshift</command>.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ # needed so that .desktop files are installed, which geoclue cares about
+ environment.systemPackages = [ cfg.package ];
+
+ services.geoclue2.appConfig.redshift = {
+ isAllowed = true;
+ isSystem = true;
+ };
+
+ systemd.user.services.redshift =
+ let
+ providerString = if lcfg.provider == "manual"
+ then "${toString lcfg.latitude}:${toString lcfg.longitude}"
+ else lcfg.provider;
+ in
+ {
+ description = "Redshift colour temperature adjuster";
+ wantedBy = [ "graphical-session.target" ];
+ partOf = [ "graphical-session.target" ];
+ serviceConfig = {
+ ExecStart = ''
+ ${cfg.package}/bin/redshift \
+ -l ${providerString} \
+ -t ${toString cfg.temperature.day}:${toString cfg.temperature.night} \
+ -b ${toString cfg.brightness.day}:${toString cfg.brightness.night} \
+ ${lib.strings.concatStringsSep " " cfg.extraOptions}
+ '';
+ RestartSec = 3;
+ Restart = "always";
+ };
+ };
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/terminal-server.nix b/nixpkgs/nixos/modules/services/x11/terminal-server.nix
new file mode 100644
index 00000000000..503c14c9b62
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/terminal-server.nix
@@ -0,0 +1,56 @@
+# 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.
+
+{ lib, pkgs, ... }:
+
+with lib;
+
+{
+
+ config = {
+
+ services.xserver.enable = true;
+ services.xserver.videoDrivers = [];
+
+ # Enable GDM. Any display manager will do as long as it supports XDMCP.
+ services.xserver.displayManager.gdm.enable = true;
+
+ systemd.sockets.terminal-server =
+ { description = "Terminal Server Socket";
+ wantedBy = [ "sockets.target" ];
+ before = [ "multi-user.target" ];
+ socketConfig.Accept = true;
+ socketConfig.ListenStream = 5900;
+ };
+
+ systemd.services."terminal-server@" =
+ { description = "Terminal Server";
+
+ path =
+ [ pkgs.xorg.xorgserver.out pkgs.gawk pkgs.which pkgs.openssl pkgs.xorg.xauth
+ pkgs.nettools pkgs.shadow pkgs.procps pkgs.utillinux pkgs.bash
+ ];
+
+ environment.FD_GEOM = "1024x786x24";
+ environment.FD_XDMCP_IF = "127.0.0.1";
+ #environment.FIND_DISPLAY_OUTPUT = "/tmp/foo"; # to debug the "find display" script
+
+ serviceConfig =
+ { StandardInput = "socket";
+ StandardOutput = "socket";
+ StandardError = "journal";
+ ExecStart = "@${pkgs.x11vnc}/bin/x11vnc x11vnc -inetd -display WAIT:1024x786:cmd=FINDCREATEDISPLAY-Xvfb.xdmcp -unixpw -ssl SAVE";
+ # Don't kill the X server when the user quits the VNC
+ # connection. FIXME: the X server should run in a
+ # separate systemd session.
+ KillMode = "process";
+ };
+ };
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix b/nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix
new file mode 100644
index 00000000000..71262431b68
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/unclutter-xfixes.nix
@@ -0,0 +1,58 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.unclutter-xfixes;
+
+in {
+ options.services.unclutter-xfixes = {
+
+ enable = mkOption {
+ description = "Enable unclutter-xfixes to hide your mouse cursor when inactive.";
+ type = types.bool;
+ default = false;
+ };
+
+ package = mkOption {
+ description = "unclutter-xfixes derivation to use.";
+ type = types.package;
+ default = pkgs.unclutter-xfixes;
+ defaultText = "pkgs.unclutter-xfixes";
+ };
+
+ timeout = mkOption {
+ description = "Number of seconds before the cursor is marked inactive.";
+ type = types.int;
+ default = 1;
+ };
+
+ threshold = mkOption {
+ description = "Minimum number of pixels considered cursor movement.";
+ type = types.int;
+ default = 1;
+ };
+
+ extraOptions = mkOption {
+ description = "More arguments to pass to the unclutter-xfixes command.";
+ type = types.listOf types.str;
+ default = [];
+ example = [ "exclude-root" "ignore-scrolling" "fork" ];
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.user.services.unclutter-xfixes = {
+ description = "unclutter-xfixes";
+ wantedBy = [ "graphical-session.target" ];
+ partOf = [ "graphical-session.target" ];
+ serviceConfig.ExecStart = ''
+ ${cfg.package}/bin/unclutter \
+ --timeout ${toString cfg.timeout} \
+ --jitter ${toString (cfg.threshold - 1)} \
+ ${concatMapStrings (x: " --"+x) cfg.extraOptions} \
+ '';
+ serviceConfig.RestartSec = 3;
+ serviceConfig.Restart = "always";
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/unclutter.nix b/nixpkgs/nixos/modules/services/x11/unclutter.nix
new file mode 100644
index 00000000000..5f16a680050
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/unclutter.nix
@@ -0,0 +1,74 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.unclutter;
+
+in {
+ options.services.unclutter = {
+
+ enable = mkOption {
+ description = "Enable unclutter to hide your mouse cursor when inactive";
+ type = types.bool;
+ default = false;
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.unclutter;
+ defaultText = "pkgs.unclutter";
+ description = "unclutter derivation to use.";
+ };
+
+ keystroke = mkOption {
+ description = "Wait for a keystroke before hiding the cursor";
+ type = types.bool;
+ default = false;
+ };
+
+ timeout = mkOption {
+ description = "Number of seconds before the cursor is marked inactive";
+ type = types.int;
+ default = 1;
+ };
+
+ threeshold = mkOption {
+ description = "Minimum number of pixels considered cursor movement";
+ type = types.int;
+ default = 1;
+ };
+
+ excluded = mkOption {
+ description = "Names of windows where unclutter should not apply";
+ type = types.listOf types.str;
+ default = [];
+ example = [ "" ];
+ };
+
+ extraOptions = mkOption {
+ description = "More arguments to pass to the unclutter command";
+ type = types.listOf types.str;
+ default = [];
+ example = [ "noevent" "grab" ];
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.user.services.unclutter = {
+ description = "unclutter";
+ wantedBy = [ "graphical-session.target" ];
+ partOf = [ "graphical-session.target" ];
+ serviceConfig.ExecStart = ''
+ ${cfg.package}/bin/unclutter \
+ -idle ${toString cfg.timeout} \
+ -jitter ${toString (cfg.threeshold - 1)} \
+ ${optionalString cfg.keystroke "-keystroke"} \
+ ${concatMapStrings (x: " -"+x) cfg.extraOptions} \
+ -not ${concatStringsSep " " cfg.excluded} \
+ '';
+ serviceConfig.PassEnvironment = "DISPLAY";
+ serviceConfig.RestartSec = 3;
+ serviceConfig.Restart = "always";
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/urxvtd.nix b/nixpkgs/nixos/modules/services/x11/urxvtd.nix
new file mode 100644
index 00000000000..d916fa5bb39
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/urxvtd.nix
@@ -0,0 +1,48 @@
+{ config, lib, pkgs, ... }:
+
+# maintainer: siddharthist
+
+with lib;
+
+let
+ cfg = config.services.urxvtd;
+in {
+ options.services.urxvtd = {
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Enable urxvtd, the urxvt terminal daemon. To use urxvtd, run
+ "urxvtc".
+ '';
+ };
+
+ package = mkOption {
+ default = pkgs.rxvt_unicode-with-plugins;
+ defaultText = "pkgs.rxvt_unicode-with-plugins";
+ description = ''
+ Package to install. Usually pkgs.rxvt_unicode-with-plugins or pkgs.rxvt_unicode
+ '';
+ type = types.package;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.user.services.urxvtd = {
+ description = "urxvt terminal daemon";
+ wantedBy = [ "graphical-session.target" ];
+ partOf = [ "graphical-session.target" ];
+ path = [ pkgs.xsel ];
+ serviceConfig = {
+ ExecStart = "${cfg.package}/bin/urxvtd -o";
+ Environment = "RXVT_SOCKET=%t/urxvtd-socket";
+ Restart = "on-failure";
+ RestartSec = "5s";
+ };
+ };
+
+ environment.systemPackages = [ cfg.package ];
+ environment.variables.RXVT_SOCKET = "/run/user/$(id -u)/urxvtd-socket";
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/2bwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/2bwm.nix
new file mode 100644
index 00000000000..fdbdf35b0f5
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/2bwm.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.windowManager."2bwm";
+
+in
+
+{
+
+ ###### interface
+
+ options = {
+ services.xserver.windowManager."2bwm".enable = mkEnableOption "2bwm";
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.xserver.windowManager.session = singleton
+ { name = "2bwm";
+ start =
+ ''
+ ${pkgs._2bwm}/bin/2bwm &
+ waitPID=$!
+ '';
+ };
+
+ environment.systemPackages = [ pkgs._2bwm ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/afterstep.nix b/nixpkgs/nixos/modules/services/x11/window-managers/afterstep.nix
new file mode 100644
index 00000000000..ba88a64c702
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/afterstep.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.afterstep;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.afterstep.enable = mkEnableOption "afterstep";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "afterstep";
+ start = ''
+ ${pkgs.afterstep}/bin/afterstep &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.afterstep ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix b/nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix
new file mode 100644
index 00000000000..089e9f769f0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/awesome.nix
@@ -0,0 +1,66 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.windowManager.awesome;
+ awesome = cfg.package;
+ getLuaPath = lib : dir : "${lib}/${dir}/lua/${pkgs.luaPackages.lua.luaversion}";
+ makeSearchPath = lib.concatMapStrings (path:
+ " --search " + (getLuaPath path "share") +
+ " --search " + (getLuaPath path "lib")
+ );
+in
+
+{
+
+ ###### interface
+
+ options = {
+
+ services.xserver.windowManager.awesome = {
+
+ enable = mkEnableOption "Awesome window manager";
+
+ luaModules = mkOption {
+ default = [];
+ type = types.listOf types.package;
+ description = "List of lua packages available for being used in the Awesome configuration.";
+ example = literalExample "[ luaPackages.oocairo ]";
+ };
+
+ package = mkOption {
+ default = null;
+ type = types.nullOr types.package;
+ description = "Package to use for running the Awesome WM.";
+ apply = pkg: if pkg == null then pkgs.awesome else pkg;
+ };
+
+ noArgb = mkOption {
+ default = false;
+ type = types.bool;
+ description = "Disable client transparency support, which can be greatly detrimental to performance in some setups";
+ };
+ };
+
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.xserver.windowManager.session = singleton
+ { name = "awesome";
+ start =
+ ''
+ ${awesome}/bin/awesome ${lib.optionalString cfg.noArgb "--no-argb"} ${makeSearchPath cfg.luaModules} &
+ waitPID=$!
+ '';
+ };
+
+ environment.systemPackages = [ awesome ];
+
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix
new file mode 100644
index 00000000000..23cd4f6529a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/bspwm.nix
@@ -0,0 +1,77 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.bspwm;
+in
+
+{
+ options = {
+ services.xserver.windowManager.bspwm = {
+ enable = mkEnableOption "bspwm";
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.bspwm;
+ defaultText = "pkgs.bspwm";
+ example = "pkgs.bspwm-unstable";
+ description = ''
+ bspwm package to use.
+ '';
+ };
+ configFile = mkOption {
+ type = with types; nullOr path;
+ example = "${pkgs.bspwm}/share/doc/bspwm/examples/bspwmrc";
+ default = null;
+ description = ''
+ Path to the bspwm configuration file.
+ If null, $HOME/.config/bspwm/bspwmrc will be used.
+ '';
+ };
+
+ sxhkd = {
+ package = mkOption {
+ type = types.package;
+ default = pkgs.sxhkd;
+ defaultText = "pkgs.sxhkd";
+ example = "pkgs.sxhkd-unstable";
+ description = ''
+ sxhkd package to use.
+ '';
+ };
+ configFile = mkOption {
+ type = with types; nullOr path;
+ example = "${pkgs.bspwm}/share/doc/bspwm/examples/sxhkdrc";
+ default = null;
+ description = ''
+ Path to the sxhkd configuration file.
+ If null, $HOME/.config/sxhkd/sxhkdrc will be used.
+ '';
+ };
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "bspwm";
+ start = ''
+ export _JAVA_AWT_WM_NONREPARENTING=1
+ SXHKD_SHELL=/bin/sh ${cfg.sxhkd.package}/bin/sxhkd ${optionalString (cfg.sxhkd.configFile != null) "-c \"${cfg.sxhkd.configFile}\""} &
+ ${cfg.package}/bin/bspwm ${optionalString (cfg.configFile != null) "-c \"${cfg.configFile}\""} &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ cfg.package ];
+ };
+
+ imports = [
+ (mkRemovedOptionModule [ "services" "xserver" "windowManager" "bspwm-unstable" "enable" ]
+ "Use services.xserver.windowManager.bspwm.enable and set services.xserver.windowManager.bspwm.package to pkgs.bspwm-unstable to use the unstable version of bspwm.")
+ (mkRemovedOptionModule [ "services" "xserver" "windowManager" "bspwm" "startThroughSession" ]
+ "bspwm package does not provide bspwm-session anymore.")
+ (mkRemovedOptionModule [ "services" "xserver" "windowManager" "bspwm" "sessionScript" ]
+ "bspwm package does not provide bspwm-session anymore.")
+ ];
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix
new file mode 100644
index 00000000000..176c1f46127
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/clfswm.nix
@@ -0,0 +1,24 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.clfswm;
+in
+
+{
+ options = {
+ services.xserver.windowManager.clfswm.enable = mkEnableOption "clfswm";
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "clfswm";
+ start = ''
+ ${pkgs.clfswm}/bin/clfswm &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.clfswm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/default.nix b/nixpkgs/nixos/modules/services/x11/window-managers/default.nix
new file mode 100644
index 00000000000..2a1f22fa9a4
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/default.nix
@@ -0,0 +1,79 @@
+{ config, lib, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager;
+in
+
+{
+ imports = [
+ ./2bwm.nix
+ ./afterstep.nix
+ ./bspwm.nix
+ ./dwm.nix
+ ./evilwm.nix
+ ./exwm.nix
+ ./fluxbox.nix
+ ./fvwm.nix
+ ./herbstluftwm.nix
+ ./i3.nix
+ ./jwm.nix
+ ./leftwm.nix
+ ./metacity.nix
+ ./mwm.nix
+ ./openbox.nix
+ ./pekwm.nix
+ ./notion.nix
+ ./ratpoison.nix
+ ./sawfish.nix
+ ./stumpwm.nix
+ ./spectrwm.nix
+ ./twm.nix
+ ./windowmaker.nix
+ ./wmii.nix
+ ./xmonad.nix
+ ./qtile.nix
+ ./none.nix ];
+
+ options = {
+
+ services.xserver.windowManager = {
+
+ session = mkOption {
+ internal = true;
+ 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 {
+ type = types.str;
+ default = "none";
+ example = "wmii";
+ description = "Default window manager loaded if none have been chosen.";
+ 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/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix
new file mode 100644
index 00000000000..7777913ce1e
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/dwm.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.windowManager.dwm;
+
+in
+
+{
+
+ ###### interface
+
+ options = {
+ services.xserver.windowManager.dwm.enable = mkEnableOption "dwm";
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.xserver.windowManager.session = singleton
+ { name = "dwm";
+ start =
+ ''
+ dwm &
+ waitPID=$!
+ '';
+ };
+
+ environment.systemPackages = [ pkgs.dwm ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/evilwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/evilwm.nix
new file mode 100644
index 00000000000..6e19e3572c7
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/evilwm.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.evilwm;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.evilwm.enable = mkEnableOption "evilwm";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "evilwm";
+ start = ''
+ ${pkgs.evilwm}/bin/evilwm &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.evilwm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix
new file mode 100644
index 00000000000..dc1d957c170
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/exwm.nix
@@ -0,0 +1,54 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.exwm;
+ loadScript = pkgs.writeText "emacs-exwm-load" ''
+ (require 'exwm)
+ ${optionalString cfg.enableDefaultConfig ''
+ (require 'exwm-config)
+ (exwm-config-default)
+ ''}
+ '';
+ packages = epkgs: cfg.extraPackages epkgs ++ [ epkgs.exwm ];
+ exwm-emacs = pkgs.emacsWithPackages packages;
+in
+
+{
+ options = {
+ services.xserver.windowManager.exwm = {
+ enable = mkEnableOption "exwm";
+ enableDefaultConfig = mkOption {
+ default = true;
+ type = lib.types.bool;
+ description = "Enable an uncustomised exwm configuration.";
+ };
+ extraPackages = mkOption {
+ default = self: [];
+ example = literalExample ''
+ epkgs: [
+ epkgs.emms
+ epkgs.magit
+ epkgs.proofgeneral
+ ]
+ '';
+ description = ''
+ Extra packages available to Emacs. The value must be a
+ function which receives the attrset defined in
+ <varname>emacsPackages</varname> as the sole argument.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "exwm";
+ start = ''
+ ${exwm-emacs}/bin/emacs -l ${loadScript}
+ '';
+ };
+ environment.systemPackages = [ exwm-emacs ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/fluxbox.nix b/nixpkgs/nixos/modules/services/x11/window-managers/fluxbox.nix
new file mode 100644
index 00000000000..b409335702a
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/fluxbox.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.fluxbox;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.fluxbox.enable = mkEnableOption "fluxbox";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "fluxbox";
+ start = ''
+ ${pkgs.fluxbox}/bin/startfluxbox &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.fluxbox ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/fvwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/fvwm.nix
new file mode 100644
index 00000000000..9a51b9cd660
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/fvwm.nix
@@ -0,0 +1,41 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.fvwm;
+ fvwm = pkgs.fvwm.override { gestures = cfg.gestures; };
+in
+
+{
+
+ ###### interface
+
+ options = {
+ services.xserver.windowManager.fvwm = {
+ enable = mkEnableOption "Fvwm window manager";
+
+ gestures = mkOption {
+ default = false;
+ type = types.bool;
+ description = "Whether or not to enable libstroke for gesture support";
+ };
+ };
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton
+ { name = "fvwm";
+ start =
+ ''
+ ${fvwm}/bin/fvwm &
+ waitPID=$!
+ '';
+ };
+
+ environment.systemPackages = [ fvwm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix
new file mode 100644
index 00000000000..e3ea61cb9a6
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/herbstluftwm.nix
@@ -0,0 +1,38 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.herbstluftwm;
+in
+
+{
+ options = {
+ services.xserver.windowManager.herbstluftwm = {
+ enable = mkEnableOption "herbstluftwm";
+
+ configFile = mkOption {
+ default = null;
+ type = with types; nullOr path;
+ description = ''
+ Path to the herbstluftwm configuration file. If left at the
+ default value, $XDG_CONFIG_HOME/herbstluftwm/autostart will
+ be used.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "herbstluftwm";
+ start =
+ let configFileClause = optionalString
+ (cfg.configFile != null)
+ ''-c "${cfg.configFile}"''
+ ;
+ in "${pkgs.herbstluftwm}/bin/herbstluftwm ${configFileClause}";
+ };
+ environment.systemPackages = [ pkgs.herbstluftwm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/i3.nix b/nixpkgs/nixos/modules/services/x11/window-managers/i3.nix
new file mode 100644
index 00000000000..0ef55d5f2c0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/i3.nix
@@ -0,0 +1,78 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.i3;
+in
+
+{
+ options.services.xserver.windowManager.i3 = {
+ enable = mkEnableOption "i3 window manager";
+
+ configFile = mkOption {
+ default = null;
+ type = with types; nullOr path;
+ description = ''
+ Path to the i3 configuration file.
+ If left at the default value, $HOME/.i3/config will be used.
+ '';
+ };
+
+ extraSessionCommands = mkOption {
+ default = "";
+ type = types.lines;
+ description = ''
+ Shell commands executed just before i3 is started.
+ '';
+ };
+
+ package = mkOption {
+ type = types.package;
+ default = pkgs.i3;
+ defaultText = "pkgs.i3";
+ example = "pkgs.i3-gaps";
+ description = ''
+ i3 package to use.
+ '';
+ };
+
+ extraPackages = mkOption {
+ type = with types; listOf package;
+ default = with pkgs; [ dmenu i3status i3lock ];
+ example = literalExample ''
+ with pkgs; [
+ dmenu
+ i3status
+ i3lock
+ ]
+ '';
+ description = ''
+ Extra packages to be installed system wide.
+ '';
+ };
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = [{
+ name = "i3";
+ start = ''
+ ${cfg.extraSessionCommands}
+
+ ${cfg.package}/bin/i3 ${optionalString (cfg.configFile != null)
+ "-c /etc/i3/config"
+ } &
+ waitPID=$!
+ '';
+ }];
+ environment.systemPackages = [ cfg.package ] ++ cfg.extraPackages;
+ environment.etc."i3/config" = mkIf (cfg.configFile != null) {
+ source = cfg.configFile;
+ };
+ };
+
+ imports = [
+ (mkRemovedOptionModule [ "services" "xserver" "windowManager" "i3-gaps" "enable" ]
+ "Use services.xserver.windowManager.i3.enable and set services.xserver.windowManager.i3.package to pkgs.i3-gaps to use i3-gaps.")
+ ];
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix
new file mode 100644
index 00000000000..f4ae9222df6
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/icewm.nix
@@ -0,0 +1,27 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.icewm;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.icewm.enable = mkEnableOption "icewm";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton
+ { name = "icewm";
+ start =
+ ''
+ ${pkgs.icewm}/bin/icewm &
+ waitPID=$!
+ '';
+ };
+
+ environment.systemPackages = [ pkgs.icewm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/jwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/jwm.nix
new file mode 100644
index 00000000000..0e8dab2e922
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/jwm.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.jwm;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.jwm.enable = mkEnableOption "jwm";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "jwm";
+ start = ''
+ ${pkgs.jwm}/bin/jwm &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.jwm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/leftwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/leftwm.nix
new file mode 100644
index 00000000000..3ef40df95df
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/leftwm.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.leftwm;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.leftwm.enable = mkEnableOption "leftwm";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "leftwm";
+ start = ''
+ ${pkgs.leftwm}/bin/leftwm &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.leftwm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/metacity.nix b/nixpkgs/nixos/modules/services/x11/window-managers/metacity.nix
new file mode 100644
index 00000000000..5175fd7f3b1
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/metacity.nix
@@ -0,0 +1,30 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.windowManager.metacity;
+ inherit (pkgs) gnome3;
+in
+
+{
+ options = {
+ services.xserver.windowManager.metacity.enable = mkEnableOption "metacity";
+ };
+
+ config = mkIf cfg.enable {
+
+ services.xserver.windowManager.session = singleton
+ { name = "metacity";
+ start = ''
+ ${gnome3.metacity}/bin/metacity &
+ waitPID=$!
+ '';
+ };
+
+ environment.systemPackages = [ gnome3.metacity ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/mwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/mwm.nix
new file mode 100644
index 00000000000..31f7b725f74
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/mwm.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.mwm;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.mwm.enable = mkEnableOption "mwm";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "mwm";
+ start = ''
+ ${pkgs.motif}/bin/mwm &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.motif ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/none.nix b/nixpkgs/nixos/modules/services/x11/window-managers/none.nix
new file mode 100644
index 00000000000..84cf1d77077
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/none.nix
@@ -0,0 +1,12 @@
+{
+ services = {
+ xserver = {
+ windowManager = {
+ session = [{
+ name = "none";
+ start = "";
+ }];
+ };
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/notion.nix b/nixpkgs/nixos/modules/services/x11/window-managers/notion.nix
new file mode 100644
index 00000000000..4ece0d241c9
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/notion.nix
@@ -0,0 +1,26 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.notion;
+in
+
+{
+ options = {
+ services.xserver.windowManager.notion.enable = mkEnableOption "notion";
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager = {
+ session = [{
+ name = "notion";
+ start = ''
+ ${pkgs.notion}/bin/notion &
+ waitPID=$!
+ '';
+ }];
+ };
+ environment.systemPackages = [ pkgs.notion ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/openbox.nix b/nixpkgs/nixos/modules/services/x11/window-managers/openbox.nix
new file mode 100644
index 00000000000..165772d1aa0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/openbox.nix
@@ -0,0 +1,24 @@
+{lib, pkgs, config, ...}:
+
+with lib;
+let
+ cfg = config.services.xserver.windowManager.openbox;
+in
+
+{
+ options = {
+ services.xserver.windowManager.openbox.enable = mkEnableOption "openbox";
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager = {
+ session = [{
+ name = "openbox";
+ start = "
+ ${pkgs.openbox}/bin/openbox-session
+ ";
+ }];
+ };
+ environment.systemPackages = [ pkgs.openbox ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/oroborus.nix b/nixpkgs/nixos/modules/services/x11/window-managers/oroborus.nix
new file mode 100644
index 00000000000..bd7e3396864
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/oroborus.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.oroborus;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.oroborus.enable = mkEnableOption "oroborus";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "oroborus";
+ start = ''
+ ${pkgs.oroborus}/bin/oroborus &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.oroborus ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/pekwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/pekwm.nix
new file mode 100644
index 00000000000..850335ce7dd
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/pekwm.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.pekwm;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.pekwm.enable = mkEnableOption "pekwm";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "pekwm";
+ start = ''
+ ${pkgs.pekwm}/bin/pekwm &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.pekwm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix b/nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix
new file mode 100644
index 00000000000..ad3b65150b0
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/qtile.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.qtile;
+in
+
+{
+ options = {
+ services.xserver.windowManager.qtile.enable = mkEnableOption "qtile";
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = [{
+ name = "qtile";
+ start = ''
+ ${pkgs.qtile}/bin/qtile &
+ waitPID=$!
+ '';
+ }];
+
+ environment.systemPackages = [ pkgs.qtile ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/ratpoison.nix b/nixpkgs/nixos/modules/services/x11/window-managers/ratpoison.nix
new file mode 100644
index 00000000000..0d58481d457
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/ratpoison.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.ratpoison;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.ratpoison.enable = mkEnableOption "ratpoison";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "ratpoison";
+ start = ''
+ ${pkgs.ratpoison}/bin/ratpoison &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.ratpoison ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/sawfish.nix b/nixpkgs/nixos/modules/services/x11/window-managers/sawfish.nix
new file mode 100644
index 00000000000..b988b5e1829
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/sawfish.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.sawfish;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.sawfish.enable = mkEnableOption "sawfish";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "sawfish";
+ start = ''
+ ${pkgs.sawfish}/bin/sawfish &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.sawfish ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/spectrwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/spectrwm.nix
new file mode 100644
index 00000000000..a1dc298d242
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/spectrwm.nix
@@ -0,0 +1,27 @@
+
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.spectrwm;
+in
+
+{
+ options = {
+ services.xserver.windowManager.spectrwm.enable = mkEnableOption "spectrwm";
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager = {
+ session = [{
+ name = "spectrwm";
+ start = ''
+ ${pkgs.spectrwm}/bin/spectrwm &
+ waitPID=$!
+ '';
+ }];
+ };
+ environment.systemPackages = [ pkgs.spectrwm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/stumpwm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/stumpwm.nix
new file mode 100644
index 00000000000..27a17178476
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/stumpwm.nix
@@ -0,0 +1,24 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.stumpwm;
+in
+
+{
+ options = {
+ services.xserver.windowManager.stumpwm.enable = mkEnableOption "stumpwm";
+ };
+
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "stumpwm";
+ start = ''
+ ${pkgs.lispPackages.stumpwm}/bin/stumpwm &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.lispPackages.stumpwm ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/twm.nix b/nixpkgs/nixos/modules/services/x11/window-managers/twm.nix
new file mode 100644
index 00000000000..fc09901aae3
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/twm.nix
@@ -0,0 +1,37 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ cfg = config.services.xserver.windowManager.twm;
+
+in
+
+{
+
+ ###### interface
+
+ options = {
+ services.xserver.windowManager.twm.enable = mkEnableOption "twm";
+ };
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.xserver.windowManager.session = singleton
+ { name = "twm";
+ start =
+ ''
+ ${pkgs.xorg.twm}/bin/twm &
+ waitPID=$!
+ '';
+ };
+
+ environment.systemPackages = [ pkgs.xorg.twm ];
+
+ };
+
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/windowlab.nix b/nixpkgs/nixos/modules/services/x11/window-managers/windowlab.nix
new file mode 100644
index 00000000000..fb891a39fa4
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/windowlab.nix
@@ -0,0 +1,22 @@
+{lib, pkgs, config, ...}:
+
+let
+ cfg = config.services.xserver.windowManager.windowlab;
+in
+
+{
+ options = {
+ services.xserver.windowManager.windowlab.enable =
+ lib.mkEnableOption "windowlab";
+ };
+
+ config = lib.mkIf cfg.enable {
+ services.xserver.windowManager = {
+ session =
+ [{ name = "windowlab";
+ start = "${pkgs.windowlab}/bin/windowlab";
+ }];
+ };
+ environment.systemPackages = [ pkgs.windowlab ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/windowmaker.nix b/nixpkgs/nixos/modules/services/x11/window-managers/windowmaker.nix
new file mode 100644
index 00000000000..b6272375805
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/windowmaker.nix
@@ -0,0 +1,25 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.windowManager.windowmaker;
+in
+{
+ ###### interface
+ options = {
+ services.xserver.windowManager.windowmaker.enable = mkEnableOption "windowmaker";
+ };
+
+ ###### implementation
+ config = mkIf cfg.enable {
+ services.xserver.windowManager.session = singleton {
+ name = "windowmaker";
+ start = ''
+ ${pkgs.windowmaker}/bin/wmaker &
+ waitPID=$!
+ '';
+ };
+ environment.systemPackages = [ pkgs.windowmaker ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/wmii.nix b/nixpkgs/nixos/modules/services/x11/window-managers/wmii.nix
new file mode 100644
index 00000000000..9b50a99bf23
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/wmii.nix
@@ -0,0 +1,39 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+let
+ cfg = config.services.xserver.windowManager.wmii;
+ wmii = pkgs.wmii_hg;
+in
+{
+ options = {
+ services.xserver.windowManager.wmii.enable = mkEnableOption "wmii";
+ };
+
+ 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
+ # (or "mod+a quit", which is bound to do the same thing in wmiirc
+ # by default)
+ #
+ # 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
+ ${wmii}/bin/wmii && break
+ done
+ '';
+ };
+
+ environment.systemPackages = [ wmii ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/window-managers/xmonad.nix b/nixpkgs/nixos/modules/services/x11/window-managers/xmonad.nix
new file mode 100644
index 00000000000..0e131412276
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/window-managers/xmonad.nix
@@ -0,0 +1,97 @@
+{pkgs, lib, config, ...}:
+
+with lib;
+let
+ inherit (lib) mkOption mkIf optionals literalExample;
+ cfg = config.services.xserver.windowManager.xmonad;
+ xmonad = pkgs.xmonad-with-packages.override {
+ ghcWithPackages = cfg.haskellPackages.ghcWithPackages;
+ packages = self: cfg.extraPackages self ++
+ optionals cfg.enableContribAndExtras
+ [ self.xmonad-contrib self.xmonad-extras ];
+ };
+ xmonadBin = pkgs.writers.writeHaskell "xmonad" {
+ ghc = cfg.haskellPackages.ghc;
+ libraries = [ cfg.haskellPackages.xmonad ] ++
+ cfg.extraPackages cfg.haskellPackages ++
+ optionals cfg.enableContribAndExtras
+ (with cfg.haskellPackages; [ xmonad-contrib xmonad-extras ]);
+ } cfg.config;
+
+in
+{
+ options = {
+ services.xserver.windowManager.xmonad = {
+ enable = mkEnableOption "xmonad";
+ haskellPackages = mkOption {
+ default = pkgs.haskellPackages;
+ defaultText = "pkgs.haskellPackages";
+ example = literalExample "pkgs.haskell.packages.ghc784";
+ description = ''
+ haskellPackages used to build Xmonad and other packages.
+ This can be used to change the GHC version used to build
+ Xmonad and the packages listed in
+ <varname>extraPackages</varname>.
+ '';
+ };
+
+ extraPackages = mkOption {
+ default = self: [];
+ defaultText = "self: []";
+ example = literalExample ''
+ haskellPackages: [
+ haskellPackages.xmonad-contrib
+ haskellPackages.monad-logger
+ ]
+ '';
+ description = ''
+ Extra packages available to ghc when rebuilding Xmonad. The
+ value must be a function which receives the attrset defined
+ in <varname>haskellPackages</varname> as the sole argument.
+ '';
+ };
+
+ enableContribAndExtras = mkOption {
+ default = false;
+ type = lib.types.bool;
+ description = "Enable xmonad-{contrib,extras} in Xmonad.";
+ };
+
+ config = mkOption {
+ default = null;
+ type = with lib.types; nullOr (either path str);
+ description = ''
+ Configuration from which XMonad gets compiled. If no value
+ is specified, the xmonad config from $HOME/.xmonad is taken.
+ If you use xmonad --recompile, $HOME/.xmonad will be taken as
+ the configuration, but on the next restart of display-manager
+ this config will be reapplied.
+ '';
+ example = ''
+ import XMonad
+
+ main = launch defaultConfig
+ { modMask = mod4Mask -- Use Super instead of Alt
+ , terminal = "urxvt"
+ }
+ '';
+ };
+ };
+ };
+ config = mkIf cfg.enable {
+ services.xserver.windowManager = {
+ session = [{
+ name = "xmonad";
+ start = if (cfg.config != null) then ''
+ ${xmonadBin}
+ waitPID=$!
+ '' else ''
+ ${xmonad}/bin/xmonad &
+ waitPID=$!
+ '';
+ }];
+ };
+
+ environment.systemPackages = [ xmonad ];
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/xautolock.nix b/nixpkgs/nixos/modules/services/x11/xautolock.nix
new file mode 100644
index 00000000000..3e03131ca11
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/xautolock.nix
@@ -0,0 +1,140 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+ cfg = config.services.xserver.xautolock;
+in
+ {
+ options = {
+ services.xserver.xautolock = {
+ enable = mkEnableOption "xautolock";
+ enableNotifier = mkEnableOption "xautolock.notify" // {
+ description = ''
+ Whether to enable the notifier feature of xautolock.
+ This publishes a notification before the autolock.
+ '';
+ };
+
+ time = mkOption {
+ default = 15;
+ type = types.int;
+
+ description = ''
+ Idle time (in minutes) to wait until xautolock locks the computer.
+ '';
+ };
+
+ locker = mkOption {
+ default = "${pkgs.xlockmore}/bin/xlock"; # default according to `man xautolock`
+ example = "${pkgs.i3lock}/bin/i3lock -i /path/to/img";
+ type = types.str;
+
+ description = ''
+ The script to use when automatically locking the computer.
+ '';
+ };
+
+ nowlocker = mkOption {
+ default = null;
+ example = "${pkgs.i3lock}/bin/i3lock -i /path/to/img";
+ type = types.nullOr types.str;
+
+ description = ''
+ The script to use when manually locking the computer with <command>xautolock -locknow</command>.
+ '';
+ };
+
+ notify = mkOption {
+ default = 10;
+ type = types.int;
+
+ description = ''
+ Time (in seconds) before the actual lock when the notification about the pending lock should be published.
+ '';
+ };
+
+ notifier = mkOption {
+ default = null;
+ example = "${pkgs.libnotify}/bin/notify-send \"Locking in 10 seconds\"";
+ type = types.nullOr types.str;
+
+ description = ''
+ Notification script to be used to warn about the pending autolock.
+ '';
+ };
+
+ killer = mkOption {
+ default = null; # default according to `man xautolock` is none
+ example = "${pkgs.systemd}/bin/systemctl suspend";
+ type = types.nullOr types.str;
+
+ description = ''
+ The script to use when nothing has happend for as long as <option>killtime</option>
+ '';
+ };
+
+ killtime = mkOption {
+ default = 20; # default according to `man xautolock`
+ type = types.int;
+
+ description = ''
+ Minutes xautolock waits until it executes the script specified in <option>killer</option>
+ (Has to be at least 10 minutes)
+ '';
+ };
+
+ extraOptions = mkOption {
+ type = types.listOf types.str;
+ default = [ ];
+ example = [ "-detectsleep" ];
+ description = ''
+ Additional command-line arguments to pass to
+ <command>xautolock</command>.
+ '';
+ };
+ };
+ };
+
+ config = mkIf cfg.enable {
+ environment.systemPackages = with pkgs; [ xautolock ];
+ systemd.user.services.xautolock = {
+ description = "xautolock service";
+ wantedBy = [ "graphical-session.target" ];
+ partOf = [ "graphical-session.target" ];
+ serviceConfig = with lib; {
+ ExecStart = strings.concatStringsSep " " ([
+ "${pkgs.xautolock}/bin/xautolock"
+ "-noclose"
+ "-time ${toString cfg.time}"
+ "-locker '${cfg.locker}'"
+ ] ++ optionals cfg.enableNotifier [
+ "-notify ${toString cfg.notify}"
+ "-notifier '${cfg.notifier}'"
+ ] ++ optionals (cfg.nowlocker != null) [
+ "-nowlocker '${cfg.nowlocker}'"
+ ] ++ optionals (cfg.killer != null) [
+ "-killer '${cfg.killer}'"
+ "-killtime ${toString cfg.killtime}"
+ ] ++ cfg.extraOptions);
+ Restart = "always";
+ };
+ };
+ assertions = [
+ {
+ assertion = cfg.enableNotifier -> cfg.notifier != null;
+ message = "When enabling the notifier for xautolock, you also need to specify the notify script";
+ }
+ {
+ assertion = cfg.killer != null -> cfg.killtime >= 10;
+ message = "killtime has to be at least 10 minutes according to `man xautolock`";
+ }
+ ] ++ (lib.forEach [ "locker" "notifier" "nowlocker" "killer" ]
+ (option:
+ {
+ assertion = cfg.${option} != null -> builtins.substring 0 1 cfg.${option} == "/";
+ message = "Please specify a canonical path for `services.xserver.xautolock.${option}`";
+ })
+ );
+ };
+ }
diff --git a/nixpkgs/nixos/modules/services/x11/xbanish.nix b/nixpkgs/nixos/modules/services/x11/xbanish.nix
new file mode 100644
index 00000000000..b95fac68f16
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/xbanish.nix
@@ -0,0 +1,31 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let cfg = config.services.xbanish;
+
+in {
+ options.services.xbanish = {
+
+ enable = mkEnableOption "xbanish";
+
+ arguments = mkOption {
+ description = "Arguments to pass to xbanish command";
+ default = "";
+ example = "-d -i shift";
+ type = types.str;
+ };
+ };
+
+ config = mkIf cfg.enable {
+ systemd.user.services.xbanish = {
+ description = "xbanish hides the mouse pointer";
+ wantedBy = [ "graphical-session.target" ];
+ partOf = [ "graphical-session.target" ];
+ serviceConfig.ExecStart = ''
+ ${pkgs.xbanish}/bin/xbanish ${cfg.arguments}
+ '';
+ serviceConfig.Restart = "always";
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/xfs.conf b/nixpkgs/nixos/modules/services/x11/xfs.conf
new file mode 100644
index 00000000000..13dcf803db2
--- /dev/null
+++ b/nixpkgs/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/nixpkgs/nixos/modules/services/x11/xfs.nix b/nixpkgs/nixos/modules/services/x11/xfs.nix
new file mode 100644
index 00000000000..ea7cfa1aa43
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/xfs.nix
@@ -0,0 +1,46 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ configFile = ./xfs.conf;
+
+in
+
+{
+
+ ###### interface
+
+ options = {
+
+ services.xfs = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = "Whether to enable the X Font Server.";
+ };
+
+ };
+
+ };
+
+
+ ###### implementation
+
+ config = mkIf config.services.xfs.enable {
+ assertions = singleton
+ { assertion = config.fonts.enableFontDir;
+ message = "Please enable fonts.enableFontDir to use the X Font Server.";
+ };
+
+ systemd.services.xfs = {
+ description = "X Font Server";
+ after = [ "network.target" ];
+ wantedBy = [ "multi-user.target" ];
+ path = [ pkgs.xorg.xfs ];
+ script = "xfs -config ${configFile}";
+ };
+ };
+}
diff --git a/nixpkgs/nixos/modules/services/x11/xserver.nix b/nixpkgs/nixos/modules/services/x11/xserver.nix
new file mode 100644
index 00000000000..a8406544a72
--- /dev/null
+++ b/nixpkgs/nixos/modules/services/x11/xserver.nix
@@ -0,0 +1,822 @@
+{ config, lib, pkgs, ... }:
+
+with lib;
+
+let
+
+ # Abbreviations.
+ cfg = config.services.xserver;
+ xorg = pkgs.xorg;
+
+
+ # Map video driver names to driver packages. FIXME: move into card-specific modules.
+ knownVideoDrivers = {
+ # Alias so people can keep using "virtualbox" instead of "vboxvideo".
+ virtualbox = { modules = [ xorg.xf86videovboxvideo ]; driverName = "vboxvideo"; };
+
+ # Alias so that "radeon" uses the xf86-video-ati driver.
+ radeon = { modules = [ xorg.xf86videoati ]; driverName = "ati"; };
+
+ # modesetting does not have a xf86videomodesetting package as it is included in xorgserver
+ modesetting = {};
+ };
+
+ 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
+ ];
+
+ xrandrOptions = {
+ output = mkOption {
+ type = types.str;
+ example = "DVI-0";
+ description = ''
+ The output name of the monitor, as shown by <citerefentry>
+ <refentrytitle>xrandr</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </citerefentry> invoked without arguments.
+ '';
+ };
+
+ primary = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether this head is treated as the primary monitor,
+ '';
+ };
+
+ monitorConfig = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ DisplaySize 408 306
+ Option "DPMS" "false"
+ '';
+ description = ''
+ Extra lines to append to the <literal>Monitor</literal> section
+ verbatim. Available options are documented in the MONITOR section in
+ <citerefentry><refentrytitle>xorg.conf</refentrytitle>
+ <manvolnum>5</manvolnum></citerefentry>.
+ '';
+ };
+ };
+
+ # Just enumerate all heads without discarding XRandR output information.
+ xrandrHeads = let
+ mkHead = num: config: {
+ name = "multihead${toString num}";
+ inherit config;
+ };
+ in imap1 mkHead cfg.xrandrHeads;
+
+ xrandrDeviceSection = let
+ monitors = forEach xrandrHeads (h: ''
+ Option "monitor-${h.config.output}" "${h.name}"
+ '');
+ # First option is indented through the space in the config but any
+ # subsequent options aren't so we need to apply indentation to
+ # them here
+ monitorsIndented = if length monitors > 1
+ then singleton (head monitors) ++ map (m: " " + m) (tail monitors)
+ else monitors;
+ in concatStrings monitorsIndented;
+
+ # 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: singleton {
+ inherit (current) name;
+ value = ''
+ Section "Monitor"
+ Identifier "${current.name}"
+ ${optionalString (current.config.primary) ''
+ Option "Primary" "true"
+ ''}
+ ${optionalString (previous != []) ''
+ Option "RightOf" "${(head previous).name}"
+ ''}
+ ${current.config.monitorConfig}
+ EndSection
+ '';
+ } ++ previous;
+ monitors = reverseList (foldl mkMonitor [] xrandrHeads);
+ in concatMapStrings (getAttr "value") monitors;
+
+ configFile = pkgs.runCommand "xserver.conf"
+ { xfs = optionalString (cfg.useXFS != false)
+ ''FontPath "${toString cfg.useXFS}"'';
+ inherit (cfg) config;
+ preferLocalBuild = true;
+ }
+ ''
+ 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
+ ''; # */
+
+in
+
+{
+
+ imports =
+ [ ./display-managers/default.nix
+ ./window-managers/default.nix
+ ./desktop-managers/default.nix
+ ];
+
+
+ ###### interface
+
+ options = {
+
+ services.xserver = {
+
+ enable = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable the X server.
+ '';
+ };
+
+ autorun = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to start the X server automatically.
+ '';
+ };
+
+ exportConfiguration = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to symlink the X server configuration under
+ <filename>/etc/X11/xorg.conf</filename>.
+ '';
+ };
+
+ enableTCP = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to allow the X server to accept TCP connections.
+ '';
+ };
+
+ autoRepeatDelay = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ description = ''
+ Sets the autorepeat delay (length of time in milliseconds that a key must be depressed before autorepeat starts).
+ '';
+ };
+
+ autoRepeatInterval = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ description = ''
+ Sets the autorepeat interval (length of time in milliseconds that should elapse between autorepeat-generated keystrokes).
+ '';
+ };
+
+ inputClassSections = mkOption {
+ type = types.listOf types.lines;
+ default = [];
+ example = literalExample ''
+ [ '''
+ Identifier "Trackpoint Wheel Emulation"
+ MatchProduct "ThinkPad USB Keyboard with TrackPoint"
+ Option "EmulateWheel" "true"
+ Option "EmulateWheelButton" "2"
+ Option "Emulate3Buttons" "false"
+ '''
+ ]
+ '';
+ description = "Content of additional InputClass sections of the X server configuration file.";
+ };
+
+ modules = mkOption {
+ type = types.listOf types.path;
+ default = [];
+ example = literalExample "[ pkgs.xf86_input_wacom ]";
+ description = "Packages to be added to the module search path of the X server.";
+ };
+
+ resolutions = mkOption {
+ type = types.listOf types.attrs;
+ 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.
+ '';
+ };
+
+ videoDrivers = mkOption {
+ type = types.listOf types.str;
+ # !!! We'd like "nv" here, but it segfaults the X server.
+ default = [ "radeon" "cirrus" "vesa" "vmware" "modesetting" ];
+ example = [
+ "ati_unfree" "amdgpu" "amdgpu-pro"
+ "nv" "nvidia" "nvidiaLegacy390" "nvidiaLegacy340" "nvidiaLegacy304"
+ ];
+ # TODO(@oxij): think how to easily add the rest, like those nvidia things
+ relatedPackages = concatLists
+ (mapAttrsToList (n: v:
+ optional (hasPrefix "xf86video" n) {
+ path = [ "xorg" n ];
+ title = removePrefix "xf86video" n;
+ }) pkgs.xorg);
+ description = ''
+ The names of the video drivers the configuration
+ supports. They will be tried in order until one that
+ supports your card is found.
+ Don't combine those with "incompatible" OpenGL implementations,
+ e.g. free ones (mesa-based) with proprietary ones.
+
+ For unfree "nvidia*", the supported GPU lists are on
+ https://www.nvidia.com/object/unix.html
+ '';
+ };
+
+ videoDriver = mkOption {
+ type = types.nullOr types.str;
+ default = null;
+ example = "i810";
+ description = ''
+ The name of the video driver for your graphics card. This
+ option is obsolete; please set the
+ <option>services.xserver.videoDrivers</option> instead.
+ '';
+ };
+
+ drivers = mkOption {
+ type = types.listOf types.attrs;
+ internal = true;
+ description = ''
+ A list of attribute sets specifying drivers to be loaded by
+ the X11 server.
+ '';
+ };
+
+ dpi = mkOption {
+ type = types.nullOr types.int;
+ default = null;
+ description = "DPI resolution to use for X server.";
+ };
+
+ startDbusSession = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to start a new DBus session when you log in with dbus-launch.
+ '';
+ };
+
+ updateDbusEnvironment = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to update the DBus activation environment after launching the
+ desktop manager.
+ '';
+ };
+
+ layout = mkOption {
+ type = types.str;
+ default = "us";
+ description = ''
+ Keyboard layout, or multiple keyboard layouts separated by commas.
+ '';
+ };
+
+ xkbModel = mkOption {
+ type = types.str;
+ default = "pc104";
+ example = "presario";
+ description = ''
+ Keyboard model.
+ '';
+ };
+
+ xkbOptions = mkOption {
+ type = types.str;
+ default = "terminate:ctrl_alt_bksp";
+ example = "grp:caps_toggle, grp_led:scroll";
+ description = ''
+ X keyboard options; layout switching goes here.
+ '';
+ };
+
+ xkbVariant = mkOption {
+ type = types.str;
+ default = "";
+ example = "colemak";
+ description = ''
+ X keyboard variant.
+ '';
+ };
+
+ xkbDir = mkOption {
+ type = types.path;
+ default = "${pkgs.xkeyboard_config}/etc/X11/xkb";
+ description = ''
+ Path used for -xkbdir xserver parameter.
+ '';
+ };
+
+ config = mkOption {
+ type = types.lines;
+ description = ''
+ The contents of the configuration file of the X server
+ (<filename>xorg.conf</filename>).
+ '';
+ };
+
+ deviceSection = mkOption {
+ type = types.lines;
+ default = "";
+ example = "VideoRAM 131072";
+ description = "Contents of the first Device section of the X server configuration file.";
+ };
+
+ screenSection = mkOption {
+ type = types.lines;
+ default = "";
+ example = ''
+ Option "RandRRotation" "on"
+ '';
+ description = "Contents of the first Screen section of the X server configuration file.";
+ };
+
+ monitorSection = mkOption {
+ type = types.lines;
+ default = "";
+ example = "HorizSync 28-49";
+ description = "Contents of the first Monitor section of the X server configuration file.";
+ };
+
+ extraConfig = mkOption {
+ type = types.lines;
+ default = "";
+ description = "Additional contents (sections) included in the X server configuration file";
+ };
+
+ xrandrHeads = mkOption {
+ default = [];
+ example = [
+ "HDMI-0"
+ { output = "DVI-0"; primary = true; }
+ { output = "DVI-1"; monitorConfig = "Option \"Rotate\" \"left\""; }
+ ];
+ type = with types; listOf (coercedTo str (output: {
+ inherit output;
+ }) (submodule { options = xrandrOptions; }));
+ # Set primary to true for the first head if no other has been set
+ # primary already.
+ apply = heads: let
+ hasPrimary = any (x: x.primary) heads;
+ firstPrimary = head heads // { primary = true; };
+ newHeads = singleton firstPrimary ++ tail heads;
+ in if heads != [] && !hasPrimary then newHeads else heads;
+ description = ''
+ Multiple monitor configuration, just specify a list of XRandR
+ outputs. The individual elements should be either simple strings or
+ an attribute set of output options.
+
+ If the element is a string, it is denoting the physical output for a
+ monitor, if it's an attribute set, you must at least provide the
+ <option>output</option> option.
+
+ The monitors will be mapped from left to right in the order of the
+ list.
+
+ By default, the first monitor will be set as the primary monitor if
+ none of the elements contain an option that has set
+ <option>primary</option> to <literal>true</literal>.
+
+ <note><para>Only one monitor is allowed to be primary.</para></note>
+
+ Be careful using this option with multiple graphic adapters or with
+ drivers that have poor support for XRandR, unexpected things might
+ happen with those.
+ '';
+ };
+
+ serverFlagsSection = mkOption {
+ default = "";
+ example =
+ ''
+ Option "BlankTime" "0"
+ Option "StandbyTime" "0"
+ Option "SuspendTime" "0"
+ Option "OffTime" "0"
+ '';
+ description = "Contents of the ServerFlags section of the X server configuration file.";
+ };
+
+ moduleSection = mkOption {
+ type = types.lines;
+ default = "";
+ example =
+ ''
+ SubSection "extmod"
+ EndSubsection
+ '';
+ description = "Contents of the Module section of the X server configuration file.";
+ };
+
+ serverLayoutSection = mkOption {
+ type = types.lines;
+ default = "";
+ example =
+ ''
+ Option "AIGLX" "true"
+ '';
+ description = "Contents of the ServerLayout section of the X server configuration file.";
+ };
+
+ extraDisplaySettings = mkOption {
+ type = types.lines;
+ default = "";
+ example = "Virtual 2048 2048";
+ description = "Lines to be added to every Display subsection of the Screen section.";
+ };
+
+ defaultDepth = mkOption {
+ type = types.int;
+ default = 0;
+ example = 8;
+ description = "Default colour depth.";
+ };
+
+ useXFS = mkOption {
+ # FIXME: what's the type of this option?
+ default = false;
+ example = "unix/:7100";
+ description = "Determines how to connect to the X Font Server.";
+ };
+
+ tty = mkOption {
+ type = types.nullOr types.int;
+ default = 7;
+ description = "Virtual console for the X server.";
+ };
+
+ display = mkOption {
+ type = types.nullOr types.int;
+ default = 0;
+ description = "Display number for the X server.";
+ };
+
+ virtualScreen = mkOption {
+ type = types.nullOr types.attrs;
+ default = null;
+ example = { x = 2048; y = 2048; };
+ description = ''
+ Virtual screen size for Xrandr.
+ '';
+ };
+
+ verbose = mkOption {
+ type = types.nullOr types.int;
+ default = 3;
+ example = 7;
+ description = ''
+ Controls verbosity of X logging.
+ '';
+ };
+
+ useGlamor = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to use the Glamor module for 2D acceleration,
+ if possible.
+ '';
+ };
+
+ enableCtrlAltBackspace = mkOption {
+ type = types.bool;
+ default = false;
+ description = ''
+ Whether to enable the DontZap option, which binds Ctrl+Alt+Backspace
+ to forcefully kill X. This can lead to data loss and is disabled
+ by default.
+ '';
+ };
+
+ terminateOnReset = mkOption {
+ type = types.bool;
+ default = true;
+ description = ''
+ Whether to terminate X upon server reset.
+ '';
+ };
+ };
+
+ };
+
+
+
+ ###### implementation
+
+ config = mkIf cfg.enable {
+
+ services.xserver.displayManager.lightdm.enable =
+ let dmconf = cfg.displayManager;
+ default = !( dmconf.auto.enable
+ || dmconf.gdm.enable
+ || dmconf.sddm.enable
+ || dmconf.slim.enable
+ || dmconf.xpra.enable );
+ in mkIf (default) true;
+
+ hardware.opengl.enable = mkDefault true;
+
+ services.xserver.videoDrivers = mkIf (cfg.videoDriver != null) [ cfg.videoDriver ];
+
+ # FIXME: somehow check for unknown driver names.
+ services.xserver.drivers = flip concatMap cfg.videoDrivers (name:
+ let driver =
+ attrByPath [name]
+ (if xorg ? ${"xf86video" + name}
+ then { modules = [xorg.${"xf86video" + name}]; }
+ else null)
+ knownVideoDrivers;
+ in optional (driver != null) ({ inherit name; modules = []; driverName = name; } // driver));
+
+ assertions = [
+ { assertion = config.security.polkit.enable;
+ message = "X11 requires Polkit to be enabled (‘security.polkit.enable = true’).";
+ }
+ (let primaryHeads = filter (x: x.primary) cfg.xrandrHeads; in {
+ assertion = length primaryHeads < 2;
+ message = "Only one head is allowed to be primary in "
+ + "‘services.xserver.xrandrHeads’, but there are "
+ + "${toString (length primaryHeads)} heads set to primary: "
+ + concatMapStringsSep ", " (x: x.output) primaryHeads;
+ })
+ ];
+
+ environment.etc =
+ (optionals cfg.exportConfiguration
+ [ { source = "${configFile}";
+ target = "X11/xorg.conf";
+ }
+ # -xkbdir command line option does not seems to be passed to xkbcomp.
+ { source = "${cfg.xkbDir}";
+ target = "X11/xkb";
+ }
+ ])
+ # localectl looks into 00-keyboard.conf
+ ++ [
+ {
+ text = ''
+ Section "InputClass"
+ Identifier "Keyboard catchall"
+ MatchIsKeyboard "on"
+ Option "XkbModel" "${cfg.xkbModel}"
+ Option "XkbLayout" "${cfg.layout}"
+ Option "XkbOptions" "${cfg.xkbOptions}"
+ Option "XkbVariant" "${cfg.xkbVariant}"
+ EndSection
+ '';
+ target = "X11/xorg.conf.d/00-keyboard.conf";
+ }
+ ]
+ # Needed since 1.18; see https://bugs.freedesktop.org/show_bug.cgi?id=89023#c5
+ ++ (let cfgPath = "/X11/xorg.conf.d/10-evdev.conf"; in
+ [{
+ source = xorg.xf86inputevdev.out + "/share" + cfgPath;
+ target = cfgPath;
+ }]
+ );
+
+ environment.systemPackages =
+ [ xorg.xorgserver.out
+ 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
+ xorg.xauth
+ pkgs.xterm
+ pkgs.xdg_utils
+ xorg.xf86inputevdev.out # get evdev.4 man page
+ ]
+ ++ optional (elem "virtualbox" cfg.videoDrivers) xorg.xrefresh;
+
+ environment.pathsToLink = [ "/share/X11" ];
+
+ xdg = {
+ autostart.enable = true;
+ menus.enable = true;
+ mime.enable = true;
+ icons.enable = true;
+ };
+
+ # The default max inotify watches is 8192.
+ # Nowadays most apps require a good number of inotify watches,
+ # the value below is used by default on several other distros.
+ boot.kernel.sysctl."fs.inotify.max_user_watches" = mkDefault 524288;
+
+ systemd.defaultUnit = mkIf cfg.autorun "graphical.target";
+
+ systemd.services.display-manager =
+ { description = "X11 Server";
+
+ after = [ "systemd-udev-settle.service" "acpid.service" "systemd-logind.service" ];
+ wants = [ "systemd-udev-settle.service" ];
+
+ restartIfChanged = false;
+
+ environment =
+ optionalAttrs config.hardware.opengl.setLdLibraryPath
+ { LD_LIBRARY_PATH = pkgs.addOpenGLRunpath.driverLink; }
+ // cfg.displayManager.job.environment;
+
+ preStart =
+ ''
+ ${cfg.displayManager.job.preStart}
+
+ rm -f /tmp/.X0-lock
+ '';
+
+ script = "${cfg.displayManager.job.execCmd}";
+
+ serviceConfig = {
+ Restart = "always";
+ RestartSec = "200ms";
+ SyslogIdentifier = "display-manager";
+ # Stop restarting if the display manager stops (crashes) 2 times
+ # in one minute. Starting X typically takes 3-4s.
+ StartLimitInterval = "30s";
+ StartLimitBurst = "3";
+ };
+ };
+
+ services.xserver.displayManager.xserverArgs =
+ [ "-config ${configFile}"
+ "-xkbdir" "${cfg.xkbDir}"
+ # Log at the default verbosity level to stderr rather than /var/log/X.*.log.
+ "-logfile" "/dev/null"
+ ] ++ optional (cfg.display != null) ":${toString cfg.display}"
+ ++ optional (cfg.tty != null) "vt${toString cfg.tty}"
+ ++ optional (cfg.dpi != null) "-dpi ${toString cfg.dpi}"
+ ++ optional (cfg.verbose != null) "-verbose ${toString cfg.verbose}"
+ ++ optional (!cfg.enableTCP) "-nolisten tcp"
+ ++ optional (cfg.autoRepeatDelay != null) "-ardelay ${toString cfg.autoRepeatDelay}"
+ ++ optional (cfg.autoRepeatInterval != null) "-arinterval ${toString cfg.autoRepeatInterval}"
+ ++ optional cfg.terminateOnReset "-terminate";
+
+ services.xserver.modules =
+ concatLists (catAttrs "modules" cfg.drivers) ++
+ [ xorg.xorgserver.out
+ xorg.xf86inputevdev.out
+ ];
+
+ system.extraDependencies = singleton (pkgs.runCommand "xkb-validated" {
+ inherit (cfg) xkbModel layout xkbVariant xkbOptions;
+ nativeBuildInputs = [ pkgs.xkbvalidate ];
+ preferLocalBuild = true;
+ } ''
+ xkbvalidate "$xkbModel" "$layout" "$xkbVariant" "$xkbOptions"
+ touch "$out"
+ '');
+
+ services.xserver.config =
+ ''
+ Section "ServerFlags"
+ Option "AllowMouseOpenFail" "on"
+ Option "DontZap" "${if cfg.enableCtrlAltBackspace then "off" else "on"}"
+ ${cfg.serverFlagsSection}
+ EndSection
+
+ Section "Module"
+ ${cfg.moduleSection}
+ EndSection
+
+ Section "Monitor"
+ Identifier "Monitor[0]"
+ ${cfg.monitorSection}
+ EndSection
+
+ # Additional "InputClass" sections
+ ${flip concatMapStrings cfg.inputClassSections (inputClassSection: ''
+ Section "InputClass"
+ ${inputClassSection}
+ 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 cfg.drivers (d: ''
+ Screen "Screen-${d.name}[0]"
+ '')}
+ EndSection
+
+ ${if cfg.useGlamor then ''
+ Section "Module"
+ Load "dri2"
+ Load "glamoregl"
+ EndSection
+ '' else ""}
+
+ # For each supported driver, add a "Device" and "Screen"
+ # section.
+ ${flip concatMapStrings cfg.drivers (driver: ''
+
+ Section "Device"
+ Identifier "Device-${driver.name}[0]"
+ Driver "${driver.driverName or driver.name}"
+ ${if cfg.useGlamor then ''Option "AccelMethod" "glamor"'' else ""}
+ ${cfg.deviceSection}
+ ${driver.deviceSection or ""}
+ ${xrandrDeviceSection}
+ EndSection
+
+ Section "Screen"
+ Identifier "Screen-${driver.name}[0]"
+ Device "Device-${driver.name}[0]"
+ ${optionalString (cfg.monitorSection != "") ''
+ Monitor "Monitor[0]"
+ ''}
+
+ ${cfg.screenSection}
+ ${driver.screenSection or ""}
+
+ ${optionalString (cfg.defaultDepth != 0) ''
+ DefaultDepth ${toString cfg.defaultDepth}
+ ''}
+
+ ${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}
+
+ ${cfg.extraConfig}
+ '';
+
+ fonts.enableDefaultFonts = mkDefault true;
+
+ };
+
+}