push sheeet
Some checks failed
Periodic Merges (6h) / master → staging-nixos (push) Failing after 12m50s
Periodic Merges (6h) / master → staging-next (push) Failing after 12m54s
Periodic Merges (24h) / merge-base(master,staging) → haskell-updates (push) Failing after 11m54s
Periodic Merges (6h) / staging-next → staging (push) Failing after 12m13s
Periodic Merges (24h) / staging-next-25.05 → staging-25.05 (push) Failing after 13m24s
Periodic Merges (24h) / release-25.05 → staging-next-25.05 (push) Failing after 14m28s

This commit is contained in:
Dark Steveneq
2025-10-09 14:15:47 +02:00
commit 646b892680
49168 changed files with 5897842 additions and 0 deletions

View File

@@ -0,0 +1,185 @@
{
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 if isAttrs v then
"\n{\n" + convertAttrs v + "\n}"
else
abort "clight.toConf: unexpected type (v = ${v})";
getSep = v: if isAttrs v then ":" else "=";
convertAttrs =
attrs:
concatStringsSep "\n" (
mapAttrsToList (name: value: "${toString name} ${getSep value} ${toConf value};") attrs
);
clightConf = pkgs.writeText "clight.conf" (
convertAttrs (filterAttrs (_: value: value != null) cfg.settings)
);
in
{
options.services.clight = {
enable = mkEnableOption "clight";
temperature = {
day = mkOption {
type = types.int;
default = 5500;
description = ''
Colour temperature to use during the day, between
`1000` and `25000` K.
'';
};
night = mkOption {
type = types.int;
default = 3700;
description = ''
Colour temperature to use at night, between
`1000` and `25000` K.
'';
};
};
settings =
let
validConfigTypes =
with types;
oneOf [
int
str
bool
float
];
collectionTypes =
with types;
oneOf [
validConfigTypes
(listOf validConfigTypes)
];
in
mkOption {
type = with types; attrsOf (nullOr (either collectionTypes (attrsOf collectionTypes)));
default = { };
example = {
captures = 20;
gamma_long_transition = true;
ac_capture_timeouts = [
120
300
60
];
};
description = ''
Additional configuration to extend clight.conf. See
<https://github.com/FedeDP/Clight/blob/master/Extra/clight.conf> for a
sample configuration file.
'';
};
};
config = mkIf cfg.enable {
assertions =
let
inRange =
v: l: r:
v >= l && v <= r;
in
[
{
assertion =
config.location.provider == "manual"
-> inRange config.location.latitude (-90) 90 && inRange config.location.longitude (-180) 180;
message = "You must specify a valid latitude and longitude if manually providing location";
}
];
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") {
daytime.latitude = mkDefault config.location.latitude;
daytime.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}
'';
};
};
};
}

View File

@@ -0,0 +1,47 @@
{
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 ];
systemd.tmpfiles.packages = [ pkgs.colord ];
users.users.colord = {
isSystemUser = true;
home = "/var/lib/colord";
group = "colord";
};
users.groups.colord = { };
};
}

View File

@@ -0,0 +1,281 @@
{
lib,
pkgs,
config,
utils,
...
}:
let
inherit (lib)
concatMapStrings
literalExpression
mkDefault
mkEnableOption
mkIf
mkOption
types
;
cfg = config.services.xserver.desktopManager.budgie;
nixos-background-light = pkgs.nixos-artwork.wallpapers.nineish;
nixos-background-dark = pkgs.nixos-artwork.wallpapers.nineish-dark-gray;
nixos-gsettings-overrides = pkgs.budgie-gsettings-overrides.override {
inherit (cfg) extraGSettingsOverrides extraGSettingsOverridePackages;
inherit nixos-background-dark nixos-background-light;
};
nixos-background-info = pkgs.writeTextFile {
name = "nixos-background-info";
text = ''
<?xml version="1.0"?>
<!DOCTYPE wallpapers SYSTEM "gnome-wp-list.dtd">
<wallpapers>
<wallpaper deleted="false">
<name>Nineish</name>
<filename>${nixos-background-light.gnomeFilePath}</filename>
<options>zoom</options>
<shade_type>solid</shade_type>
<pcolor>#d1dcf8</pcolor>
<scolor>#e3ebfe</scolor>
</wallpaper>
<wallpaper deleted="false">
<name>Nineish Dark Gray</name>
<filename>${nixos-background-dark.gnomeFilePath}</filename>
<options>zoom</options>
<shade_type>solid</shade_type>
<pcolor>#151515</pcolor>
<scolor>#262626</scolor>
</wallpaper>
</wallpapers>
'';
destination = "/share/gnome-background-properties/nixos.xml";
};
budgie-control-center' = pkgs.budgie-control-center.override {
enableSshSocket = config.services.openssh.startWhenNeeded;
};
notExcluded = pkg: utils.disablePackageByName pkg config.environment.budgie.excludePackages;
in
{
meta.maintainers = lib.teams.budgie.members;
options = {
services.xserver.desktopManager.budgie = {
enable = mkEnableOption "the Budgie desktop";
sessionPath = mkOption {
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).
'';
type = types.listOf types.package;
default = [ ];
example = literalExpression "[ pkgs.gpaste ]";
};
extraGSettingsOverrides = mkOption {
description = "Additional GSettings overrides.";
type = types.lines;
default = "";
};
extraGSettingsOverridePackages = mkOption {
description = "List of packages for which GSettings are overridden.";
type = types.listOf types.path;
default = [ ];
};
extraPlugins = mkOption {
description = "Extra plugins for the Budgie desktop";
type = types.listOf types.package;
default = [ ];
example = literalExpression "[ pkgs.budgie-analogue-clock-applet ]";
};
};
environment.budgie.excludePackages = mkOption {
description = "Which packages Budgie should exclude from the default environment.";
type = types.listOf types.package;
default = [ ];
example = literalExpression "[ pkgs.mate-terminal ]";
};
};
config = mkIf cfg.enable {
services.displayManager.sessionPackages = with pkgs; [
budgie-desktop
];
services.xserver.displayManager.lightdm.greeters.slick = {
enable = mkDefault true;
theme = mkDefault {
name = "Qogir";
package = pkgs.qogir-theme;
};
iconTheme = mkDefault {
name = "Qogir";
package = pkgs.qogir-icon-theme;
};
cursorTheme = mkDefault {
name = "Qogir";
package = pkgs.qogir-icon-theme;
};
};
services.xserver.desktopManager.budgie.sessionPath = [ pkgs.budgie-desktop-view ];
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}
''
+ lib.optionalString config.services.gnome.gcr-ssh-agent.enable ''
# Hack: https://bugzilla.redhat.com/show_bug.cgi?id=2250704 still
# applies to sessions not managed by systemd.
if [ -z "$SSH_AUTH_SOCK" ] && [ -n "$XDG_RUNTIME_DIR" ]; then
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/gcr/ssh"
fi
'';
environment.systemPackages =
with pkgs;
[
# Budgie Desktop.
budgie-backgrounds
budgie-control-center'
(budgie-desktop-with-plugins.override { plugins = cfg.extraPlugins; })
budgie-desktop-view
budgie-screensaver
budgie-session
# Required by Budgie Menu.
gnome-menus
# Required by Budgie Control Center.
zenity
# Provides `gsettings`.
glib
# Update user directories.
xdg-user-dirs
]
++ lib.optional config.networking.networkmanager.enable pkgs.networkmanagerapplet
++ (utils.removePackagesByName [
nemo
mate.eom
mate.pluma
mate.atril
mate.engrampa
mate.mate-calc
mate.mate-system-monitor
vlc
# Desktop themes.
qogir-theme
qogir-icon-theme
nixos-background-info
# Default settings.
nixos-gsettings-overrides
] config.environment.budgie.excludePackages)
++ cfg.sessionPath;
# Both budgie-desktop-view and nemo defaults to this emulator.
programs.gnome-terminal.enable = mkDefault (notExcluded pkgs.gnome-terminal);
# Fonts.
fonts.packages = [
pkgs.noto-fonts
pkgs.hack-font
];
fonts.fontconfig.defaultFonts = {
sansSerif = mkDefault [ "Noto Sans" ];
monospace = mkDefault [ "Hack" ];
};
environment.pathsToLink = [
"/share" # TODO: https://github.com/NixOS/nixpkgs/issues/47173
];
# GSettings overrides.
environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
# Required by Budgie Desktop.
services.xserver.updateDbusEnvironment = true;
programs.dconf.enable = true;
# Required by Budgie Screensaver.
security.pam.services.budgie-screensaver = { };
# Required by Budgie's Polkit Dialog.
security.polkit.enable = mkDefault true;
# Required by Budgie Panel plugins and/or Budgie Control Center panels.
networking.networkmanager.enable = mkDefault true; # for BCC's Network panel.
programs.nm-applet.enable = config.networking.networkmanager.enable; # Budgie has no Network applet.
programs.nm-applet.indicator = true; # Budgie uses AppIndicators.
hardware.bluetooth.enable = mkDefault true; # for Budgie's Status Indicator and BCC's Bluetooth panel.
xdg.portal.enable = mkDefault true; # for BCC's Applications panel.
xdg.portal.extraPortals = with pkgs; [
xdg-desktop-portal-gtk # provides a XDG Portals implementation.
];
xdg.portal.configPackages = mkDefault [ pkgs.budgie-desktop ];
services.geoclue2.enable = mkDefault true; # for BCC's Privacy > Location Services panel.
services.upower.enable = config.powerManagement.enable; # for Budgie's Status Indicator and BCC's Power panel.
services.libinput.enable = mkDefault true; # for BCC's Mouse panel.
services.colord.enable = mkDefault true; # for BCC's Color panel.
services.gnome.at-spi2-core.enable = mkDefault true; # for BCC's A11y panel.
services.accounts-daemon.enable = mkDefault true; # for BCC's Users panel.
services.udisks2.enable = mkDefault true; # for BCC's Details panel.
# For BCC's Online Accounts panel.
services.gnome.gnome-online-accounts.enable = mkDefault true;
# For BCC's Printers panel.
services.printing.enable = mkDefault true;
services.system-config-printer.enable = config.services.printing.enable;
# For BCC's Sharing panel.
services.dleyna.enable = mkDefault true;
services.gnome.gnome-user-share.enable = mkDefault true;
services.gnome.rygel.enable = mkDefault true;
# Other default services.
services.gnome.evolution-data-server.enable = mkDefault true;
services.gnome.glib-networking.enable = mkDefault true;
services.gnome.gnome-keyring.enable = mkDefault true;
services.gnome.gcr-ssh-agent.enable = mkDefault true;
services.gnome.gnome-settings-daemon.enable = mkDefault true;
services.gvfs.enable = mkDefault true;
# Register packages for DBus.
services.dbus.packages = [
budgie-control-center'
];
# Register packages for udev.
services.udev.packages = with pkgs; [
magpie
];
# Shell integration for MATE Terminal.
programs.bash.vteIntegration = true;
programs.zsh.vteIntegration = true;
};
}

View File

@@ -0,0 +1,90 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
xcfg = config.services.xserver;
cfg = xcfg.desktopManager.cde;
in
{
options.services.xserver.desktopManager.cde = {
enable = mkEnableOption "Common Desktop Environment";
extraPackages = mkOption {
type = with types; listOf package;
default = with pkgs.xorg; [
xclock
bitmap
xlsfonts
xfd
xrefresh
xload
xwininfo
xdpyinfo
xwd
xwud
];
defaultText = literalExpression ''
with pkgs.xorg; [
xclock bitmap xlsfonts xfd xrefresh xload xwininfo xdpyinfo xwd xwud
]
'';
description = ''
Extra packages to be installed system wide.
'';
};
};
config = mkIf (xcfg.enable && cfg.enable) {
environment.systemPackages = cfg.extraPackages;
services.rpcbind.enable = true;
services.xinetd.enable = true;
services.xinetd.services = [
{
name = "cmsd";
protocol = "udp";
user = "root";
server = "${pkgs.cdesktopenv}/bin/rpc.cmsd";
extraConfig = ''
type = RPC UNLISTED
rpc_number = 100068
rpc_version = 2-5
only_from = 127.0.0.1/0
'';
}
];
users.groups.mail = { };
security.wrappers = {
dtmail = {
setgid = true;
owner = "root";
group = "mail";
source = "${pkgs.cdesktopenv}/bin/dtmail";
};
};
system.activationScripts.setup-cde = ''
mkdir -p /var/dt/{tmp,appconfig/appmanager}
chmod a+w+t /var/dt/{tmp,appconfig/appmanager}
'';
services.xserver.desktopManager.session = [
{
name = "CDE";
start = ''
exec ${pkgs.cdesktopenv}/bin/Xsession
'';
}
];
};
meta.maintainers = [ ];
}

View File

@@ -0,0 +1,275 @@
{
config,
lib,
pkgs,
utils,
...
}:
with lib;
let
cfg = config.services.xserver.desktopManager.cinnamon;
serviceCfg = config.services.cinnamon;
nixos-gsettings-overrides = pkgs.cinnamon-gsettings-overrides.override {
extraGSettingsOverridePackages = cfg.extraGSettingsOverridePackages;
extraGSettingsOverrides = cfg.extraGSettingsOverrides;
};
notExcluded = pkg: utils.disablePackageByName pkg config.environment.cinnamon.excludePackages;
in
{
options = {
services.cinnamon = {
apps.enable = mkEnableOption "Cinnamon default applications";
};
services.xserver.desktopManager.cinnamon = {
enable = mkEnableOption "the cinnamon desktop manager";
sessionPath = mkOption {
default = [ ];
type = types.listOf types.package;
example = literalExpression "[ pkgs.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).
'';
};
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.";
};
};
environment.cinnamon.excludePackages = mkOption {
default = [ ];
example = literalExpression "[ pkgs.blueman ]";
type = types.listOf types.package;
description = "Which packages cinnamon should exclude from the default environment";
};
};
config = mkMerge [
(mkIf cfg.enable {
services.displayManager.sessionPackages = [ pkgs.cinnamon ];
services.xserver.displayManager.lightdm.greeters.slick = {
enable = mkDefault true;
# Taken from mint-artwork.gschema.override
theme = mkIf (notExcluded pkgs.mint-themes) {
name = mkDefault "Mint-Y-Aqua";
package = mkDefault pkgs.mint-themes;
};
iconTheme = mkIf (notExcluded pkgs.mint-y-icons) {
name = mkDefault "Mint-Y-Sand";
package = mkDefault pkgs.mint-y-icons;
};
cursorTheme = mkIf (notExcluded pkgs.mint-cursor-themes) {
name = mkDefault "Bibata-Modern-Classic";
package = mkDefault pkgs.mint-cursor-themes;
};
};
# Have to take care of GDM + Cinnamon on Wayland users
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}
''
+ lib.optionalString config.services.gnome.gcr-ssh-agent.enable ''
# Hack: https://bugzilla.redhat.com/show_bug.cgi?id=2250704 still
# applies to sessions not managed by systemd.
if [ -z "$SSH_AUTH_SOCK" ] && [ -n "$XDG_RUNTIME_DIR" ]; then
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/gcr/ssh"
fi
'';
# Default services
services.blueman.enable = mkDefault (notExcluded pkgs.blueman);
hardware.bluetooth.enable = mkDefault true;
security.polkit.enable = true;
services.accounts-daemon.enable = true;
services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
services.dbus.packages = with pkgs; [
cinnamon
cinnamon-screensaver
nemo-with-extensions
xapp
];
services.cinnamon.apps.enable = mkDefault true;
services.gnome.evolution-data-server.enable = true;
services.gnome.glib-networking.enable = true;
services.gnome.gnome-keyring.enable = true;
services.gnome.gcr-ssh-agent.enable = mkDefault true;
services.gvfs.enable = true;
services.power-profiles-daemon.enable = mkDefault true;
services.switcherooControl.enable = mkDefault true; # xapp-gpu-offload-helper
services.touchegg.enable = mkDefault true;
services.udisks2.enable = true;
services.upower.enable = mkDefault config.powerManagement.enable;
services.libinput.enable = mkDefault true;
services.xserver.updateDbusEnvironment = true;
networking.networkmanager.enable = mkDefault true;
# Enable colord server
services.colord.enable = true;
# Enable dconf
programs.dconf.enable = true;
# Enable org.a11y.Bus
services.gnome.at-spi2-core.enable = true;
# Fix lockscreen
security.pam.services = {
cinnamon-screensaver = { };
};
environment.systemPackages =
with pkgs;
(
[
# Teach nemo-desktop how to launch file browser.
# https://github.com/linuxmint/nemo/blob/6.4.0/src/nemo-desktop-application.c#L398
(writeTextFile {
name = "x-cinnamon-mimeapps";
destination = "/share/applications/x-cinnamon-mimeapps.list";
text = ''
[Default Applications]
inode/directory=nemo.desktop
'';
})
desktop-file-utils
# common-files
cinnamon
cinnamon-session
cinnamon-desktop
cinnamon-menus
cinnamon-translations
# utils needed by some scripts
killall
# session requirements
cinnamon-screensaver
# cinnamon-killer-daemon: provided by cinnamon
networkmanagerapplet # session requirement - also nm-applet not needed
# packages
nemo-with-extensions
gnome-online-accounts-gtk
cinnamon-control-center
cinnamon-settings-daemon
libgnomekbd
# theme
adwaita-icon-theme
gnome-themes-extra
gtk3.out
# other
glib # for gsettings
xdg-user-dirs
]
++ utils.removePackagesByName [
# accessibility
onboard
# theme
sound-theme-freedesktop
nixos-artwork.wallpapers.simple-dark-gray
mint-artwork
mint-cursor-themes
mint-l-icons
mint-l-theme
mint-themes
mint-x-icons
mint-y-icons
xapp # provides some xapp-* icons
] config.environment.cinnamon.excludePackages
);
xdg.mime.enable = true;
xdg.icons.enable = true;
xdg.portal.enable = true;
xdg.portal.extraPortals = [
pkgs.xdg-desktop-portal-xapp
pkgs.xdg-desktop-portal-gtk
];
services.orca.enable = mkDefault (notExcluded pkgs.orca);
xdg.portal.configPackages = mkDefault [ pkgs.cinnamon ];
# Override GSettings schemas
environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${nixos-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
environment.pathsToLink = [
# FIXME: modules should link subdirs of `/share` rather than relying on this
"/share" # TODO: https://github.com/NixOS/nixpkgs/issues/47173
];
# Shell integration for VTE terminals
programs.bash.vteIntegration = mkDefault true;
programs.zsh.vteIntegration = mkDefault true;
# Default Fonts
fonts.packages = with pkgs; [
dejavu_fonts # Default monospace font in LMDE 6+
ubuntu-classic # required for default theme
];
})
(mkIf serviceCfg.apps.enable {
programs.gnome-disks.enable = mkDefault (notExcluded pkgs.gnome-disk-utility);
programs.gnome-terminal.enable = mkDefault (notExcluded pkgs.gnome-terminal);
programs.file-roller.enable = mkDefault (notExcluded pkgs.file-roller);
environment.systemPackages =
with pkgs;
utils.removePackagesByName [
# cinnamon team apps
bulky
warpinator
# cinnamon xapp
xviewer
xreader
xed-editor
pix
# external apps shipped with linux-mint
celluloid
gnome-calculator
gnome-calendar
gnome-screenshot
] config.environment.cinnamon.excludePackages;
})
];
}

View File

@@ -0,0 +1,120 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib) mkOption types;
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
./phosh.nix
./xfce.nix
../../desktop-managers/plasma6.nix
./lumina.nix
./lxqt.nix
./enlightenment.nix
./retroarch.nix
./kodi.nix
./mate.nix
../../desktop-managers/pantheon.nix
./surf-display.nix
./cde.nix
./cinnamon.nix
./budgie.nix
../../desktop-managers/lomiri.nix
../../desktop-managers/cosmic.nix
../../desktop-managers/gnome.nix
];
options = {
services.xserver.desktopManager = {
wallpaper = {
mode = mkOption {
type = types.enum [
"center"
"fill"
"max"
"scale"
"tile"
];
default = "scale";
example = "fill";
description = ''
The file {file}`~/.background-image` is used as a background image.
This option specifies the placement of this image onto your desktop.
Possible values:
`center`: Center the image on the background. If it is too small, it will be surrounded by a black border.
`fill`: Like `scale`, 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.
`max`: Like `fill`, but scale the image to the maximum size that fits the screen with black borders on one side.
`scale`: Fit the file into the background without repeating it, cutting off stuff or using borders. But the aspect ratio is not preserved either.
`tile`: Tile (repeat) the image in case it is too small for the screen.
'';
};
combineScreens = mkOption {
type = types.bool;
default = false;
description = ''
When set to `true` the wallpaper will stretch across all screens.
When set to `false` the wallpaper is duplicated to all screens.
'';
};
};
session = mkOption {
internal = true;
default = [ ];
example = lib.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
`displayManager`.
'';
apply = map (
d:
d
// {
manage = "desktop";
start =
d.start
# literal newline to ensure d.start's last line is not appended to
+ lib.optionalString (needBGCond d) ''
if [ -e $HOME/.background-image ]; then
${pkgs.feh}/bin/feh --bg-${cfg.wallpaper.mode} ${lib.optionalString cfg.wallpaper.combineScreens "--no-xinerama"} $HOME/.background-image
fi
'';
}
);
};
};
};
config.services.xserver.displayManager.session = cfg.session;
}

View File

@@ -0,0 +1,140 @@
{
config,
lib,
pkgs,
utils,
...
}:
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
{
meta = {
maintainers = teams.enlightenment.members;
};
imports = [
(mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "e19" "enable" ]
[ "services" "xserver" "desktopManager" "enlightenment" "enable" ]
)
];
options = {
services.xserver.desktopManager.enlightenment.enable = mkOption {
type = types.bool;
default = false;
description = "Enable the Enlightenment desktop environment.";
};
environment.enlightenment.excludePackages = mkOption {
default = [ ];
example = literalExpression "[ pkgs.enlightenment.ephoto ]";
type = types.listOf types.package;
description = "Which packages Enlightenment should exclude from the default environment";
};
};
config = mkIf cfg.enable {
environment.systemPackages = utils.removePackagesByName (with pkgs; [
enlightenment.econnman
enlightenment.efl
enlightenment.enlightenment
enlightenment.ecrire
enlightenment.ephoto
enlightenment.rage
enlightenment.terminology
xorg.xcursorthemes
]) config.environment.enlightenment.excludePackages;
environment.pathsToLink = [
"/etc/enlightenment"
"/share/enlightenment"
"/share/elementary"
"/share/locale"
];
services.displayManager.sessionPackages = [ pkgs.enlightenment.enlightenment ];
services.xserver.displayManager.sessionCommands = ''
if test "$XDG_CURRENT_DESKTOP" = "Enlightenment"; then
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 https://freedesktop.org/wiki/Software/xdg-user-dirs/
${pkgs.xdg-user-dirs}/bin/xdg-user-dirs-update
fi
'';
# Wrappers for programs installed by enlightenment that should be setuid
security.wrappers = {
enlightenment_ckpasswd = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_ckpasswd";
};
enlightenment_sys = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_sys";
};
enlightenment_system = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.enlightenment.enlightenment}/lib/enlightenment/utils/enlightenment_system";
};
};
environment.etc."X11/xkb".source = xcfg.xkb.dir;
fonts.packages = [ pkgs.dejavu_fonts ];
services.udisks2.enable = true;
services.upower.enable = config.powerManagement.enable;
services.libinput.enable = mkDefault true;
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";
};
};
};
}

View File

@@ -0,0 +1,42 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.desktopManager.kodi;
in
{
options = {
services.xserver.desktopManager.kodi = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the kodi multimedia center.";
};
package = mkPackageOption pkgs "kodi" {
example = "kodi.withPackages (p: with p; [ jellyfin pvr-iptvsimple vfs-sftp ])";
};
};
};
config = mkIf cfg.enable {
services.xserver.desktopManager.session = [
{
name = "kodi";
start = ''
LIRC_SOCKET_PATH=/run/lirc/lircd ${cfg.package}/bin/kodi --standalone &
waitPID=$!
'';
}
];
environment.systemPackages = [ cfg.package ];
};
}

View File

@@ -0,0 +1,48 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
xcfg = config.services.xserver;
cfg = xcfg.desktopManager.lumina;
in
{
meta = {
maintainers = teams.lumina.members;
};
options = {
services.xserver.desktopManager.lumina.enable = mkOption {
type = types.bool;
default = false;
description = "Enable the Lumina desktop manager";
};
};
config = mkIf cfg.enable {
services.displayManager.sessionPackages = [
pkgs.lumina.lumina
];
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"
];
};
}

View File

@@ -0,0 +1,99 @@
{
config,
lib,
pkgs,
utils,
...
}:
with lib;
let
cfg = config.services.xserver.desktopManager.lxqt;
in
{
meta = {
maintainers = teams.lxqt.members;
};
options = {
services.xserver.desktopManager.lxqt.enable = mkEnableOption "the LXQt desktop manager";
services.xserver.desktopManager.lxqt.iconThemePackage =
lib.mkPackageOption pkgs [ "kdePackages" "breeze-icons" ] { }
// {
description = "The package that provides a default icon theme.";
};
services.xserver.desktopManager.lxqt.extraPackages = lib.mkOption {
type = with lib.types; listOf package;
default = [ ];
defaultText = lib.literalExpression "[ ]";
example = lib.literalExpression "with pkgs; [ xscreensaver ]";
description = "Extra packages to be installed system wide.";
};
environment.lxqt.excludePackages = mkOption {
type = with lib.types; listOf package;
default = [ ];
defaultText = lib.literalExpression "[ ]";
example = lib.literalExpression "with pkgs; [ lxqt.qterminal ]";
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
++ [ cfg.iconThemePackage ]
++ (utils.removePackagesByName pkgs.lxqt.optionalPackages config.environment.lxqt.excludePackages)
++ cfg.extraPackages;
# Link some extra directories in /run/current-system/software/share
environment.pathsToLink = [ "/share" ];
programs.gnupg.agent.pinentryPackage = mkDefault pkgs.pinentry-qt;
# virtual file systems support for PCManFM-QT
services.gvfs.enable = mkDefault true;
services.upower.enable = config.powerManagement.enable;
services.libinput.enable = mkDefault true;
xdg.portal.lxqt.enable = mkDefault true;
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1050804
xdg.portal.config.lxqt.default = mkDefault [
"lxqt"
"gtk"
];
};
}

View File

@@ -0,0 +1,124 @@
{
config,
lib,
pkgs,
utils,
...
}:
with lib;
let
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";
extraPanelApplets = mkOption {
default = [ ];
example = literalExpression "with pkgs.mate; [ mate-applets ]";
type = types.listOf types.package;
description = "Extra applets to add to mate-panel.";
};
extraCajaExtensions = mkOption {
default = [ ];
example = lib.literalExpression "with pkgs.mate; [ caja-extensions ]";
type = types.listOf types.package;
description = "Extra extensions to add to caja.";
};
enableWaylandSession = mkEnableOption "MATE Wayland session";
};
environment.mate.excludePackages = mkOption {
default = [ ];
example = literalExpression "[ pkgs.mate.mate-terminal pkgs.mate.pluma ]";
type = types.listOf types.package;
description = "Which MATE packages to exclude from the default environment";
};
};
config = mkMerge [
(mkIf (cfg.enable || cfg.enableWaylandSession) {
services.displayManager.sessionPackages = [
pkgs.mate.mate-session-manager
];
environment.extraInit = lib.optionalString config.services.gnome.gcr-ssh-agent.enable ''
# Hack: https://bugzilla.redhat.com/show_bug.cgi?id=2250704 still
# applies to sessions not managed by systemd.
if [ -z "$SSH_AUTH_SOCK" ] && [ -n "$XDG_RUNTIME_DIR" ]; then
export SSH_AUTH_SOCK="$XDG_RUNTIME_DIR/gcr/ssh"
fi
'';
# Debugging
environment.sessionVariables.MATE_SESSION_DEBUG = mkIf cfg.debug "1";
environment.systemPackages = utils.removePackagesByName (
pkgs.mate.basePackages
++ pkgs.mate.extraPackages
++ [
(pkgs.mate.caja-with-extensions.override {
extensions = cfg.extraCajaExtensions;
})
(pkgs.mate.mate-panel-with-applets.override {
applets = cfg.extraPanelApplets;
})
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/
pkgs.yelp # for 'Contents' in 'Help' menus
]
) config.environment.mate.excludePackages;
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.gnome.at-spi2-core.enable = true;
services.gnome.glib-networking.enable = true;
services.gnome.gnome-keyring.enable = true;
services.gnome.gcr-ssh-agent.enable = mkDefault true;
services.udev.packages = [ pkgs.mate.mate-settings-daemon ];
services.gvfs.enable = true;
services.upower.enable = config.powerManagement.enable;
services.libinput.enable = mkDefault true;
security.pam.services.mate-screensaver.unixAuth = true;
xdg.portal.configPackages = mkDefault [ pkgs.mate.mate-desktop ];
environment.pathsToLink = [ "/share" ];
})
(mkIf cfg.enableWaylandSession {
programs.wayfire.enable = true;
environment.sessionVariables.NIX_GSETTINGS_OVERRIDES_DIR = "${pkgs.mate.mate-gsettings-overrides}/share/gsettings-schemas/nixos-gsettings-overrides/glib-2.0/schemas";
environment.systemPackages = [ pkgs.mate.mate-wayland-session ];
services.displayManager.sessionPackages = [ pkgs.mate.mate-wayland-session ];
})
];
}

View File

@@ -0,0 +1,57 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
runXdgAutostart = config.services.xserver.desktopManager.runXdgAutostartIfNone;
in
{
options = {
services.xserver.desktopManager.runXdgAutostartIfNone = mkOption {
type = types.bool;
default = false;
description = ''
Whether to run XDG autostart files for sessions without a desktop manager
(with only a window manager), these sessions usually don't handle XDG
autostart files by default.
Some services like {option}`i18n.inputMethod` and
{option}`service.earlyoom` use XDG autostart files to start.
If this option is not set to `true` and you are using
a window manager without a desktop manager, you need to manually start
them or running `dex` somewhere.
'';
};
};
config = mkMerge [
{
services.xserver.desktopManager.session = [
{
name = "none";
start = optionalString runXdgAutostart ''
/run/current-system/systemd/bin/systemctl --user start xdg-autostart-if-no-desktop-manager.target
'';
}
];
}
(mkIf runXdgAutostart {
systemd.user.targets.xdg-autostart-if-no-desktop-manager = {
description = "Run XDG autostart files";
# From `plasma-workspace`, `share/systemd/user/plasma-workspace@.target`.
requires = [
"xdg-desktop-autostart.target"
"graphical-session.target"
];
before = [
"xdg-desktop-autostart.target"
"graphical-session.target"
];
bindsTo = [ "graphical-session.target" ];
};
})
];
}

View File

@@ -0,0 +1,254 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.xserver.desktopManager.phosh;
# Based on https://source.puri.sm/Librem5/librem5-base/-/blob/4596c1056dd75ac7f043aede07887990fd46f572/default/sm.puri.OSK0.desktop
oskItem = pkgs.makeDesktopItem {
name = "sm.puri.OSK0";
desktopName = "On-screen keyboard";
exec = "${pkgs.squeekboard}/bin/squeekboard";
categories = [
"GNOME"
"Core"
];
onlyShowIn = [ "GNOME" ];
noDisplay = true;
extraConfig = {
X-GNOME-Autostart-Phase = "Panel";
X-GNOME-Provides = "inputmethod";
X-GNOME-Autostart-Notify = "true";
X-GNOME-AutoRestart = "true";
};
};
phocConfigType = lib.types.submodule {
options = {
xwayland = lib.mkOption {
description = ''
Whether to enable XWayland support.
To start XWayland immediately, use `immediate`.
'';
type = lib.types.enum [
"true"
"false"
"immediate"
];
default = "false";
};
cursorTheme = lib.mkOption {
description = ''
Cursor theme to use in Phosh.
'';
type = lib.types.str;
default = "default";
};
outputs = lib.mkOption {
description = ''
Output configurations.
'';
type = lib.types.attrsOf phocOutputType;
default = {
DSI-1 = {
scale = 2;
};
};
};
};
};
phocOutputType = lib.types.submodule {
options = {
modeline = lib.mkOption {
description = ''
One or more modelines.
'';
type = lib.types.either lib.types.str (lib.types.listOf lib.types.str);
default = [ ];
example = [
"87.25 720 776 848 976 1440 1443 1453 1493 -hsync +vsync"
"65.13 768 816 896 1024 1024 1025 1028 1060 -HSync +VSync"
];
};
mode = lib.mkOption {
description = ''
Default video mode.
'';
type = lib.types.nullOr lib.types.str;
default = null;
example = "768x1024";
};
scale = lib.mkOption {
description = ''
Display scaling factor.
'';
type =
lib.types.nullOr (lib.types.addCheck (lib.types.either lib.types.int lib.types.float) (x: x > 0))
// {
description = "null or positive integer or float";
};
default = null;
example = 2;
};
rotate = lib.mkOption {
description = ''
Screen transformation.
'';
type = lib.types.enum [
"90"
"180"
"270"
"flipped"
"flipped-90"
"flipped-180"
"flipped-270"
null
];
default = null;
};
};
};
optionalKV = k: v: lib.optionalString (v != null) "${k} = ${builtins.toString v}";
renderPhocOutput =
name: output:
let
modelines = if builtins.isList output.modeline then output.modeline else [ output.modeline ];
renderModeline = l: "modeline = ${l}";
in
''
[output:${name}]
${lib.concatStringsSep "\n" (map renderModeline modelines)}
${optionalKV "mode" output.mode}
${optionalKV "scale" output.scale}
${optionalKV "rotate" output.rotate}
'';
renderPhocConfig =
phoc:
let
outputs = lib.mapAttrsToList renderPhocOutput phoc.outputs;
in
''
[core]
xwayland = ${phoc.xwayland}
${lib.concatStringsSep "\n" outputs}
[cursor]
theme = ${phoc.cursorTheme}
'';
in
{
options = {
services.xserver.desktopManager.phosh = {
enable = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable the Phone Shell.";
};
package = lib.mkPackageOption pkgs "phosh" { };
user = lib.mkOption {
description = "The user to run the Phosh service.";
type = lib.types.str;
example = "alice";
};
group = lib.mkOption {
description = "The group to run the Phosh service.";
type = lib.types.str;
example = "users";
};
phocConfig = lib.mkOption {
description = ''
Configurations for the Phoc compositor.
'';
type = lib.types.oneOf [
lib.types.lines
lib.types.path
phocConfigType
];
default = { };
};
};
};
config = lib.mkIf cfg.enable {
# Inspired by https://gitlab.gnome.org/World/Phosh/phosh/-/blob/main/data/phosh.service
systemd.services.phosh = {
wantedBy = [ "graphical.target" ];
serviceConfig = {
ExecStart = "${cfg.package}/bin/phosh-session";
User = cfg.user;
Group = cfg.group;
PAMName = "login";
WorkingDirectory = "~";
Restart = "always";
TTYPath = "/dev/tty7";
TTYReset = "yes";
TTYVHangup = "yes";
TTYVTDisallocate = "yes";
# Fail to start if not controlling the tty.
StandardInput = "tty-fail";
StandardOutput = "journal";
StandardError = "journal";
# Log this user with utmp, letting it show up with commands 'w' and 'who'.
UtmpIdentifier = "tty7";
UtmpMode = "user";
};
environment = {
# We are running without a display manager, so need to provide
# a value for XDG_CURRENT_DESKTOP.
#
# Among other things, this variable influences:
# - visibility of desktop entries with "OnlyShowIn=Phosh;"
# https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-1.5.html#key-onlyshowin
# - the chosen xdg-desktop-portal configuration.
# https://flatpak.github.io/xdg-desktop-portal/docs/portals.conf.html
XDG_CURRENT_DESKTOP = "Phosh:GNOME";
# pam_systemd uses these to identify the session in logind.
# https://www.freedesktop.org/software/systemd/man/latest/pam_systemd.html#desktop=
XDG_SESSION_DESKTOP = "phosh";
XDG_SESSION_TYPE = "wayland";
};
};
environment.systemPackages = [
pkgs.phoc
cfg.package
pkgs.squeekboard
oskItem
];
systemd.packages = [ cfg.package ];
programs.feedbackd.enable = true;
security.pam.services.phosh = { };
services.graphical-desktop.enable = true;
services.gnome.core-shell.enable = true;
services.gnome.core-os-services.enable = true;
services.displayManager.sessionPackages = [ cfg.package ];
environment.etc."phosh/phoc.ini".source =
if builtins.isPath cfg.phocConfig then
cfg.phocConfig
else if builtins.isString cfg.phocConfig then
pkgs.writeText "phoc.ini" cfg.phocConfig
else
pkgs.writeText "phoc.ini" (renderPhocConfig cfg.phocConfig);
};
}

View File

@@ -0,0 +1,48 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.desktopManager.retroarch;
in
{
options.services.xserver.desktopManager.retroarch = {
enable = mkEnableOption "RetroArch";
package = mkPackageOption pkgs "retroarch" {
example = "retroarch-full";
};
extraArgs = mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"--verbose"
"--host"
];
description = "Extra arguments to pass to RetroArch.";
};
};
config = mkIf cfg.enable {
services.xserver.desktopManager.session = [
{
name = "RetroArch";
start = ''
${cfg.package}/bin/retroarch -f ${escapeShellArgs cfg.extraArgs} &
waitPID=$!
'';
}
];
environment.systemPackages = [ cfg.package ];
};
meta.maintainers = with maintainers; [ j0hax ];
}

View File

@@ -0,0 +1,134 @@
{
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";
defaultText = literalExpression ''"''${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 `man 1 xset` 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 `man xmodmap` 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 `/etc/default/surf-display`.
'';
};
};
};
config = mkIf cfg.enable {
services.displayManager.sessionPackages = [
pkgs.surf-display
];
environment.etc."default/surf-display".text = surfDisplayConf;
};
}

View File

@@ -0,0 +1,249 @@
{
config,
lib,
pkgs,
utils,
...
}:
with lib;
let
cfg = config.services.xserver.desktopManager.xfce;
excludePackages = config.environment.xfce.excludePackages;
in
{
meta = {
maintainers = teams.xfce.members;
};
imports = [
# added 2019-08-18
# needed to preserve some semblance of UI familarity
# with original XFCE module
(mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "xfce4-14" "extraSessionCommands" ]
[ "services" "xserver" "displayManager" "sessionCommands" ]
)
# added 2019-11-04
# xfce4-14 module removed and promoted to xfce.
# Needed for configs that used xfce4-14 module to migrate to this one.
(mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "xfce4-14" "enable" ]
[ "services" "xserver" "desktopManager" "xfce" "enable" ]
)
(mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "xfce4-14" "noDesktop" ]
[ "services" "xserver" "desktopManager" "xfce" "noDesktop" ]
)
(mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "xfce4-14" "enableXfwm" ]
[ "services" "xserver" "desktopManager" "xfce" "enableXfwm" ]
)
(mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "xfce" "extraSessionCommands" ]
[ "services" "xserver" "displayManager" "sessionCommands" ]
)
(mkRemovedOptionModule [ "services" "xserver" "desktopManager" "xfce" "screenLock" ] "")
# added 2022-06-26
# thunar has its own module
(mkRenamedOptionModule
[ "services" "xserver" "desktopManager" "xfce" "thunarPlugins" ]
[ "programs" "thunar" "plugins" ]
)
];
options = {
services.xserver.desktopManager.xfce = {
enable = mkOption {
type = types.bool;
default = false;
description = "Enable the Xfce desktop environment.";
};
noDesktop = mkOption {
type = types.bool;
default = false;
description = "Don't install XFCE desktop components (xfdesktop and panel).";
};
enableXfwm = mkOption {
type = types.bool;
default = true;
description = "Enable the XFWM (default) window manager.";
};
enableScreensaver = mkOption {
type = types.bool;
default = true;
description = "Enable the XFCE screensaver.";
};
enableWaylandSession = mkEnableOption "the experimental Xfce Wayland session";
waylandSessionCompositor = mkOption {
type = lib.types.str;
default = "";
example = "wayfire";
description = ''
Command line to run a Wayland compositor, defaults to `labwc --startup`
if not specified. Note that `xfce4-session` will be passed to it as an
argument, see `startxfce4 --help` for details.
Some compositors do not have an option equivalent to labwc's `--startup`
and you might have to add xfce4-session somewhere in their configurations.
'';
};
};
environment.xfce.excludePackages = mkOption {
default = [ ];
example = literalExpression "[ pkgs.xfce.xfce4-volumed-pulse ]";
type = types.listOf types.package;
description = "Which packages XFCE should exclude from the default environment";
};
};
config = mkIf cfg.enable {
environment.systemPackages = utils.removePackagesByName (
with pkgs;
[
glib # for gsettings
gtk3.out # gtk-update-icon-cache
gnome-themes-extra
adwaita-icon-theme
hicolor-icon-theme
tango-icon-theme
xfce.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/
xfce.exo
xfce.garcon
xfce.libxfce4ui
xfce.mousepad
xfce.parole
xfce.ristretto
xfce.xfce4-appfinder
xfce.xfce4-notifyd
xfce.xfce4-screenshooter
xfce.xfce4-session
xfce.xfce4-settings
xfce.xfce4-taskmanager
xfce.xfce4-terminal
]
# TODO: NetworkManager doesn't belong here
++ lib.optional config.networking.networkmanager.enable networkmanagerapplet
++ lib.optional config.powerManagement.enable xfce.xfce4-power-manager
++ lib.optionals (config.services.pulseaudio.enable || config.services.pipewire.pulse.enable) [
pavucontrol
# volume up/down keys support:
# xfce4-pulseaudio-plugin includes all the functionalities of xfce4-volumed-pulse
# but can only be used with xfce4-panel, so for no-desktop usage we still include
# xfce4-volumed-pulse
(if cfg.noDesktop then xfce.xfce4-volumed-pulse else xfce.xfce4-pulseaudio-plugin)
]
++ lib.optionals cfg.enableXfwm [
xfce.xfwm4
xfce.xfwm4-themes
]
++ lib.optionals (!cfg.noDesktop) [
xfce.xfce4-panel
xfce.xfdesktop
]
++ lib.optional cfg.enableScreensaver xfce.xfce4-screensaver
) excludePackages;
programs.gnupg.agent.pinentryPackage = mkDefault pkgs.pinentry-gtk2;
programs.xfconf.enable = true;
programs.thunar.enable = true;
programs.labwc.enable = mkDefault (
cfg.enableWaylandSession
&& (cfg.waylandSessionCompositor == "" || lib.substring 0 5 cfg.waylandSessionCompositor == "labwc")
);
environment.pathsToLink = [
"/share/xfce4"
"/lib/xfce4"
"/share/gtksourceview-3.0"
"/share/gtksourceview-4.0"
];
services.xserver.desktopManager.session = [
{
name = "xfce";
prettyName = "Xfce Session";
desktopNames = [ "XFCE" ];
bgSupport = !cfg.noDesktop;
start = ''
${pkgs.runtimeShell} ${pkgs.xfce.xfce4-session.xinitrc} &
waitPID=$!
'';
}
];
# Copied from https://gitlab.xfce.org/xfce/xfce4-session/-/blob/xfce4-session-4.19.2/xfce-wayland.desktop.in
# to maintain consistent l10n state with X11 session file and to support the waylandSessionCompositor option.
services.displayManager.sessionPackages = optionals cfg.enableWaylandSession [
(
(pkgs.writeTextDir "share/wayland-sessions/xfce-wayland.desktop" ''
[Desktop Entry]
Version=1.0
Name=Xfce Session (Wayland)
Comment=Use this session to run Xfce as your desktop environment
Exec=startxfce4 --wayland ${cfg.waylandSessionCompositor}
Icon=
Type=Application
DesktopNames=XFCE
Keywords=xfce;wayland;desktop;environment;session;
'').overrideAttrs
(_: {
passthru.providedSessions = [ "xfce-wayland" ];
})
)
];
services.xserver.updateDbusEnvironment = true;
programs.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.gnome.glib-networking.enable = true;
services.gvfs.enable = true;
services.tumbler.enable = true;
services.system-config-printer.enable = (mkIf config.services.printing.enable (mkDefault true));
services.libinput.enable = mkDefault true; # used in xfce4-settings-manager
services.colord.enable = mkDefault true;
# 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 = utils.removePackagesByName (with pkgs.xfce; [
xfce4-notifyd
]) excludePackages;
security.pam.services.xfce4-screensaver.unixAuth = cfg.enableScreensaver;
xdg.portal.configPackages = mkDefault [ pkgs.xfce.xfce4-session ];
};
}

View File

@@ -0,0 +1,43 @@
{
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 = literalExpression ''versionOlder config.system.stateVersion "19.09" && config.services.xserver.enable;'';
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 ];
};
}

View File

@@ -0,0 +1,45 @@
{
accountsservice,
glib,
gobject-introspection,
python3,
wrapGAppsNoGuiHook,
lib,
}:
python3.pkgs.buildPythonApplication {
name = "set-session";
format = "other";
src = ./set-session.py;
dontUnpack = true;
strictDeps = false;
nativeBuildInputs = [
wrapGAppsNoGuiHook
gobject-introspection
];
buildInputs = [
accountsservice
glib
];
propagatedBuildInputs = with python3.pkgs; [
pygobject3
ordered-set
];
installPhase = ''
mkdir -p $out/bin
cp $src $out/bin/set-session
chmod +x $out/bin/set-session
'';
meta = with lib; {
maintainers = with maintainers; [ ] ++ teams.pantheon.members;
};
}

View File

@@ -0,0 +1,357 @@
# This module declares the options to define a *display manager*, the
# program responsible for handling X logins (such as LightDM, GDM, or SDDM).
# 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,
options,
pkgs,
...
}:
let
inherit (lib)
mkOption
types
literalExpression
optionalString
;
cfg = config.services.xserver;
xorg = pkgs.xorg;
fontconfig = config.fonts.fontconfig;
xresourcesXft = pkgs.writeText "Xresources-Xft" ''
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: ${fontconfig.hinting.style}
'';
# FIXME: this is an ugly hack.
# Some sessions (read: most WMs) don't activate systemd's `graphical-session.target`.
# Other sessions (read: most non-WMs) expect `graphical-session.target` to be reached
# when the entire session is actually ready. We used to just unconditionally force
# `graphical-session.target` to be activated in the session wrapper so things like
# xdg-autostart-generator work on sessions that are wrong, but this broke sessions
# that do things right. So, preserve this behavior (with some extra steps) by matching
# on XDG_CURRENT_DESKTOP and deliberately ignoring sessions we know can do the right thing.
fakeSession = action: ''
session_is_systemd_aware=$(
IFS=:
for i in $XDG_CURRENT_DESKTOP; do
case $i in
KDE|GNOME|Pantheon|X-NIXOS-SYSTEMD-AWARE) echo "1"; exit; ;;
*) ;;
esac
done
)
if [ -z "$session_is_systemd_aware" ]; then
/run/current-system/systemd/bin/systemctl --user ${action} nixos-fake-graphical-session.target
fi
'';
# file provided by services.xserver.displayManager.sessionData.wrapper
xsessionWrapper = pkgs.writeScript "xsession-wrapper" ''
#! ${pkgs.bash}/bin/bash
# Shared environment setup for graphical sessions.
. /etc/profile
if test -f ~/.profile; then
source ~/.profile
fi
cd "$HOME"
# Allow the user to execute commands at the beginning of the X session.
if test -f ~/.xprofile; then
source ~/.xprofile
fi
${optionalString config.services.displayManager.logToJournal ''
if [ -z "$_DID_SYSTEMD_CAT" ]; then
export _DID_SYSTEMD_CAT=1
exec ${config.systemd.package}/bin/systemd-cat -t xsession "$0" "$@"
fi
''}
${optionalString config.services.displayManager.logToFile ''
exec &> >(tee ~/.xsession-errors)
''}
# 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
# Import environment variables into the systemd user environment.
${optionalString (cfg.displayManager.importedVariables != [ ]) (
"/run/current-system/systemd/bin/systemctl --user import-environment "
+ toString (lib.unique cfg.displayManager.importedVariables)
)}
# Speed up application start by 50-150ms according to
# https://kdemonkey.blogspot.com/2008/04/magic-trick.html
compose_cache="''${XCOMPOSECACHE:-$HOME/.compose-cache}"
mkdir -p "$compose_cache"
# To avoid accidentally deleting a wrongly set up XCOMPOSECACHE directory,
# defensively try to delete cache *files* only, following the file format specified in
# https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/master/modules/im/ximcp/imLcIm.c#L353-358
# sprintf (*res, "%s/%c%d_%03x_%08x_%08x", dir, _XimGetMyEndian(), XIM_CACHE_VERSION, (unsigned int)sizeof (DefTree), hash, hash2);
${pkgs.findutils}/bin/find "$compose_cache" -maxdepth 1 -regextype posix-extended -regex '.*/[Bl][0-9]+_[0-9a-f]{3}_[0-9a-f]{8}_[0-9a-f]{8}' -delete
unset compose_cache
# Work around KDE errors when a user first logs in and
# .local/share doesn't exist yet.
mkdir -p "''${XDG_DATA_HOME:-$HOME/.local/share}"
unset _DID_SYSTEMD_CAT
${cfg.displayManager.sessionCommands}
${fakeSession "start"}
# 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
# TODO: Do we need this? Should not the session always exist?
echo "error: unknown session $1" 1>&2
exit 1
fi
'';
in
{
options = {
services.xserver.displayManager = {
xauthBin = mkOption {
internal = true;
default = "${xorg.xauth}/bin/xauth";
defaultText = literalExpression ''"''${pkgs.xorg.xauth}/bin/xauth"'';
description = "Path to the {command}`xauth` 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.
'';
};
session = mkOption {
default = [ ];
type = types.listOf types.attrs;
example = literalExpression ''
[ { 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
{var}`waitPID` 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
{var}`manage` either to `"window"`
or `"desktop"`.
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.
'';
};
importedVariables = mkOption {
type = types.listOf (types.strMatching "[a-zA-Z_][a-zA-Z0-9_]*");
visible = false;
description = ''
Environment variables to import into the systemd user environment.
'';
};
};
};
config = {
services.displayManager.sessionData.wrapper = xsessionWrapper;
services.xserver.displayManager.xserverBin = "${xorg.xorgserver.out}/bin/X";
services.xserver.displayManager.importedVariables = [
# This is required by user units using the session bus.
"DBUS_SESSION_BUS_ADDRESS"
# These are needed by the ssh-agent unit.
"DISPLAY"
"XAUTHORITY"
# This is required to specify session within user units (e.g. loginctl lock-session).
"XDG_SESSION_ID"
];
systemd.user.targets.nixos-fake-graphical-session = {
unitConfig = {
Description = "Fake graphical-session target for non-systemd-aware sessions";
BindsTo = "graphical-session.target";
};
};
# Create desktop files and scripts for starting sessions for WMs/DMs
# that do not have upstream session files (those defined using services.{display,desktop,window}Manager.session options).
services.displayManager.sessionPackages =
let
dms = lib.filter (s: s.manage == "desktop") cfg.displayManager.session;
wms = lib.filter (s: s.manage == "window") cfg.displayManager.session;
# Script responsible for starting the window manager and the desktop manager.
xsession =
dm: wm:
pkgs.writeScript "xsession" ''
#! ${pkgs.bash}/bin/bash
# Legacy session script used to construct .desktop files from
# `services.xserver.displayManager.session` entries. Called from
# `sessionWrapper`.
# Start the window manager.
${wm.start}
# Start the desktop manager.
${dm.start}
${optionalString cfg.updateDbusEnvironment ''
${lib.getBin pkgs.dbus}/bin/dbus-update-activation-environment --systemd --all
''}
test -n "$waitPID" && wait "$waitPID"
${fakeSession "stop"}
exit 0
'';
in
# We will generate every possible pair of WM and DM.
lib.concatLists (
lib.mapCartesianProduct
(
{ dm, wm }:
let
sessionName = "${dm.name}${optionalString (wm.name != "none") ("+" + wm.name)}";
prettyName =
if dm.name != "none" then
"${dm.prettyName or dm.name}${
optionalString (wm.name != "none") (" (" + (wm.prettyName or wm.name) + ")")
}"
else
(wm.prettyName or wm.name);
script = xsession dm wm;
desktopNames = if dm ? desktopNames then lib.concatStringsSep ";" dm.desktopNames else sessionName;
in
lib.optional (dm.name != "none" || wm.name != "none") (
pkgs.writeTextFile {
name = "${sessionName}-xsession";
destination = "/share/xsessions/${sessionName}.desktop";
# Desktop Entry Specification:
# - https://standards.freedesktop.org/desktop-entry-spec/latest/
# - https://standards.freedesktop.org/desktop-entry-spec/latest/ar01s06.html
text = ''
[Desktop Entry]
Version=1.0
Type=XSession
TryExec=${script}
Exec=${script}
Name=${prettyName}
DesktopNames=${desktopNames}
'';
}
// {
providedSessions = [ sessionName ];
}
)
)
{
dm = dms;
wm = wms;
}
);
};
imports = [
(lib.mkRemovedOptionModule
[ "services" "xserver" "displayManager" "desktopManagerHandlesLidAndPower" ]
"The option is no longer necessary because all display managers have already delegated lid management to systemd."
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "displayManager" "job" "logsXsession" ]
[ "services" "displayManager" "logToFile" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "displayManager" "logToJournal" ]
[ "services" "displayManager" "logToJournal" ]
)
(lib.mkRenamedOptionModule
[ "services" "xserver" "displayManager" "extraSessionFilesPackages" ]
[ "services" "displayManager" "sessionPackages" ]
)
];
}

View File

@@ -0,0 +1,122 @@
{
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 = mkPackageOption pkgs "gnome-themes-extra" { };
name = mkOption {
type = types.str;
default = "Adwaita";
description = ''
Name of the theme to use for the lightdm-enso-os-greeter
'';
};
};
iconTheme = {
package = mkPackageOption pkgs "papirus-icon-theme" { };
name = mkOption {
type = types.str;
default = "ePapirus";
description = ''
Name of the icon theme to use for the lightdm-enso-os-greeter
'';
};
};
cursorTheme = {
package = mkPackageOption pkgs "capitaine-cursors" { };
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;
};
};
};
};
}

View File

@@ -0,0 +1,166 @@
{
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 = mkPackageOption pkgs "gnome-themes-extra" { };
name = mkOption {
type = types.str;
default = "Adwaita";
description = ''
Name of the theme to use for the lightdm-gtk-greeter.
'';
};
};
iconTheme = {
package = mkPackageOption pkgs "adwaita-icon-theme" { };
name = mkOption {
type = types.str;
default = "Adwaita";
description = ''
Name of the icon theme to use for the lightdm-gtk-greeter.
'';
};
};
cursorTheme = {
package = mkPackageOption pkgs "adwaita-icon-theme" { };
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;
};
}

View File

@@ -0,0 +1,42 @@
{
config,
lib,
pkgs,
...
}:
let
dmcfg = config.services.displayManager;
ldmcfg = config.services.xserver.displayManager.lightdm;
cfg = ldmcfg.greeters.lomiri;
in
{
meta.maintainers = lib.teams.lomiri.members;
options = {
services.xserver.displayManager.lightdm.greeters.lomiri = {
enable = lib.mkEnableOption "lomiri's greeter as the lightdm greeter";
};
};
config = lib.mkIf (ldmcfg.enable && cfg.enable) {
# Lomiri greeter == Lomiri shell in special mode, need some basics setup at least
services.desktopManager.lomiri.basics = true;
services.xserver.displayManager.lightdm.greeters.gtk.enable = false;
services.xserver.displayManager.lightdm.greeter = lib.mkDefault {
package = pkgs.lomiri.lomiri.greeter;
name = "lomiri-greeter";
};
# Greeter needs to be run through its wrapper
# Greeter doesn't work with our set-session.py script, need to set default user-session
services.xserver.displayManager.lightdm.extraSeatDefaults = ''
greeter-wrapper = ${lib.getExe' pkgs.lomiri.lomiri "lomiri-greeter-wrapper"}
user-session = ${dmcfg.defaultSession}
'';
};
}

View File

@@ -0,0 +1,104 @@
{
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:
invalid-password-text = Invalid Password
show-input-cursor = true
password-alignment = right
[greeter-hotkeys]
mod-key = meta
shutdown-key = s
restart-key = r
hibernate-key = h
suspend-key = u
[greeter-theme]
font = Sans
font-size = 1em
font-weight = bold
font-style = normal
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"
password-border-color = "#080800"
password-border-width = 2px
${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 using
[](#opt-services.displayManager.defaultSession).
'';
};
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;
};
}

View File

@@ -0,0 +1,29 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
dmcfg = config.services.xserver.displayManager;
ldmcfg = dmcfg.lightdm;
cfg = ldmcfg.greeters.mobile;
in
{
options = {
services.xserver.displayManager.lightdm.greeters.mobile = {
enable = mkEnableOption "lightdm-mobile-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.lightdm-mobile-greeter.xgreeters;
name = "lightdm-mobile-greeter";
};
};
}

View File

@@ -0,0 +1,56 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
dmcfg = config.services.xserver.displayManager;
ldmcfg = dmcfg.lightdm;
cfg = ldmcfg.greeters.pantheon;
in
{
meta = with lib; {
maintainers = with maintainers; [ ] ++ teams.pantheon.members;
};
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";
};
# Show manual login card.
services.xserver.displayManager.lightdm.extraSeatDefaults = "greeter-show-manual-login=true";
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.allowed".source =
"${pkgs.pantheon.elementary-default-settings}/etc/wingpanel.d/io.elementary.greeter.allowed";
};
}

View File

@@ -0,0 +1,126 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
ldmcfg = config.services.xserver.displayManager.lightdm;
cfg = ldmcfg.greeters.slick;
inherit (pkgs) writeText;
theme = cfg.theme.package;
icons = cfg.iconTheme.package;
font = cfg.font.package;
cursors = cfg.cursorTheme.package;
slickGreeterConf = writeText "slick-greeter.conf" ''
[Greeter]
background=${ldmcfg.background}
theme-name=${cfg.theme.name}
icon-theme-name=${cfg.iconTheme.name}
font-name=${cfg.font.name}
cursor-theme-name=${cfg.cursorTheme.name}
cursor-theme-size=${toString cfg.cursorTheme.size}
draw-user-backgrounds=${boolToString cfg.draw-user-backgrounds}
${cfg.extraConfig}
'';
in
{
options = {
services.xserver.displayManager.lightdm.greeters.slick = {
enable = mkEnableOption "lightdm-slick-greeter as the lightdm greeter";
theme = {
package = mkPackageOption pkgs "gnome-themes-extra" { };
name = mkOption {
type = types.str;
default = "Adwaita";
description = ''
Name of the theme to use for the lightdm-slick-greeter.
'';
};
};
iconTheme = {
package = mkPackageOption pkgs "adwaita-icon-theme" { };
name = mkOption {
type = types.str;
default = "Adwaita";
description = ''
Name of the icon theme to use for the lightdm-slick-greeter.
'';
};
};
font = {
package = mkPackageOption pkgs "ubuntu-classic" { };
name = mkOption {
type = types.str;
default = "Ubuntu 11";
description = ''
Name of the font to use.
'';
};
};
cursorTheme = {
package = mkPackageOption pkgs "adwaita-icon-theme" { };
name = mkOption {
type = types.str;
default = "Adwaita";
description = ''
Name of the cursor theme to use for the lightdm-slick-greeter.
'';
};
size = mkOption {
type = types.int;
default = 24;
description = ''
Size of the cursor theme to use for the lightdm-slick-greeter.
'';
};
};
draw-user-backgrounds = mkEnableOption "draw user backgrounds";
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Extra configuration that should be put in the lightdm-slick-greeter.conf
configuration file.
'';
};
};
};
config = mkIf (ldmcfg.enable && cfg.enable) {
services.xserver.displayManager.lightdm = {
greeters.gtk.enable = false;
greeter = mkDefault {
package = pkgs.lightdm-slick-greeter.xgreeters;
name = "lightdm-slick-greeter";
};
};
environment.systemPackages = [
cursors
icons
theme
];
fonts.packages = [ font ];
environment.etc."lightdm/slick-greeter.conf".source = slickGreeterConf;
};
}

View File

@@ -0,0 +1,94 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
dmcfg = config.services.xserver.displayManager;
ldmcfg = dmcfg.lightdm;
cfg = ldmcfg.greeters.tiny;
in
{
options = {
services.xserver.displayManager.lightdm.greeters.tiny = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether to enable lightdm-tiny-greeter as the lightdm greeter.
Note that this greeter starts only the default X session.
You can configure the default X session using
[](#opt-services.displayManager.defaultSession).
'';
};
label = {
user = mkOption {
type = types.str;
default = "Username";
description = ''
The string to represent the user_text label.
'';
};
pass = mkOption {
type = types.str;
default = "Password";
description = ''
The string to represent the pass_text label.
'';
};
};
extraConfig = mkOption {
type = types.lines;
default = "";
description = ''
Section to describe style and ui.
'';
};
};
};
config = mkIf (ldmcfg.enable && cfg.enable) {
services.xserver.displayManager.lightdm.greeters.gtk.enable = false;
services.xserver.displayManager.lightdm.greeter =
let
configHeader = ''
#include <gtk/gtk.h>
static const char *user_text = "${cfg.label.user}";
static const char *pass_text = "${cfg.label.pass}";
static const char *session = "${dmcfg.defaultSession}";
'';
config = optionalString (cfg.extraConfig != "") (configHeader + cfg.extraConfig);
package = pkgs.lightdm-tiny-greeter.override { conf = config; };
in
mkDefault {
package = package.xgreeters;
name = "lightdm-tiny-greeter";
};
assertions = [
{
assertion = dmcfg.defaultSession != null;
message = ''
Please set: services.displayManager.defaultSession
'';
}
];
};
}

View File

@@ -0,0 +1,334 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
xcfg = config.services.xserver;
dmcfg = config.services.displayManager;
xEnv = config.systemd.services.display-manager.environment;
cfg = xcfg.displayManager.lightdm;
sessionData = dmcfg.sessionData;
setSessionScript = pkgs.callPackage ./account-service-util.nix { };
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 ${xcfg.displayManager.xserverBin} ${toString xcfg.displayManager.xserverArgs} $additionalArgs "$@"
'';
usersConf = writeText "users.conf" ''
[UserList]
minimum-uid=1000
hidden-users=${concatStringsSep " " dmcfg.hiddenUsers}
hidden-shells=/run/current-system/sw/bin/nologin
'';
lightdmConf = writeText "lightdm.conf" ''
[LightDM]
minimum-vt = 1
${optionalString cfg.greeter.enable ''
greeter-user = ${config.users.users.lightdm.name}
greeters-directory = ${cfg.greeter.package}
''}
sessions-directory = ${dmcfg.sessionData.desktops}/share/xsessions:${dmcfg.sessionData.desktops}/share/wayland-sessions
${cfg.extraConfig}
[Seat:*]
xserver-command = ${xserverWrapper}
session-wrapper = ${dmcfg.sessionData.wrapper}
${optionalString cfg.greeter.enable ''
greeter-session = ${cfg.greeter.name}
''}
${optionalString dmcfg.autoLogin.enable ''
autologin-user = ${dmcfg.autoLogin.user}
autologin-user-timeout = ${toString cfg.autoLogin.timeout}
autologin-session = ${sessionData.autologinSession}
''}
${optionalString (xcfg.displayManager.setupCommands != "") ''
display-setup-script=${pkgs.writeScript "lightdm-display-setup" ''
#!${pkgs.bash}/bin/bash
${xcfg.displayManager.setupCommands}
''}
''}
${cfg.extraSeatDefaults}
'';
in
{
meta = with lib; {
maintainers = with maintainers; [ ] ++ teams.pantheon.members;
};
# 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
./lightdm-greeters/lomiri.nix
./lightdm-greeters/tiny.nix
./lightdm-greeters/slick.nix
./lightdm-greeters/mobile.nix
(mkRenamedOptionModule
[ "services" "xserver" "displayManager" "lightdm" "autoLogin" "enable" ]
[
"services"
"displayManager"
"autoLogin"
"enable"
]
)
(mkRenamedOptionModule
[ "services" "xserver" "displayManager" "lightdm" "autoLogin" "user" ]
[
"services"
"displayManager"
"autoLogin"
"user"
]
)
];
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.either types.path (types.strMatching "^#[0-9]{6}$");
# Manual cannot depend on packages, we are actually setting the default in config below.
defaultText = literalExpression "pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath";
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.";
};
# Configuration for automatic login specific to LightDM
autoLogin.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 = dmcfg.autoLogin.enable -> sessionData.autologinSession != null;
message = ''
LightDM auto-login requires that services.displayManager.defaultSession is set.
'';
}
{
assertion = !cfg.greeter.enable -> (dmcfg.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.
'';
}
];
# Keep in sync with the defaultText value from the option definition.
services.xserver.displayManager.lightdm.background =
mkDefault pkgs.nixos-artwork.wallpapers.simple-dark-gray-bottom.gnomeFilePath;
# Set default session in session chooser to a specified values basically ignore session history.
# Auto-login is already covered by a config value.
services.displayManager.preStart =
optionalString (!dmcfg.autoLogin.enable && dmcfg.defaultSession != null)
''
${setSessionScript}/bin/set-session ${dmcfg.defaultSession}
'';
# setSessionScript needs session-files in XDG_DATA_DIRS
services.displayManager.environment.XDG_DATA_DIRS = "${dmcfg.sessionData.desktops}/share/";
# setSessionScript wants AccountsService
systemd.services.display-manager.wants = [
"accounts-daemon.service"
];
# lightdm relaunches itself via just `lightdm`, so needs to be on the PATH
services.displayManager.execCmd = ''
export PATH=${lightdm}/sbin:$PATH
exec ${lightdm}/sbin/lightdm
'';
# Pull in dependencies of services we replace.
systemd.services.display-manager.after = [
"rc-local.service"
"systemd-machined.service"
"systemd-user-sessions.service"
"user.slice"
];
# user.slice needs to be present
systemd.services.display-manager.requires = [
"user.slice"
];
# lightdm stops plymouth so when it fails make sure plymouth stops.
systemd.services.display-manager.onFailure = [
"plymouth-quit.service"
];
systemd.services.display-manager.serviceConfig = {
BusName = "org.freedesktop.DisplayManager";
IgnoreSIGPIPE = "no";
# This allows lightdm to pass the LUKS password through to PAM.
# login keyring is unlocked automatic when autologin is used.
KeyringMode = "shared";
KillMode = "mixed";
StandardError = "inherit";
};
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.polkit.enable = true;
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=/etc/pam/environment readenv=0
session optional ${config.systemd.package}/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 yescrypt
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 -"
"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.display = null; # We specify our own display (and logfile) in xserver-wrapper up there
};
}

View File

@@ -0,0 +1,89 @@
#!/usr/bin/env python
import gi, argparse, os, logging, sys
gi.require_version("AccountsService", "1.0")
from gi.repository import AccountsService, GLib
from ordered_set import OrderedSet
def get_session_file(session):
system_data_dirs = GLib.get_system_data_dirs()
session_dirs = OrderedSet(
os.path.join(data_dir, session)
for data_dir in system_data_dirs
for session in {"wayland-sessions", "xsessions"}
)
session_files = OrderedSet(
os.path.join(dir, session + ".desktop")
for dir in session_dirs
if os.path.exists(os.path.join(dir, session + ".desktop"))
)
# Deal with duplicate wayland-sessions and xsessions.
# Needed for the situation in gnome-session, where there's
# a xsession named the same as a wayland session.
if any(map(is_session_wayland, session_files)):
session_files = OrderedSet(
session for session in session_files if is_session_wayland(session)
)
else:
session_files = OrderedSet(
session for session in session_files if is_session_xsession(session)
)
if len(session_files) == 0:
logging.warning("No session files are found.")
sys.exit(0)
else:
return session_files[0]
def is_session_xsession(session_file):
return "/xsessions/" in session_file
def is_session_wayland(session_file):
return "/wayland-sessions/" in session_file
def main():
parser = argparse.ArgumentParser(
description="Set session type for all normal users."
)
parser.add_argument("session", help="Name of session to set.")
args = parser.parse_args()
session = getattr(args, "session")
session_file = get_session_file(session)
user_manager = AccountsService.UserManager.get_default()
users = user_manager.list_users()
for user in users:
if user.is_system_account():
continue
else:
if is_session_wayland(session_file):
logging.debug(
f"Setting session name: {session}, as we found the existing wayland-session: {session_file}"
)
user.set_session(session)
user.set_session_type("wayland")
elif is_session_xsession(session_file):
logging.debug(
f"Setting session name: {session}, as we found the existing xsession: {session_file}"
)
user.set_x_session(session)
user.set_session(session)
user.set_session_type("x11")
else:
logging.error(f"Couldn't figure out session type for {session_file}")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,21 @@
{
config,
lib,
pkgs,
...
}:
with lib;
{
# added 2019-11-11
imports = [
(mkRemovedOptionModule [ "services" "xserver" "displayManager" "slim" ] ''
The SLIM project is abandoned and their last release was in 2013.
Because of this it poses a security risk to your system.
Other issues include it not fully supporting systemd and logind sessions.
Please use a different display manager such as LightDM, SDDM, or GDM.
You can also use the startx module which uses Xinitrc.
'')
];
}

View File

@@ -0,0 +1,107 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.xserver.displayManager.startx;
# WM session script
# Note: this assumes a single WM has been enabled
sessionScript = lib.concatMapStringsSep "\n" (
i: i.start
) config.services.xserver.windowManager.session;
in
{
###### interface
options = {
services.xserver.displayManager.startx = {
enable = lib.mkOption {
type = lib.types.bool;
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
virtual terminal.
::: {.note}
The X server will run under the current user, not as root.
:::
'';
};
generateScript = lib.mkOption {
type = lib.types.bool;
default = false;
description = ''
Whether to generate the system-wide xinitrc script (/etc/X11/xinit/xinitrc).
This script will take care of setting up the session for systemd user
services, running the window manager and cleaning up on exit.
::: {.note}
This script will only be used by `startx` when both `.xinitrc` does not
exists and the `XINITRC` environment variable is unset.
:::
'';
};
extraCommands = lib.mkOption {
type = lib.types.lines;
default = "";
description = ''
Shell commands to be added to the system-wide xinitrc script.
'';
};
};
};
###### implementation
config = lib.mkIf cfg.enable {
services.xserver.exportConfiguration = true;
# Other displayManagers log to /dev/null because they're services and put
# Xorg's stdout in the journal
#
# To send log to Xorg's default log location ($XDG_DATA_HOME/xorg/), we do
# not specify a log file when running X
services.xserver.logFile = lib.mkDefault null;
# Implement xserverArgs via xinit's system-wide xserverrc
environment.etc."X11/xinit/xserverrc".source = pkgs.writeShellScript "xserverrc" ''
exec ${pkgs.xorg.xorgserver}/bin/X \
${toString config.services.xserver.displayManager.xserverArgs} "$@"
'';
# Add a sane system-wide xinitrc script
environment.etc."X11/xinit/xinitrc" = lib.mkIf cfg.generateScript {
source = pkgs.writeShellScript "xinitrc" ''
${cfg.extraCommands}
# start user services
systemctl --user import-environment DISPLAY XDG_SESSION_ID
systemctl --user start nixos-fake-graphical-session.target
# run the window manager script
${sessionScript}
wait $waitPID
# stop services and all subprocesses
systemctl --user stop nixos-fake-graphical-session.target
kill 0
'';
};
environment.systemPackages = with pkgs; [ xorg.xinit ];
};
}

View File

@@ -0,0 +1,57 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.xserver.displayManager.sx;
in
{
options = {
services.xserver.displayManager.sx = {
enable = lib.mkEnableOption "" // {
description = ''
Whether to enable the "sx" pseudo-display manager, which allows users
to start manually via the "sx" command from a vt shell. The X server
runs under the user's id, not as root. The user must provide a
~/.config/sx/sxrc file containing session startup commands, see
{manpage}`sx(1)`. This is not automatically generated from the desktopManager
and windowManager settings. sx doesn't have a way to directly set
X server flags, but it can be done by overriding its xorgserver
dependency.
'';
};
addAsSession = lib.mkEnableOption "" // {
description = ''
Whether to add sx as a display manager session. Keep in mind that sx
expects to be run from a TTY, so it may not work in your display
manager.
'';
};
package = lib.mkPackageOption pkgs "sx" { };
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
services = {
displayManager.sessionPackages = lib.optionals cfg.addAsSession [ cfg.package ];
xserver = {
exportConfiguration = true;
logFile = lib.mkDefault null;
};
};
};
meta.maintainers = with lib.maintainers; [
figsoda
thiagokokada
];
}

View File

@@ -0,0 +1,333 @@
{
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";
};
desktop = mkOption {
type = types.nullOr types.str;
default = null;
example = "gnome-shell";
description = "Start a desktop environment instead of seamless mode";
};
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:
# https://www.x.org/archive/X11R7.5/doc/man/man1/cvt.1.html
# xtiming:
# https://xtiming.sourceforge.net/cgi-bin/xtiming.pl
# gtf:
# https://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.displayManager.execCmd = ''
${optionalString (cfg.pulseaudio) "export PULSE_COOKIE=/run/pulse/.config/pulse/cookie"}
exec ${pkgs.xpra}/bin/xpra ${
if cfg.desktop == null then "start" else "start-desktop --start=${cfg.desktop}"
} \
--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 ];
services.pulseaudio.enable = mkDefault cfg.pulseaudio;
services.pulseaudio.systemWide = mkDefault cfg.pulseaudio;
};
}

View File

@@ -0,0 +1,156 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
layouts = config.services.xserver.xkb.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 `xkb_compat "name" { ... }` 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 `xkb_geometry "name" { ... }` 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 `xkb_keycodes "name" { ... }` 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
`xkb_symbols "name" { ... }` 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 `xkb_types "name" { ... }` block.
'';
};
};
};
xkb_patched = pkgs.xorg.xkeyboardconfig_custom {
layouts = config.services.xserver.xkb.extraLayouts;
};
in
{
imports = [
(lib.mkRenamedOptionModuleWith {
sinceRelease = 2311;
from = [
"services"
"xserver"
"extraLayouts"
];
to = [
"services"
"xserver"
"xkb"
"extraLayouts"
];
})
];
###### interface
options.services.xserver.xkb = {
extraLayouts = mkOption {
type = types.attrsOf (types.submodule layoutOpts);
default = { };
example = literalExpression ''
{
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:
<https://www.x.org/releases/current/doc/xorg-docs/input/XKB-Enhancing.html#Defining_New_Layouts>.
For more examples see
<https://wiki.archlinux.org/index.php/X_KeyBoard_extension#Basic_examples>
'';
};
};
###### implementation
config = mkIf (layouts != { }) {
environment.sessionVariables = {
# runtime override supported by multiple libraries e. g. libxkbcommon
# https://xkbcommon.org/doc/current/group__include-path.html
XKB_CONFIG_ROOT = config.services.xserver.xkb.dir;
};
services.xserver = {
xkb.dir = "${xkb_patched}/etc/X11/xkb";
exportConfiguration =
config.services.xserver.displayManager.startx.enable
|| config.services.xserver.displayManager.sx.enable;
};
};
}

View File

@@ -0,0 +1,42 @@
{
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}";
};
}

View File

@@ -0,0 +1,114 @@
{
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 <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.libinput.enable;
message = ''
cmt and libinput are incompatible, meaning you cannot enable them both.
To use cmt you need to disable libinput with `services.libinput.enable = false`
If you haven't enabled it in configuration.nix, it's enabled by default on a
different xserver module.
'';
}
];
};
}

View File

@@ -0,0 +1,42 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.digimend;
pkg = config.boot.kernelPackages.digimend;
in
{
options = {
services.xserver.digimend = {
enable = mkEnableOption "the digimend drivers for Huion/XP-Pen/etc. tablets";
};
};
config = mkIf cfg.enable {
# digimend drivers use xsetwacom and wacom X11 drivers
services.xserver.wacom.enable = true;
boot.extraModulePackages = [ pkg ];
environment.etc."X11/xorg.conf.d/50-digimend.conf".source =
"${pkg}/usr/share/X11/xorg.conf.d/50-digimend.conf";
};
}

View File

@@ -0,0 +1,248 @@
{
config,
lib,
options,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.synaptics;
opt = options.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.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;
defaultText = literalExpression "config.${opt.twoFingerScroll}";
description = "Whether to enable horizontal two-finger drag-scrolling.";
};
vertTwoFingerScroll = mkOption {
type = types.bool;
default = cfg.twoFingerScroll;
defaultText = literalExpression "config.${opt.twoFingerScroll}";
description = "Whether to enable vertical two-finger drag-scrolling.";
};
horizEdgeScroll = mkOption {
type = types.bool;
default = !cfg.horizTwoFingerScroll;
defaultText = literalExpression "! config.${opt.horizTwoFingerScroll}";
description = "Whether to enable horizontal edge drag-scrolling.";
};
vertEdgeScroll = mkOption {
type = types.bool;
default = !cfg.vertTwoFingerScroll;
defaultText = literalExpression "! config.${opt.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.libinput.enable;
message = "Synaptics and libinput are incompatible, you cannot enable both.";
}
];
};
}

View File

@@ -0,0 +1,53 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.wacom;
in
{
options = {
services.xserver.wacom = {
enable = mkOption {
type = types.bool;
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"` 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";
};
}

View File

@@ -0,0 +1,79 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.imwheel;
in
{
options = {
services.xserver.imwheel = {
enable = mkEnableOption "IMWheel service";
extraOptions = mkOption {
type = types.listOf types.str;
default = [ "--buttons=45" ];
example = [ "--debug" ];
description = ''
Additional command-line arguments to pass to
{command}`imwheel`.
'';
};
rules = mkOption {
type = types.attrsOf types.str;
default = { };
example = literalExpression ''
{
".*" = '''
None, Up, Button4, 8
None, Down, Button5, 8
Shift_L, Up, Shift_L|Button4, 4
Shift_L, Down, Shift_L|Button5, 4
Control_L, Up, Control_L|Button4
Control_L, Down, Control_L|Button5
''';
}
'';
description = ''
Window class translation rules.
/etc/X11/imwheelrc is generated based on this config
which means this config is global for all users.
See [official man pages](https://imwheel.sourceforge.net/imwheel.1.html)
for more information.
'';
};
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ pkgs.imwheel ];
environment.etc."X11/imwheel/imwheelrc".source = pkgs.writeText "imwheelrc" (
concatStringsSep "\n\n" (mapAttrsToList (rule: conf: "\"${rule}\"\n${conf}") cfg.rules)
);
systemd.user.services.imwheel = {
description = "imwheel service";
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
serviceConfig = {
ExecStart =
"${pkgs.imwheel}/bin/imwheel "
+ escapeShellArgs (
[
"--detach"
"--kill"
]
++ cfg.extraOptions
);
ExecStop = "${pkgs.procps}/bin/pkill imwheel";
RestartSec = 3;
Restart = "always";
};
};
};
}

View File

@@ -0,0 +1,385 @@
{
config,
lib,
options,
pkgs,
...
}:
with lib;
let
cfg = config.services.picom;
opt = options.services.picom;
pairOf =
x:
with types;
addCheck (listOf x) (y: length y == 2) // { description = "pair of ${x.description}"; };
mkDefaultAttrs = mapAttrs (n: v: mkDefault v);
# Basically a tinkered lib.generators.mkKeyValueDefault
# It either serializes a top-level definition "key: { values };"
# or an expression "key = { values };"
mkAttrsString =
top:
mapAttrsToList (
k: v:
let
sep = if (top && isAttrs v) then ":" else "=";
in
"${escape [ sep ] k}${sep}${mkValueString v};"
);
# This serializes a Nix expression to the libconfig format.
mkValueString =
v:
if types.bool.check v then
boolToString v
else if types.int.check v then
toString v
else if types.float.check v then
toString v
else if types.str.check v then
"\"${escape [ "\"" ] v}\""
else if builtins.isList v then
"[ ${concatMapStringsSep " , " mkValueString v} ]"
else if types.attrs.check v then
"{ ${concatStringsSep " " (mkAttrsString false v)} }"
else
throw ''
invalid expression used in option services.picom.settings:
${v}
'';
toConf = attrs: concatStringsSep "\n" (mkAttrsString true cfg.settings);
configFile = pkgs.writeText "picom.conf" (toConf cfg.settings);
in
{
imports = [
(mkAliasOptionModuleMD [ "services" "compton" ] [ "services" "picom" ])
(mkRemovedOptionModule [ "services" "picom" "refreshRate" ] ''
This option corresponds to `refresh-rate`, which has been unused
since picom v6 and was subsequently removed by upstream.
See https://github.com/yshui/picom/commit/bcbc410
'')
(mkRemovedOptionModule [ "services" "picom" "experimentalBackends" ] ''
This option was removed by upstream since picom v10.
'')
];
options.services.picom = {
enable = mkOption {
type = types.bool;
default = false;
description = ''
Whether or not to enable Picom as the X.org composite manager.
'';
};
package = mkPackageOption pkgs "picom" { };
fade = mkOption {
type = types.bool;
default = false;
description = ''
Fade windows in and out.
'';
};
fadeDelta = mkOption {
type = types.ints.positive;
default = 10;
example = 5;
description = ''
Time between fade animation step (in ms).
'';
};
fadeSteps = mkOption {
type = pairOf (types.numbers.between 0.01 1);
default = [
0.028
0.03
];
example = [
0.04
0.04
];
description = ''
Opacity change between fade steps (in and out).
'';
};
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 {manpage}`picom(1)` 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 = types.numbers.between 0 1;
default = 0.75;
example = 0.8;
description = ''
Window shadows opacity.
'';
};
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 {manpage}`picom(1)` man page for more examples.
'';
};
activeOpacity = mkOption {
type = types.numbers.between 0 1;
default = 1.0;
example = 0.8;
description = ''
Opacity of active windows.
'';
};
inactiveOpacity = mkOption {
type = types.numbers.between 0.1 1;
default = 1.0;
example = 0.8;
description = ''
Opacity of inactive windows.
'';
};
menuOpacity = mkOption {
type = types.numbers.between 0 1;
default = 1.0;
example = 0.8;
description = ''
Opacity of dropdown and popup menu.
'';
};
wintypes = mkOption {
type = types.attrs;
default = {
popup_menu = {
opacity = cfg.menuOpacity;
};
dropdown_menu = {
opacity = cfg.menuOpacity;
};
};
defaultText = literalExpression ''
{
popup_menu = { opacity = config.${opt.menuOpacity}; };
dropdown_menu = { opacity = config.${opt.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 [
"egl"
"glx"
"xrender"
"xr_glx_hybrid"
];
default = "xrender";
description = ''
Backend to use: `egl`, `glx`, `xrender` or `xr_glx_hybrid`.
'';
};
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.picom.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.
'';
};
settings =
with types;
let
scalar =
oneOf [
bool
int
float
str
]
// {
description = "scalar types";
};
libConfig =
oneOf [
scalar
(listOf libConfig)
(attrsOf libConfig)
]
// {
description = "libconfig type";
};
topLevel = attrsOf libConfig // {
description = ''
libconfig configuration. The format consists of an attributes
set (called a group) of settings. Each setting can be a scalar type
(boolean, integer, floating point number or string), a list of
scalars or a group itself
'';
};
in
mkOption {
type = topLevel;
default = { };
example = literalExpression ''
blur =
{ method = "gaussian";
size = 10;
deviation = 5.0;
};
'';
description = ''
Picom settings. Use this option to configure Picom settings not exposed
in a NixOS option or to bypass one. For the available options see the
CONFIGURATION FILES section at {manpage}`picom(1)`.
'';
};
};
config = mkIf cfg.enable {
services.picom.settings = mkDefaultAttrs {
# fading
fading = cfg.fade;
fade-delta = cfg.fadeDelta;
fade-in-step = elemAt cfg.fadeSteps 0;
fade-out-step = elemAt cfg.fadeSteps 1;
fade-exclude = cfg.fadeExclude;
# shadows
shadow = cfg.shadow;
shadow-offset-x = elemAt cfg.shadowOffsets 0;
shadow-offset-y = elemAt cfg.shadowOffsets 1;
shadow-opacity = cfg.shadowOpacity;
shadow-exclude = cfg.shadowExclude;
# opacity
active-opacity = cfg.activeOpacity;
inactive-opacity = cfg.inactiveOpacity;
wintypes = cfg.wintypes;
opacity-rule = cfg.opacityRules;
# other options
backend = cfg.backend;
vsync = cfg.vSync;
};
systemd.user.services.picom = {
description = "Picom 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 = "${getExe cfg.package} --config ${configFile}";
RestartSec = 3;
Restart = "always";
};
};
environment.systemPackages = [ cfg.package ];
};
meta.maintainers = with lib.maintainers; [ rnhmjoj ];
}

View File

@@ -0,0 +1,150 @@
{
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.ints.between 1000 25000;
default = 5500;
description = ''
Colour temperature to use during the day, between
`1000` and `25000` K.
'';
};
night = mkOption {
type = types.ints.between 1000 25000;
default = 3700;
description = ''
Colour temperature to use at night, between
`1000` and `25000` K.
'';
};
};
brightness = {
day = mkOption {
type = types.str;
default = "1";
description = ''
Screen brightness to apply during the day,
between `0.1` and `1.0`.
'';
};
night = mkOption {
type = types.str;
default = "1";
description = ''
Screen brightness to apply during the night,
between `0.1` and `1.0`.
'';
};
};
package = mkPackageOption pkgs "redshift" { };
executable = mkOption {
type = types.str;
default = "/bin/redshift";
example = "/bin/redshift-gtk";
description = ''
Redshift executable to use within the package.
'';
};
extraOptions = mkOption {
type = types.listOf types.str;
default = [ ];
example = [
"-v"
"-m randr"
];
description = ''
Additional command-line arguments to pass to
{command}`redshift`.
'';
};
};
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}${cfg.executable} \
-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";
};
};
};
}

View File

@@ -0,0 +1,62 @@
# 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, ... }:
{
config = {
services.xserver.enable = true;
services.xserver.videoDrivers = [ ];
# Enable GDM. Any display manager will do as long as it supports XDMCP.
services.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.net-tools
pkgs.shadow
pkgs.procps
pkgs.util-linux
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";
};
};
};
}

View File

@@ -0,0 +1,40 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.touchegg;
in
{
meta = {
maintainers = teams.pantheon.members;
};
###### interface
options.services.touchegg = {
enable = mkEnableOption "touchegg, a multi-touch gesture recognizer";
package = mkPackageOption pkgs "touchegg" { };
};
###### implementation
config = mkIf cfg.enable {
systemd.services.touchegg = {
description = "Touchegg Daemon";
serviceConfig = {
Type = "simple";
ExecStart = "${cfg.package}/bin/touchegg --daemon";
Restart = "on-failure";
};
wantedBy = [ "multi-user.target" ];
};
environment.systemPackages = [ cfg.package ];
};
}

View File

@@ -0,0 +1,64 @@
{
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 = mkPackageOption 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";
};
};
}

View File

@@ -0,0 +1,89 @@
{
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 = mkPackageOption pkgs "unclutter" { };
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;
};
threshold = 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.threshold - 1)} \
${optionalString cfg.keystroke "-keystroke"} \
${concatMapStrings (x: " -" + x) cfg.extraOptions} \
-not ${concatStringsSep " " cfg.excluded} \
'';
serviceConfig.PassEnvironment = "DISPLAY";
serviceConfig.RestartSec = 3;
serviceConfig.Restart = "always";
};
};
imports = [
(mkRenamedOptionModule
[ "services" "unclutter" "threeshold" ]
[ "services" "unclutter" "threshold" ]
)
];
meta.maintainers = with lib.maintainers; [ rnhmjoj ];
}

View File

@@ -0,0 +1,50 @@
# urserver service
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.urserver;
in
{
options.services.urserver.enable = lib.mkEnableOption "urserver";
config = lib.mkIf cfg.enable {
networking.firewall = {
allowedTCPPorts = [
9510
9512
];
allowedUDPPorts = [
9511
9512
];
};
systemd.user.services.urserver = {
description = ''
Server for Unified Remote: The one-and-only remote for your computer.
'';
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
after = [ "network.target" ];
serviceConfig = {
Type = "forking";
ExecStart = ''
${pkgs.urserver}/bin/urserver --daemon
'';
ExecStop = ''
${pkgs.procps}/bin/pkill urserver
'';
RestartSec = 3;
Restart = "on-failure";
};
};
};
}

View File

@@ -0,0 +1,49 @@
{
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 = mkPackageOption pkgs "rxvt-unicode" { };
};
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";
};
meta.maintainers = with lib.maintainers; [ rnhmjoj ];
}

View File

@@ -0,0 +1,40 @@
{
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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,63 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.awesome;
awesome = cfg.package;
getLuaPath = lib: dir: "${lib}/${dir}/lua/${awesome.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 = literalExpression "[ pkgs.luaPackages.vicious ]";
};
package = mkPackageOption pkgs "awesome" { };
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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.berry;
in
{
###### interface
options = {
services.xserver.windowManager.berry.enable = mkEnableOption "berry";
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "berry";
start = ''
${pkgs.berry}/bin/berry &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.berry ];
};
}

View File

@@ -0,0 +1,78 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.bspwm;
in
{
options = {
services.xserver.windowManager.bspwm = {
enable = mkEnableOption "bspwm";
package = mkPackageOption pkgs "bspwm" { };
configFile = mkOption {
type = with types; nullOr path;
example = literalExpression ''"''${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 = mkPackageOption pkgs "sxhkd" { };
configFile = mkOption {
type = with types; nullOr path;
example = literalExpression ''"''${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 ${escapeShellArg cfg.sxhkd.configFile}"
} &
${cfg.package}/bin/bspwm ${
optionalString (cfg.configFile != null) "-c ${escapeShellArg cfg.configFile}"
} &
waitPID=$!
'';
};
environment.systemPackages = [ cfg.package ];
};
imports = [
(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.")
];
}

View File

@@ -0,0 +1,32 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.clfswm;
in
{
options = {
services.xserver.windowManager.clfswm = {
enable = mkEnableOption "clfswm";
package = mkPackageOption pkgs [ "sbclPackages" "clfswm" ] { };
};
};
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "clfswm";
start = ''
${cfg.package}/bin/clfswm &
waitPID=$!
'';
};
environment.systemPackages = [ cfg.package ];
};
}

View File

@@ -0,0 +1,27 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.cwm;
in
{
options = {
services.xserver.windowManager.cwm.enable = mkEnableOption "cwm";
};
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "cwm";
start = ''
cwm &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.cwm ];
};
}

View File

@@ -0,0 +1,87 @@
{ config, lib, ... }:
let
inherit (lib) mkOption types;
cfg = config.services.xserver.windowManager;
in
{
imports = [
./2bwm.nix
./afterstep.nix
./berry.nix
./bspwm.nix
./cwm.nix
./clfswm.nix
./dk.nix
./dwm.nix
./e16.nix
./evilwm.nix
./exwm.nix
./fluxbox.nix
./fvwm2.nix
./fvwm3.nix
./hackedbox.nix
./herbstluftwm.nix
./hypr.nix
./i3.nix
./jwm.nix
./leftwm.nix
./lwm.nix
./metacity.nix
./mlvwm.nix
./mwm.nix
./openbox.nix
./pekwm.nix
./notion.nix
./ragnarwm.nix
./ratpoison.nix
./sawfish.nix
./smallwm.nix
./stumpwm.nix
./spectrwm.nix
./tinywm.nix
./twm.nix
./windowmaker.nix
./wmderland.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
`displayManager`.
'';
apply = map (
d:
d
// {
manage = "window";
}
);
};
};
};
config = {
services.xserver.displayManager.session = cfg.session;
};
}

View File

@@ -0,0 +1,32 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.xserver.windowManager.dk;
in
{
options = {
services.xserver.windowManager.dk = {
enable = lib.mkEnableOption "dk";
package = lib.mkPackageOption pkgs "dk" { };
};
};
config = lib.mkIf cfg.enable {
services.xserver.windowManager.session = lib.singleton {
name = "dk";
start = ''
export _JAVA_AWT_WM_NONREPARENTING=1
${cfg.package}/bin/dk &
waitPID=$!
'';
};
environment.systemPackages = [ cfg.package ];
};
}

View File

@@ -0,0 +1,63 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.dwm;
in
{
###### interface
options = {
services.xserver.windowManager.dwm = {
enable = mkEnableOption "dwm";
extraSessionCommands = mkOption {
default = "";
type = types.lines;
description = ''
Shell commands executed just before dwm is started.
'';
};
package = mkPackageOption pkgs "dwm" {
example = ''
pkgs.dwm.overrideAttrs (oldAttrs: rec {
patches = [
(super.fetchpatch {
url = "https://dwm.suckless.org/patches/steam/dwm-steam-6.2.diff";
sha256 = "sha256-f3lffBjz7+0Khyn9c9orzReoLTqBb/9gVGshYARGdVc=";
})
];
})
'';
};
};
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "dwm";
start = ''
${cfg.extraSessionCommands}
export _JAVA_AWT_WM_NONREPARENTING=1
dwm &
waitPID=$!
'';
};
environment.systemPackages = [ cfg.package ];
};
}

View File

@@ -0,0 +1,31 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.e16;
in
{
###### interface
options = {
services.xserver.windowManager.e16.enable = mkEnableOption "e16";
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "E16";
start = ''
${pkgs.e16}/bin/e16 &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.e16 ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,74 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.exwm;
loadScript = pkgs.writeText "emacs-exwm-load" ''
${cfg.loadScript}
'';
packages = epkgs: cfg.extraPackages epkgs ++ [ epkgs.exwm ];
exwm-emacs = cfg.package.pkgs.withPackages packages;
in
{
imports = [
(mkRemovedOptionModule [ "services" "xserver" "windowManager" "exwm" "enableDefaultConfig" ]
"The upstream EXWM project no longer provides a default configuration, instead copy (parts of) exwm-config.el to your local config."
)
];
options = {
services.xserver.windowManager.exwm = {
enable = mkEnableOption "exwm";
loadScript = mkOption {
default = "(require 'exwm)";
type = types.lines;
example = ''
(require 'exwm)
(exwm-enable)
'';
description = ''
Emacs lisp code to be run after loading the user's init
file.
'';
};
package = mkPackageOption pkgs "Emacs" {
default = "emacs";
example = [ "emacs-gtk" ];
};
extraPackages = mkOption {
type = types.functionTo (types.listOf types.package);
default = epkgs: [ ];
defaultText = literalExpression "epkgs: []";
example = literalExpression ''
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
{var}`emacs.pkgs` 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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,51 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.fvwm2;
fvwm2 = pkgs.fvwm2.override { enableGestures = cfg.gestures; };
in
{
imports = [
(mkRenamedOptionModule
[ "services" "xserver" "windowManager" "fvwm" ]
[ "services" "xserver" "windowManager" "fvwm2" ]
)
];
###### interface
options = {
services.xserver.windowManager.fvwm2 = {
enable = mkEnableOption "Fvwm2 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 = "fvwm2";
start = ''
${fvwm2}/bin/fvwm &
waitPID=$!
'';
};
environment.systemPackages = [ fvwm2 ];
};
}

View File

@@ -0,0 +1,38 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.fvwm3;
inherit (pkgs) fvwm3;
in
{
###### interface
options = {
services.xserver.windowManager.fvwm3 = {
enable = mkEnableOption "Fvwm3 window manager";
};
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "fvwm3";
start = ''
${fvwm3}/bin/fvwm3 &
waitPID=$!
'';
};
environment.systemPackages = [ fvwm3 ];
};
}

View File

@@ -0,0 +1,30 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.hackedbox;
in
{
###### interface
options = {
services.xserver.windowManager.hackedbox.enable = mkEnableOption "hackedbox";
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "hackedbox";
start = ''
${pkgs.hackedbox}/bin/hackedbox &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.hackedbox ];
};
}

View File

@@ -0,0 +1,47 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.herbstluftwm;
in
{
options = {
services.xserver.windowManager.herbstluftwm = {
enable = mkEnableOption "herbstluftwm";
package = mkPackageOption pkgs "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
''
${cfg.package}/bin/herbstluftwm ${configFileClause} &
waitPID=$!
'';
};
environment.systemPackages = [ cfg.package ];
};
}

View File

@@ -0,0 +1,30 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.hypr;
in
{
###### interface
options = {
services.xserver.windowManager.hypr.enable = mkEnableOption "hypr";
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "hypr";
start = ''
${pkgs.hypr}/bin/Hypr &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.hypr ];
};
}

View File

@@ -0,0 +1,98 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.i3;
updateSessionEnvironmentScript = ''
systemctl --user import-environment PATH DISPLAY XAUTHORITY DESKTOP_SESSION XDG_CONFIG_DIRS XDG_DATA_DIRS XDG_RUNTIME_DIR XDG_SESSION_ID DBUS_SESSION_BUS_ADDRESS || true
dbus-update-activation-environment --systemd --all || true
'';
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.
'';
};
updateSessionEnvironment = mkOption {
default = true;
type = types.bool;
description = ''
Whether to run dbus-update-activation-environment and systemctl import-environment before session start.
Required for xdg portals to function properly.
'';
};
extraSessionCommands = mkOption {
default = "";
type = types.lines;
description = ''
Shell commands executed just before i3 is started.
'';
};
package = mkPackageOption pkgs "i3" { };
extraPackages = mkOption {
type = with types; listOf package;
default = with pkgs; [
dmenu
i3status
];
defaultText = literalExpression ''
with pkgs; [
dmenu
i3status
]
'';
description = ''
Extra packages to be installed system wide.
'';
};
};
config = mkIf cfg.enable {
services.xserver.windowManager.session = [
{
name = "i3";
start = ''
${cfg.extraSessionCommands}
${lib.optionalString cfg.updateSessionEnvironment updateSessionEnvironmentScript}
${cfg.package}/bin/i3 ${optionalString (cfg.configFile != null) "-c /etc/i3/config"} &
waitPID=$!
'';
}
];
programs.i3lock.enable = mkDefault true;
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"
] "i3-gaps was merged into i3. Use services.xserver.windowManager.i3.enable instead.")
];
}

View File

@@ -0,0 +1,31 @@
{
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-session &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.icewm ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,37 @@
{
config,
lib,
pkgs,
...
}:
let
inherit (lib)
mkEnableOption
mkIf
mkPackageOption
singleton
;
cfg = config.services.xserver.windowManager.katriawm;
in
{
###### interface
options = {
services.xserver.windowManager.katriawm = {
enable = mkEnableOption "katriawm";
package = mkPackageOption pkgs "katriawm" { };
};
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "katriawm";
start = ''
${cfg.package}/bin/katriawm &
waitPID=$!
'';
};
environment.systemPackages = [ cfg.package ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.lwm;
in
{
###### interface
options = {
services.xserver.windowManager.lwm.enable = mkEnableOption "lwm";
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "lwm";
start = ''
${pkgs.lwm}/bin/lwm &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.lwm ];
};
}

View File

@@ -0,0 +1,33 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.xserver.windowManager.metacity;
inherit (pkgs) metacity;
in
{
options = {
services.xserver.windowManager.metacity.enable = lib.mkEnableOption "metacity";
};
config = lib.mkIf cfg.enable {
services.xserver.windowManager.session = lib.singleton {
name = "metacity";
start = ''
${metacity}/bin/metacity &
waitPID=$!
'';
};
environment.systemPackages = [ metacity ];
};
}

View File

@@ -0,0 +1,47 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.mlvwm;
in
{
options.services.xserver.windowManager.mlvwm = {
enable = mkEnableOption "Macintosh-like Virtual Window Manager";
configFile = mkOption {
default = null;
type = with types; nullOr path;
description = ''
Path to the mlvwm configuration file.
If left at the default value, $HOME/.mlvwmrc will be used.
'';
};
};
config = mkIf cfg.enable {
services.xserver.windowManager.session = [
{
name = "mlvwm";
start = ''
${pkgs.mlvwm}/bin/mlvwm ${optionalString (cfg.configFile != null) "-f /etc/mlvwm/mlvwmrc"} &
waitPID=$!
'';
}
];
environment.etc."mlvwm/mlvwmrc" = mkIf (cfg.configFile != null) {
source = cfg.configFile;
};
environment.systemPackages = [ pkgs.mlvwm ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,32 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.nimdow;
in
{
options = {
services.xserver.windowManager.nimdow.enable = mkEnableOption "nimdow";
services.xserver.windowManager.nimdow.package = mkPackageOption pkgs "nimdow" { };
};
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "nimdow";
start = ''
${cfg.package}/bin/nimdow &
waitPID=$!
'';
};
environment.systemPackages = [
cfg.package
pkgs.st
];
};
}

View File

@@ -0,0 +1,14 @@
{
services = {
xserver = {
windowManager = {
session = [
{
name = "none";
start = "";
}
];
};
};
};
}

View File

@@ -0,0 +1,33 @@
{
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 ];
};
}

View File

@@ -0,0 +1,31 @@
{
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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,79 @@
{
config,
pkgs,
lib,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.qtile;
in
{
imports = [
(mkRemovedOptionModule [
"services"
"xserver"
"windowManager"
"qtile"
"backend"
] "The qtile package now provides separate display sessions for both X11 and Wayland.")
];
options.services.xserver.windowManager.qtile = {
enable = mkEnableOption "qtile";
package = mkPackageOption pkgs [ "python3" "pkgs" "qtile" ] { };
configFile = mkOption {
type = with types; nullOr path;
default = null;
example = literalExpression "./your_config.py";
description = ''
Path to the qtile configuration file.
If null, $XDG_CONFIG_HOME/qtile/config.py will be used.
'';
};
extraPackages = mkOption {
type = types.functionTo (types.listOf types.package);
default = _: [ ];
defaultText = literalExpression ''
python3Packages: with python3Packages; [];
'';
description = ''
Extra Python packages available to Qtile.
An example would be to include `python3Packages.qtile-extras`
for additional unofficial widgets.
'';
example = literalExpression ''
python3Packages: with python3Packages; [
qtile-extras
];
'';
};
finalPackage = mkOption {
type = types.package;
visible = false;
readOnly = true;
description = "The resulting Qtile package, bundled with extra packages";
};
};
config = mkIf cfg.enable {
services = {
xserver.windowManager.qtile.finalPackage = cfg.package.override {
extraPackages = cfg.extraPackages cfg.package.pythonModule.pkgs;
};
displayManager.sessionPackages = [ cfg.finalPackage ];
};
environment = {
etc."xdg/qtile/config.py" = mkIf (cfg.configFile != null) { source = cfg.configFile; };
systemPackages = [ cfg.finalPackage ];
};
};
}

View File

@@ -0,0 +1,31 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.ragnarwm;
in
{
###### interface
options = {
services.xserver.windowManager.ragnarwm = {
enable = mkEnableOption "ragnarwm";
package = mkPackageOption pkgs "ragnarwm" { };
};
};
###### implementation
config = mkIf cfg.enable {
services.displayManager.sessionPackages = [ cfg.package ];
environment.systemPackages = [ cfg.package ];
};
meta.maintainers = with lib.maintainers; [ sigmanificient ];
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.smallwm;
in
{
###### interface
options = {
services.xserver.windowManager.smallwm.enable = mkEnableOption "smallwm";
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "smallwm";
start = ''
${pkgs.smallwm}/bin/smallwm &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.smallwm ];
};
}

View File

@@ -0,0 +1,33 @@
{
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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.stumpwm;
in
{
options = {
services.xserver.windowManager.stumpwm.enable = mkEnableOption "stumpwm";
services.xserver.windowManager.stumpwm.package = mkPackageOption pkgs "stumpwm" { };
};
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "stumpwm";
start = ''
${cfg.package}/bin/stumpwm &
waitPID=$!
'';
};
environment.systemPackages = [ cfg.package ];
};
}

View File

@@ -0,0 +1,30 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.tinywm;
in
{
###### interface
options = {
services.xserver.windowManager.tinywm.enable = mkEnableOption "tinywm";
};
###### implementation
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "tinywm";
start = ''
${pkgs.tinywm}/bin/tinywm &
waitPID=$!
'';
};
environment.systemPackages = [ pkgs.tinywm ];
};
}

View File

@@ -0,0 +1,40 @@
{
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 ];
};
}

View File

@@ -0,0 +1,28 @@
{
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 ];
};
}

View File

@@ -0,0 +1,30 @@
{
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 ];
};
}

View File

@@ -0,0 +1,68 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
cfg = config.services.xserver.windowManager.wmderland;
in
{
options.services.xserver.windowManager.wmderland = {
enable = mkEnableOption "wmderland";
extraSessionCommands = mkOption {
default = "";
type = types.lines;
description = ''
Shell commands executed just before wmderland is started.
'';
};
extraPackages = mkOption {
type = with types; listOf package;
default = with pkgs; [
rofi
dunst
light
hsetroot
feh
rxvt-unicode
];
defaultText = literalExpression ''
with pkgs; [
rofi
dunst
light
hsetroot
feh
rxvt-unicode
]
'';
description = ''
Extra packages to be installed system wide.
'';
};
};
config = mkIf cfg.enable {
services.xserver.windowManager.session = singleton {
name = "wmderland";
start = ''
${cfg.extraSessionCommands}
${pkgs.wmderland}/bin/wmderland &
waitPID=$!
'';
};
environment.systemPackages = [
pkgs.wmderland
pkgs.wmderlandc
]
++ cfg.extraPackages;
};
}

View File

@@ -0,0 +1,46 @@
{
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 ];
};
}

View File

@@ -0,0 +1,234 @@
{
pkgs,
lib,
config,
...
}:
with lib;
let
inherit (lib)
mkOption
mkIf
optionals
literalExpression
optionalString
;
cfg = config.services.xserver.windowManager.xmonad;
ghcWithPackages = cfg.haskellPackages.ghcWithPackages;
packages =
self:
cfg.extraPackages self
++ optionals cfg.enableContribAndExtras [
self.xmonad-contrib
self.xmonad-extras
];
xmonad-vanilla = pkgs.xmonad-with-packages.override {
inherit ghcWithPackages packages;
};
xmonad-config =
let
xmonadAndPackages = self: [ self.xmonad ] ++ packages self;
xmonadEnv = ghcWithPackages xmonadAndPackages;
configured = pkgs.writers.writeHaskellBin "xmonad" {
ghc = cfg.haskellPackages.ghc;
libraries = xmonadAndPackages cfg.haskellPackages;
inherit (cfg) ghcArgs;
} cfg.config;
in
pkgs.runCommand "xmonad"
{
preferLocalBuild = true;
nativeBuildInputs = [ pkgs.makeWrapper ];
}
(
''
install -D ${xmonadEnv}/share/man/man1/xmonad.1.gz $out/share/man/man1/xmonad.1.gz
makeWrapper ${configured}/bin/xmonad $out/bin/xmonad \
''
+ optionalString cfg.enableConfiguredRecompile ''
--set XMONAD_GHC "${xmonadEnv}/bin/ghc" \
''
+ ''
--set XMONAD_XMESSAGE "${pkgs.xorg.xmessage}/bin/xmessage"
''
);
xmonad = if (cfg.config != null) then xmonad-config else xmonad-vanilla;
in
{
meta.maintainers = with maintainers; [
lassulus
xaverdh
ivanbrennan
slotThe
];
options = {
services.xserver.windowManager.xmonad = {
enable = mkEnableOption "xmonad";
haskellPackages = mkOption {
default = pkgs.haskellPackages;
defaultText = literalExpression "pkgs.haskellPackages";
example = literalExpression "pkgs.haskell.packages.ghc910";
type = types.attrs;
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
{var}`extraPackages`.
'';
};
extraPackages = mkOption {
type = types.functionTo (types.listOf types.package);
default = self: [ ];
defaultText = literalExpression "self: []";
example = literalExpression ''
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 {var}`haskellPackages` 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, a vanilla xmonad binary is put in PATH, which will
attempt to recompile and exec your xmonad config from $HOME/.xmonad.
This setup is then analogous to other (non-NixOS) linux distributions.
If you do set this option, you likely want to use "launch" as your
entry point for xmonad (as in the example), to avoid xmonad's
recompilation logic on startup. Doing so will render the default
"mod+q" restart key binding dysfunctional though, because that attempts
to call your binary with the "--restart" command line option, unless
you implement that yourself. You way mant to bind "mod+q" to
`(restart "xmonad" True)` instead, which will just restart
xmonad from PATH. This allows e.g. switching to the new xmonad binary
after rebuilding your system with nixos-rebuild.
For the same reason, ghc is not added to the environment when this
option is set, unless {option}`enableConfiguredRecompile` is
set to `true`.
If you actually want to run xmonad with a config specified here, but
also be able to recompile and restart it from a copy of that source in
$HOME/.xmonad on the fly, set {option}`enableConfiguredRecompile`
to `true` and implement something like "compileRestart"
from the example.
This should allow you to switch at will between the local xmonad and
the one NixOS puts in your PATH.
'';
example = ''
import XMonad
import XMonad.Util.EZConfig (additionalKeys)
import Control.Monad (when)
import Text.Printf (printf)
import System.Posix.Process (executeFile)
import System.Info (arch,os)
import System.Environment (getArgs)
import System.FilePath ((</>))
compiledConfig = printf "xmonad-%s-%s" arch os
myConfig = defaultConfig
{ modMask = mod4Mask -- Use Super instead of Alt
, terminal = "urxvt" }
`additionalKeys`
[ ( (mod4Mask,xK_r), compileRestart True)
, ( (mod4Mask,xK_q), restart "xmonad" True ) ]
compileRestart resume = do
dirs <- asks directories
whenX (recompile dirs True) $ do
when resume writeStateToFile
catchIO
( do
args <- getArgs
executeFile (cacheDir dirs </> compiledConfig) False args Nothing
)
main = getDirectories >>= launch myConfig
--------------------------------------------
{- For versions before 0.17.0 use this instead -}
--------------------------------------------
-- compileRestart resume =
-- whenX (recompile True) $
-- when resume writeStateToFile
-- *> catchIO
-- ( do
-- dir <- getXMonadDataDir
-- args <- getArgs
-- executeFile (dir </> compiledConfig) False args Nothing
-- )
--
-- main = launch myConfig
--------------------------------------------
'';
};
enableConfiguredRecompile = mkOption {
default = false;
type = lib.types.bool;
description = ''
Enable recompilation even if {option}`config` is set to a
non-null value. This adds the necessary Haskell dependencies (GHC with
packages) to the xmonad binary's environment.
'';
};
xmonadCliArgs = mkOption {
default = [ ];
type = with lib.types; listOf str;
description = ''
Command line arguments passed to the xmonad binary.
'';
};
ghcArgs = mkOption {
default = [ ];
type = with lib.types; listOf str;
description = ''
Command line arguments passed to the compiler (ghc)
invocation when xmonad.config is set.
'';
};
};
};
config = mkIf cfg.enable {
services.xserver.windowManager = {
session = [
{
name = "xmonad";
start = ''
systemd-cat -t xmonad -- ${xmonad}/bin/xmonad ${lib.escapeShellArgs cfg.xmonadCliArgs} &
waitPID=$!
'';
}
];
};
environment.systemPackages = [ xmonad ];
};
}

View File

@@ -0,0 +1,150 @@
{
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`
defaultText = literalExpression ''"''${pkgs.xlockmore}/bin/xlock"'';
example = literalExpression ''"''${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 = literalExpression ''"''${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`.
'';
};
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 = literalExpression ''"''${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 = "/run/current-system/systemd/bin/systemctl suspend";
type = types.nullOr types.str;
description = ''
The script to use when nothing has happened for as long as {option}`killtime`
'';
};
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`
(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`.
'';
};
};
};
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}`";
}));
};
}

View File

@@ -0,0 +1,38 @@
{
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";
};
};
}

View File

@@ -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/

View File

@@ -0,0 +1,50 @@
{
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}";
};
};
}

View File

@@ -0,0 +1,42 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.xscreensaver;
in
{
options.services.xscreensaver = {
enable = lib.mkEnableOption "xscreensaver user service";
package = lib.mkPackageOption pkgs "xscreensaver" { };
};
config = lib.mkIf cfg.enable {
# Make xscreensaver-auth setuid root so that it can (try to) prevent the OOM
# killer from unlocking the screen.
security.wrappers.xscreensaver-auth = {
setuid = true;
owner = "root";
group = "root";
source = "${pkgs.xscreensaver}/libexec/xscreensaver/xscreensaver-auth";
};
systemd.user.services.xscreensaver = {
enable = true;
description = "XScreenSaver";
after = [ "graphical-session-pre.target" ];
partOf = [ "graphical-session.target" ];
wantedBy = [ "graphical-session.target" ];
path = [ cfg.package ];
serviceConfig.ExecStart = "${cfg.package}/bin/xscreensaver -no-splash";
};
};
meta.maintainers = with lib.maintainers; [
vancluever
];
}

Some files were not shown because too many files have changed in this diff Show More