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 (mkAliasOptionModuleMD [ "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
50 (mkRemovedOptionModule [ "services" "picom" "experimentalBackends" ] ''
51 This option was removed by upstream since picom v10.
55 options.services.picom = {
60 Whether or not to enable Picom as the X.org composite manager.
64 package = mkPackageOption pkgs "picom" { };
70 Fade windows in and out.
74 fadeDelta = mkOption {
75 type = types.ints.positive;
79 Time between fade animation step (in ms).
83 fadeSteps = mkOption {
84 type = pairOf (types.numbers.between 0.01 1);
85 default = [ 0.028 0.03 ];
86 example = [ 0.04 0.04 ];
88 Opacity change between fade steps (in and out).
92 fadeExclude = mkOption {
93 type = types.listOf types.str;
96 "window_type *= 'menu'"
101 List of conditions of windows that should not be faded.
102 See `picom(1)` man page for more examples.
114 shadowOffsets = mkOption {
115 type = pairOf types.int;
116 default = [ (-15) (-15) ];
117 example = [ (-10) (-15) ];
119 Left and right offset for shadows (in pixels).
123 shadowOpacity = mkOption {
124 type = types.numbers.between 0 1;
128 Window shadows opacity.
132 shadowExclude = mkOption {
133 type = types.listOf types.str;
136 "window_type *= 'menu'"
141 List of conditions of windows that should have no shadow.
142 See `picom(1)` man page for more examples.
146 activeOpacity = mkOption {
147 type = types.numbers.between 0 1;
151 Opacity of active windows.
155 inactiveOpacity = mkOption {
156 type = types.numbers.between 0.1 1;
160 Opacity of inactive windows.
164 menuOpacity = mkOption {
165 type = types.numbers.between 0 1;
169 Opacity of dropdown and popup menu.
173 wintypes = mkOption {
176 popup_menu = { opacity = cfg.menuOpacity; };
177 dropdown_menu = { opacity = cfg.menuOpacity; };
179 defaultText = literalExpression ''
181 popup_menu = { opacity = config.${opt.menuOpacity}; };
182 dropdown_menu = { opacity = config.${opt.menuOpacity}; };
187 Rules for specific window types.
191 opacityRules = mkOption {
192 type = types.listOf types.str;
195 "95:class_g = 'URxvt' && !_NET_WM_STATE@:32a"
196 "0:_NET_WM_STATE@:32a *= '_NET_WM_STATE_HIDDEN'"
199 Rules that control the opacity of windows, in format PERCENT:PATTERN.
204 type = types.enum [ "egl" "glx" "xrender" "xr_glx_hybrid" ];
207 Backend to use: `egl`, `glx`, `xrender` or `xr_glx_hybrid`.
212 type = with types; either bool
213 (enum [ "none" "drm" "opengl" "opengl-oml" "opengl-swc" "opengl-mswc" ]);
218 msg = "The type of services.picom.vSync has changed to bool:"
219 + " interpreting ${x} as ${boolToString res}";
225 Enable vertical synchronization. Chooses the best method
226 (drm, opengl, opengl-oml, opengl-swc, opengl-mswc) automatically.
227 The bool value should be used, the others are just for backwards compatibility.
231 settings = with types;
233 scalar = oneOf [ bool int float str ]
234 // { description = "scalar types"; };
236 libConfig = oneOf [ scalar (listOf libConfig) (attrsOf libConfig) ]
237 // { description = "libconfig type"; };
239 topLevel = attrsOf libConfig
240 // { description = ''
241 libconfig configuration. The format consists of an attributes
242 set (called a group) of settings. Each setting can be a scalar type
243 (boolean, integer, floating point number or string), a list of
244 scalars or a group itself
251 example = literalExpression ''
253 { method = "gaussian";
259 Picom settings. Use this option to configure Picom settings not exposed
260 in a NixOS option or to bypass one. For the available options see the
261 CONFIGURATION FILES section at `picom(1)`.
266 config = mkIf cfg.enable {
267 services.picom.settings = mkDefaultAttrs {
270 fade-delta = cfg.fadeDelta;
271 fade-in-step = elemAt cfg.fadeSteps 0;
272 fade-out-step = elemAt cfg.fadeSteps 1;
273 fade-exclude = cfg.fadeExclude;
277 shadow-offset-x = elemAt cfg.shadowOffsets 0;
278 shadow-offset-y = elemAt cfg.shadowOffsets 1;
279 shadow-opacity = cfg.shadowOpacity;
280 shadow-exclude = cfg.shadowExclude;
283 active-opacity = cfg.activeOpacity;
284 inactive-opacity = cfg.inactiveOpacity;
286 wintypes = cfg.wintypes;
288 opacity-rule = cfg.opacityRules;
291 backend = cfg.backend;
295 systemd.user.services.picom = {
296 description = "Picom composite manager";
297 wantedBy = [ "graphical-session.target" ];
298 partOf = [ "graphical-session.target" ];
300 # Temporarily fixes corrupt colours with Mesa 18
301 environment = mkIf (cfg.backend == "glx") {
302 allow_rgb10_configs = "false";
306 ExecStart = "${getExe cfg.package} --config ${configFile}";
312 environment.systemPackages = [ cfg.package ];
315 meta.maintainers = with lib.maintainers; [ rnhmjoj ];