2021-12-05 21:45:35 +01:00
|
|
|
{ config, lib, options, pkgs, ... }:
|
2016-07-17 02:25:38 +02:00
|
|
|
|
|
|
|
with lib;
|
|
|
|
|
|
|
|
let
|
|
|
|
|
2020-01-03 13:51:22 +01:00
|
|
|
cfg = config.services.picom;
|
2021-12-05 21:45:35 +01:00
|
|
|
opt = options.services.picom;
|
2016-07-17 02:25:38 +02:00
|
|
|
|
2020-05-02 19:04:50 +02:00
|
|
|
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);
|
2019-07-19 15:48:28 +02:00
|
|
|
|
2020-01-03 13:51:22 +01:00
|
|
|
configFile = pkgs.writeText "picom.conf" (toConf cfg.settings);
|
2016-07-17 02:25:38 +02:00
|
|
|
|
|
|
|
in {
|
|
|
|
|
2020-01-03 13:51:22 +01:00
|
|
|
imports = [
|
2022-12-30 20:43:53 +01:00
|
|
|
(mkAliasOptionModuleMD [ "services" "compton" ] [ "services" "picom" ])
|
2022-06-11 08:59:07 +02:00
|
|
|
(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
|
|
|
|
'')
|
2022-11-16 21:07:23 +01:00
|
|
|
(mkRemovedOptionModule [ "services" "picom" "experimentalBackends" ] ''
|
|
|
|
This option was removed by upstream since picom v10.
|
|
|
|
'')
|
2020-01-03 13:51:22 +01:00
|
|
|
];
|
|
|
|
|
|
|
|
options.services.picom = {
|
2016-07-17 02:25:38 +02:00
|
|
|
enable = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = lib.mdDoc ''
|
2020-09-07 20:52:31 +02:00
|
|
|
Whether or not to enable Picom as the X.org composite manager.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2023-11-30 19:03:14 +01:00
|
|
|
package = mkPackageOption pkgs "picom" { };
|
2023-08-10 19:40:42 +02:00
|
|
|
|
2016-07-17 02:25:38 +02:00
|
|
|
fade = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = lib.mdDoc ''
|
|
|
|
Fade windows in and out.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
fadeDelta = mkOption {
|
2020-05-02 19:04:50 +02:00
|
|
|
type = types.ints.positive;
|
2016-07-17 02:25:38 +02:00
|
|
|
default = 10;
|
|
|
|
example = 5;
|
|
|
|
description = lib.mdDoc ''
|
|
|
|
Time between fade animation step (in ms).
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
fadeSteps = mkOption {
|
2022-07-17 12:56:40 +02:00
|
|
|
type = pairOf (types.numbers.between 0.01 1);
|
2020-05-02 19:04:50 +02:00
|
|
|
default = [ 0.028 0.03 ];
|
|
|
|
example = [ 0.04 0.04 ];
|
2016-07-17 02:25:38 +02:00
|
|
|
description = lib.mdDoc ''
|
|
|
|
Opacity change between fade steps (in and out).
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
fadeExclude = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = [];
|
|
|
|
example = [
|
|
|
|
"window_type *= 'menu'"
|
|
|
|
"name ~= 'Firefox$'"
|
2019-06-02 20:16:31 +02:00
|
|
|
"focused = 1"
|
2016-07-17 02:25:38 +02:00
|
|
|
];
|
|
|
|
description = lib.mdDoc ''
|
2017-04-08 06:04:55 +02:00
|
|
|
List of conditions of windows that should not be faded.
|
2020-01-03 13:51:22 +01:00
|
|
|
See `picom(1)` man page for more examples.
|
2016-07-17 02:25:38 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
shadow = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = false;
|
|
|
|
description = lib.mdDoc ''
|
|
|
|
Draw window shadows.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
shadowOffsets = mkOption {
|
2017-10-16 23:52:42 +02:00
|
|
|
type = pairOf types.int;
|
2016-07-17 02:25:38 +02:00
|
|
|
default = [ (-15) (-15) ];
|
|
|
|
example = [ (-10) (-15) ];
|
|
|
|
description = lib.mdDoc ''
|
|
|
|
Left and right offset for shadows (in pixels).
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
shadowOpacity = mkOption {
|
2022-07-17 12:56:40 +02:00
|
|
|
type = types.numbers.between 0 1;
|
2020-05-02 19:04:50 +02:00
|
|
|
default = 0.75;
|
|
|
|
example = 0.8;
|
2016-07-17 02:25:38 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-05-02 19:04:50 +02:00
|
|
|
Window shadows opacity.
|
2016-07-17 02:25:38 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
shadowExclude = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = [];
|
|
|
|
example = [
|
|
|
|
"window_type *= 'menu'"
|
|
|
|
"name ~= 'Firefox$'"
|
2019-06-02 20:16:31 +02:00
|
|
|
"focused = 1"
|
2016-07-17 02:25:38 +02:00
|
|
|
];
|
|
|
|
description = lib.mdDoc ''
|
2017-04-08 06:04:55 +02:00
|
|
|
List of conditions of windows that should have no shadow.
|
2020-01-03 13:51:22 +01:00
|
|
|
See `picom(1)` man page for more examples.
|
2016-07-17 02:25:38 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
activeOpacity = mkOption {
|
2022-07-17 12:56:40 +02:00
|
|
|
type = types.numbers.between 0 1;
|
2020-05-02 19:04:50 +02:00
|
|
|
default = 1.0;
|
|
|
|
example = 0.8;
|
2016-07-17 02:25:38 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-05-02 19:04:50 +02:00
|
|
|
Opacity of active windows.
|
2016-07-17 02:25:38 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
inactiveOpacity = mkOption {
|
2022-07-17 12:56:40 +02:00
|
|
|
type = types.numbers.between 0.1 1;
|
2020-05-02 19:04:50 +02:00
|
|
|
default = 1.0;
|
|
|
|
example = 0.8;
|
2016-07-17 02:25:38 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-05-02 19:04:50 +02:00
|
|
|
Opacity of inactive windows.
|
2016-07-17 02:25:38 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
menuOpacity = mkOption {
|
2022-07-17 12:56:40 +02:00
|
|
|
type = types.numbers.between 0 1;
|
2020-05-02 19:04:50 +02:00
|
|
|
default = 1.0;
|
|
|
|
example = 0.8;
|
2016-07-17 02:25:38 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-05-02 19:04:50 +02:00
|
|
|
Opacity of dropdown and popup menu.
|
2016-07-17 02:25:38 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2019-06-02 20:16:31 +02:00
|
|
|
wintypes = mkOption {
|
|
|
|
type = types.attrs;
|
2021-12-05 21:45:35 +01:00
|
|
|
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}; };
|
|
|
|
}
|
|
|
|
'';
|
2019-06-02 20:16:31 +02:00
|
|
|
example = {};
|
|
|
|
description = lib.mdDoc ''
|
|
|
|
Rules for specific window types.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2017-10-12 16:07:52 +02:00
|
|
|
opacityRules = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = [];
|
2017-10-16 23:52:42 +02:00
|
|
|
example = [
|
|
|
|
"95:class_g = 'URxvt' && !_NET_WM_STATE@:32a"
|
|
|
|
"0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'"
|
|
|
|
];
|
2017-10-12 16:07:52 +02:00
|
|
|
description = lib.mdDoc ''
|
2017-10-16 23:52:42 +02:00
|
|
|
Rules that control the opacity of windows, in format PERCENT:PATTERN.
|
2017-10-12 16:07:52 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2016-07-17 02:25:38 +02:00
|
|
|
backend = mkOption {
|
2022-11-19 19:13:29 +01:00
|
|
|
type = types.enum [ "egl" "glx" "xrender" "xr_glx_hybrid" ];
|
2017-10-16 23:54:10 +02:00
|
|
|
default = "xrender";
|
2016-07-17 02:25:38 +02:00
|
|
|
description = lib.mdDoc ''
|
2022-11-19 19:13:29 +01:00
|
|
|
Backend to use: `egl`, `glx`, `xrender` or `xr_glx_hybrid`.
|
2016-07-17 02:25:38 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
vSync = mkOption {
|
2019-05-28 13:37:14 +02:00
|
|
|
type = with types; either bool
|
|
|
|
(enum [ "none" "drm" "opengl" "opengl-oml" "opengl-swc" "opengl-mswc" ]);
|
|
|
|
default = false;
|
|
|
|
apply = x:
|
|
|
|
let
|
|
|
|
res = x != "none";
|
2020-01-03 13:51:22 +01:00
|
|
|
msg = "The type of services.picom.vSync has changed to bool:"
|
2019-06-02 20:16:31 +02:00
|
|
|
+ " interpreting ${x} as ${boolToString res}";
|
2019-05-28 13:37:14 +02:00
|
|
|
in
|
|
|
|
if isBool x then x
|
|
|
|
else warn msg res;
|
|
|
|
|
|
|
|
description = lib.mdDoc ''
|
|
|
|
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.
|
2017-10-16 23:52:42 +02:00
|
|
|
'';
|
2016-07-17 02:25:38 +02:00
|
|
|
};
|
|
|
|
|
2020-05-02 19:04:50 +02:00
|
|
|
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
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2019-07-19 15:48:28 +02:00
|
|
|
in mkOption {
|
2020-05-02 19:04:50 +02:00
|
|
|
type = topLevel;
|
|
|
|
default = { };
|
2021-10-03 18:06:03 +02:00
|
|
|
example = literalExpression ''
|
2020-05-02 19:04:50 +02:00
|
|
|
blur =
|
|
|
|
{ method = "gaussian";
|
|
|
|
size = 10;
|
|
|
|
deviation = 5.0;
|
|
|
|
};
|
|
|
|
'';
|
2016-07-17 02:25:38 +02:00
|
|
|
description = lib.mdDoc ''
|
2020-05-02 19:04:50 +02:00
|
|
|
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 `picom(1)`.
|
2016-07-17 02:25:38 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
2020-05-02 19:04:50 +02:00
|
|
|
services.picom.settings = mkDefaultAttrs {
|
2019-07-19 15:48:28 +02:00
|
|
|
# fading
|
2020-05-02 19:04:50 +02:00
|
|
|
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;
|
2019-07-19 15:48:28 +02:00
|
|
|
|
|
|
|
# shadows
|
2020-05-02 19:04:50 +02:00
|
|
|
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;
|
2019-07-19 15:48:28 +02:00
|
|
|
|
|
|
|
# opacity
|
2020-05-02 19:04:50 +02:00
|
|
|
active-opacity = cfg.activeOpacity;
|
|
|
|
inactive-opacity = cfg.inactiveOpacity;
|
2019-07-19 15:48:28 +02:00
|
|
|
|
2020-05-02 19:04:50 +02:00
|
|
|
wintypes = cfg.wintypes;
|
2019-07-19 15:48:28 +02:00
|
|
|
|
2020-05-02 19:04:50 +02:00
|
|
|
opacity-rule = cfg.opacityRules;
|
2019-07-19 15:48:28 +02:00
|
|
|
|
|
|
|
# other options
|
2020-05-02 19:04:50 +02:00
|
|
|
backend = cfg.backend;
|
|
|
|
vsync = cfg.vSync;
|
2019-07-19 15:48:28 +02:00
|
|
|
};
|
|
|
|
|
2020-01-03 13:51:22 +01:00
|
|
|
systemd.user.services.picom = {
|
|
|
|
description = "Picom composite manager";
|
2017-05-25 19:33:13 +02:00
|
|
|
wantedBy = [ "graphical-session.target" ];
|
|
|
|
partOf = [ "graphical-session.target" ];
|
2018-10-19 00:57:35 +02:00
|
|
|
|
|
|
|
# Temporarily fixes corrupt colours with Mesa 18
|
|
|
|
environment = mkIf (cfg.backend == "glx") {
|
|
|
|
allow_rgb10_configs = "false";
|
|
|
|
};
|
|
|
|
|
2016-07-17 02:25:38 +02:00
|
|
|
serviceConfig = {
|
2023-08-14 10:19:41 +02:00
|
|
|
ExecStart = "${getExe cfg.package} --config ${configFile}";
|
2016-07-17 02:25:38 +02:00
|
|
|
RestartSec = 3;
|
|
|
|
Restart = "always";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-08-10 19:40:42 +02:00
|
|
|
environment.systemPackages = [ cfg.package ];
|
2016-07-17 02:25:38 +02:00
|
|
|
};
|
|
|
|
|
2019-12-04 17:07:45 +01:00
|
|
|
meta.maintainers = with lib.maintainers; [ rnhmjoj ];
|
|
|
|
|
2016-07-17 02:25:38 +02:00
|
|
|
}
|