1 { config, lib, options, pkgs, ... }:
7 cfg = config.services.picom;
8 opt = options.services.picom;
10 pairOf = x: with types;
11 addCheck (listOf x) (y: length y == 2)
12 // { description = "pair of ${x.description}"; };
14 mkDefaultAttrs = mapAttrs (n: v: mkDefault v);
16 # Basically a tinkered lib.generators.mkKeyValueDefault
17 # It either serializes a top-level definition "key: { values };"
18 # or an expression "key = { values };"
21 let sep = if (top && isAttrs v) then ":" else "=";
22 in "${escape [ sep ] k}${sep}${mkValueString v};");
24 # This serializes a Nix expression to the libconfig format.
26 if types.bool.check v then boolToString v
27 else if types.int.check v then toString v
28 else if types.float.check v then toString v
29 else if types.str.check v then "\"${escape [ "\"" ] v}\""
30 else if builtins.isList v then "[ ${concatMapStringsSep " , " mkValueString v} ]"
31 else if types.attrs.check v then "{ ${concatStringsSep " " (mkAttrsString false v) } }"
33 invalid expression used in option services.picom.settings:
37 toConf = attrs: concatStringsSep "\n" (mkAttrsString true cfg.settings);
39 configFile = pkgs.writeText "picom.conf" (toConf cfg.settings);
44 (mkAliasOptionModule [ "services" "compton" ] [ "services" "picom" ])
45 (mkRemovedOptionModule [ "services" "picom" "refreshRate" ] ''
46 This option corresponds to `refresh-rate`, which has been unused
47 since picom v6 and was subsequently removed by upstream.
48 See https://github.com/yshui/picom/commit/bcbc410
52 options.services.picom = {
56 description = lib.mdDoc ''
57 Whether or not to enable Picom as the X.org composite manager.
61 experimentalBackends = mkOption {
64 description = lib.mdDoc ''
65 Whether to use the unstable new reimplementation of the backends.
72 description = lib.mdDoc ''
73 Fade windows in and out.
77 fadeDelta = mkOption {
78 type = types.ints.positive;
81 description = lib.mdDoc ''
82 Time between fade animation step (in ms).
86 fadeSteps = mkOption {
87 type = pairOf (types.numbers.between 0.01 1);
88 default = [ 0.028 0.03 ];
89 example = [ 0.04 0.04 ];
90 description = lib.mdDoc ''
91 Opacity change between fade steps (in and out).
95 fadeExclude = mkOption {
96 type = types.listOf types.str;
99 "window_type *= 'menu'"
103 description = lib.mdDoc ''
104 List of conditions of windows that should not be faded.
105 See `picom(1)` man page for more examples.
112 description = lib.mdDoc ''
117 shadowOffsets = mkOption {
118 type = pairOf types.int;
119 default = [ (-15) (-15) ];
120 example = [ (-10) (-15) ];
121 description = lib.mdDoc ''
122 Left and right offset for shadows (in pixels).
126 shadowOpacity = mkOption {
127 type = types.numbers.between 0 1;
130 description = lib.mdDoc ''
131 Window shadows opacity.
135 shadowExclude = mkOption {
136 type = types.listOf types.str;
139 "window_type *= 'menu'"
143 description = lib.mdDoc ''
144 List of conditions of windows that should have no shadow.
145 See `picom(1)` man page for more examples.
149 activeOpacity = mkOption {
150 type = types.numbers.between 0 1;
153 description = lib.mdDoc ''
154 Opacity of active windows.
158 inactiveOpacity = mkOption {
159 type = types.numbers.between 0.1 1;
162 description = lib.mdDoc ''
163 Opacity of inactive windows.
167 menuOpacity = mkOption {
168 type = types.numbers.between 0 1;
171 description = lib.mdDoc ''
172 Opacity of dropdown and popup menu.
176 wintypes = mkOption {
179 popup_menu = { opacity = cfg.menuOpacity; };
180 dropdown_menu = { opacity = cfg.menuOpacity; };
182 defaultText = literalExpression ''
184 popup_menu = { opacity = config.${opt.menuOpacity}; };
185 dropdown_menu = { opacity = config.${opt.menuOpacity}; };
189 description = lib.mdDoc ''
190 Rules for specific window types.
194 opacityRules = mkOption {
195 type = types.listOf types.str;
198 "95:class_g = 'URxvt' && !_NET_WM_STATE@:32a"
199 "0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'"
201 description = lib.mdDoc ''
202 Rules that control the opacity of windows, in format PERCENT:PATTERN.
207 type = types.enum [ "glx" "xrender" "xr_glx_hybrid" ];
209 description = lib.mdDoc ''
210 Backend to use: `glx`, `xrender` or `xr_glx_hybrid`.
215 type = with types; either bool
216 (enum [ "none" "drm" "opengl" "opengl-oml" "opengl-swc" "opengl-mswc" ]);
221 msg = "The type of services.picom.vSync has changed to bool:"
222 + " interpreting ${x} as ${boolToString res}";
227 description = lib.mdDoc ''
228 Enable vertical synchronization. Chooses the best method
229 (drm, opengl, opengl-oml, opengl-swc, opengl-mswc) automatically.
230 The bool value should be used, the others are just for backwards compatibility.
234 settings = with types;
236 scalar = oneOf [ bool int float str ]
237 // { description = "scalar types"; };
239 libConfig = oneOf [ scalar (listOf libConfig) (attrsOf libConfig) ]
240 // { description = "libconfig type"; };
242 topLevel = attrsOf libConfig
243 // { description = ''
244 libconfig configuration. The format consists of an attributes
245 set (called a group) of settings. Each setting can be a scalar type
246 (boolean, integer, floating point number or string), a list of
247 scalars or a group itself
254 example = literalExpression ''
256 { method = "gaussian";
261 description = lib.mdDoc ''
262 Picom settings. Use this option to configure Picom settings not exposed
263 in a NixOS option or to bypass one. For the available options see the
264 CONFIGURATION FILES section at `picom(1)`.
269 config = mkIf cfg.enable {
270 services.picom.settings = mkDefaultAttrs {
273 fade-delta = cfg.fadeDelta;
274 fade-in-step = elemAt cfg.fadeSteps 0;
275 fade-out-step = elemAt cfg.fadeSteps 1;
276 fade-exclude = cfg.fadeExclude;
280 shadow-offset-x = elemAt cfg.shadowOffsets 0;
281 shadow-offset-y = elemAt cfg.shadowOffsets 1;
282 shadow-opacity = cfg.shadowOpacity;
283 shadow-exclude = cfg.shadowExclude;
286 active-opacity = cfg.activeOpacity;
287 inactive-opacity = cfg.inactiveOpacity;
289 wintypes = cfg.wintypes;
291 opacity-rule = cfg.opacityRules;
294 backend = cfg.backend;
298 systemd.user.services.picom = {
299 description = "Picom composite manager";
300 wantedBy = [ "graphical-session.target" ];
301 partOf = [ "graphical-session.target" ];
303 # Temporarily fixes corrupt colours with Mesa 18
304 environment = mkIf (cfg.backend == "glx") {
305 allow_rgb10_configs = "false";
309 ExecStart = "${pkgs.picom}/bin/picom --config ${configFile}"
310 + (optionalString cfg.experimentalBackends " --experimental-backends");
316 environment.systemPackages = [ pkgs.picom ];
319 meta.maintainers = with lib.maintainers; [ rnhmjoj ];