diff --git a/doc/release-notes/rl-2003.adoc b/doc/release-notes/rl-2003.adoc index 5ca3cdd79..bc94b15ce 100644 --- a/doc/release-notes/rl-2003.adoc +++ b/doc/release-notes/rl-2003.adoc @@ -69,6 +69,11 @@ use home-manager.users.jane = { config.config = "foo"; }; ---- +* The `services.compton` module has been deprecated and instead the +new module `services.picom` should be used. This is because Nixpkgs no +longer packages compton, and instead packages the (mostly) compatible +fork called picom. + [[sec-release-20.03-state-version-changes]] === State Version Changes diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 8495e956e..82bb057bd 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1415,6 +1415,34 @@ in A new module is available: 'services.keynav'. ''; } + + { + time = "2020-03-24T22:17:20+00:00"; + condition = config.services.compton.enable; + message = '' + The 'services.compton' module has been deprecated and + instead the new module 'services.picom' should be used. This + is because Nixpkgs no longer packages compton, and instead + packages the (mostly) compatible fork called picom. + + The 'services.compton' and 'services.picom' modules have a + few differences: + + - 'services.picom' has a new 'experimentalBackends' + option. + + - 'vSync' is now a boolean value on 'services.picom', as + opposed to the string in 'services.compton'. + + Migrating to the new picom service is simple - just change + all references to 'services.compton' to 'services.picom', + and adhere to the above changes. + + The deprecated 'services.compton' will eventually be removed + in the future. Please update your configurations to use + 'services.picom' as soon as possible. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index d46a7d300..b714f7d26 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -141,6 +141,7 @@ let (loadModule ./services/parcellite.nix { }) (loadModule ./services/password-store-sync.nix { condition = hostPlatform.isLinux; }) (loadModule ./services/pasystray.nix { }) + (loadModule ./services/picom.nix { }) (loadModule ./services/polybar.nix { }) (loadModule ./services/random-background.nix { }) (loadModule ./services/redshift.nix { }) diff --git a/modules/services/compton.nix b/modules/services/compton.nix index 3a67c7cb5..0b8e7232b 100644 --- a/modules/services/compton.nix +++ b/modules/services/compton.nix @@ -1,301 +1,43 @@ { config, lib, pkgs, ... }: -with lib; -with builtins; +with lib; { + imports = let + old = n: [ "services" "compton" n ]; + new = n: [ "services" "picom" n ]; + in [ + (mkRenamedOptionModule (old "activeOpacity") (new "activeOpacity")) + (mkRenamedOptionModule (old "backend") (new "backend")) + (mkRenamedOptionModule (old "blur") (new "blur")) + (mkRenamedOptionModule (old "blurExclude") (new "blurExclude")) + (mkRenamedOptionModule (old "extraOptions") (new "extraOptions")) + (mkRenamedOptionModule (old "fade") (new "fade")) + (mkRenamedOptionModule (old "fadeDelta") (new "fadeDelta")) + (mkRenamedOptionModule (old "fadeExclude") (new "fadeExclude")) + (mkRenamedOptionModule (old "fadeSteps") (new "fadeSteps")) + (mkRenamedOptionModule (old "inactiveDim") (new "inactiveDim")) + (mkRenamedOptionModule (old "inactiveOpacity") (new "inactiveOpacity")) + (mkRenamedOptionModule (old "menuOpacity") (new "menuOpacity")) + (mkRenamedOptionModule (old "noDNDShadow") (new "noDNDShadow")) + (mkRenamedOptionModule (old "noDockShadow") (new "noDockShadow")) + (mkRenamedOptionModule (old "opacityRule") (new "opacityRule")) + (mkRenamedOptionModule (old "package") (new "package")) + (mkRenamedOptionModule (old "refreshRate") (new "refreshRate")) + (mkRenamedOptionModule (old "shadow") (new "shadow")) + (mkRenamedOptionModule (old "shadowExclude") (new "shadowExclude")) + (mkRenamedOptionModule (old "shadowOffsets") (new "shadowOffsets")) + (mkRenamedOptionModule (old "shadowOpacity") (new "shadowOpacity")) + (mkChangedOptionModule (old "vSync") (new "vSync") (v: v != "none")) + ]; -let - - cfg = config.services.compton; - - configFile = pkgs.writeText "compton.conf" (optionalString cfg.fade '' - # fading - fading = true; - fade-delta = ${toString cfg.fadeDelta}; - fade-in-step = ${elemAt cfg.fadeSteps 0}; - fade-out-step = ${elemAt cfg.fadeSteps 1}; - fade-exclude = ${toJSON cfg.fadeExclude}; - '' + optionalString cfg.shadow '' - - # shadows - shadow = true; - shadow-offset-x = ${toString (elemAt cfg.shadowOffsets 0)}; - shadow-offset-y = ${toString (elemAt cfg.shadowOffsets 1)}; - shadow-opacity = ${cfg.shadowOpacity}; - shadow-exclude = ${toJSON cfg.shadowExclude}; - no-dock-shadow = ${toJSON cfg.noDockShadow}; - no-dnd-shadow = ${toJSON cfg.noDNDShadow}; - '' + optionalString cfg.blur '' - - # blur - blur-background = true; - blur-background-exclude = ${toJSON cfg.blurExclude}; - '' + '' - - # opacity - active-opacity = ${cfg.activeOpacity}; - inactive-opacity = ${cfg.inactiveOpacity}; - inactive-dim = ${cfg.inactiveDim}; - menu-opacity = ${cfg.menuOpacity}; - opacity-rule = ${toJSON cfg.opacityRule}; - - # other options - backend = ${toJSON cfg.backend}; - vsync = ${toJSON cfg.vSync}; - refresh-rate = ${toString cfg.refreshRate}; - '' + cfg.extraOptions); - -in { - - options.services.compton = { - enable = mkEnableOption "Compton X11 compositor"; - - blur = mkOption { - type = types.bool; - default = false; - description = '' - Enable background blur on transparent windows. - ''; - }; - - blurExclude = mkOption { - type = types.listOf types.str; - default = [ ]; - example = [ "class_g = 'slop'" "class_i = 'polybar'" ]; - description = '' - List of windows to exclude background blur. - See the - - compton - 1 - - man page for more examples. - ''; - }; - - fade = mkOption { - type = types.bool; - default = false; - description = '' - Fade windows in and out. - ''; - }; - - fadeDelta = mkOption { - type = types.int; - default = 10; - example = 5; - description = '' - Time between fade animation step (in ms). - ''; - }; - - fadeSteps = mkOption { - type = types.listOf types.str; - 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 the - - compton - 1 - - man page for more examples. - ''; - }; - - shadow = mkOption { - type = types.bool; - default = false; - description = '' - Draw window shadows. - ''; - }; - - shadowOffsets = mkOption { - type = types.listOf types.int; - default = [ (-15) (-15) ]; - example = [ (-10) (-15) ]; - description = '' - Horizontal and vertical offsets for shadows (in pixels). - ''; - }; - - shadowOpacity = mkOption { - type = types.str; - default = "0.75"; - example = "0.8"; - description = '' - Window shadows opacity (number in range 0 - 1). - ''; - }; - - 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 the - - compton - 1 - - man page for more examples. - ''; - }; - - noDockShadow = mkOption { - type = types.bool; - default = true; - description = '' - Avoid shadow on docks. - ''; - }; - - noDNDShadow = mkOption { - type = types.bool; - default = true; - description = '' - Avoid shadow on drag-and-drop windows. - ''; - }; - - activeOpacity = mkOption { - type = types.str; - default = "1.0"; - example = "0.8"; - description = '' - Opacity of active windows. - ''; - }; - - inactiveDim = mkOption { - type = types.str; - default = "0.0"; - example = "0.2"; - description = '' - Dim inactive windows. - ''; - }; - - inactiveOpacity = mkOption { - type = types.str; - default = "1.0"; - example = "0.8"; - description = '' - Opacity of inactive windows. - ''; - }; - - menuOpacity = mkOption { - type = types.str; - default = "1.0"; - example = "0.8"; - description = '' - Opacity of dropdown and popup menu. - ''; - }; - - opacityRule = mkOption { - type = types.listOf types.str; - default = [ ]; - example = [ "87:class_i ?= 'scratchpad'" "91:class_i ?= 'xterm'" ]; - description = '' - List of opacity rules. - See the - - compton - 1 - - man page for more examples. - ''; - }; - - backend = mkOption { - type = types.str; - default = "glx"; - description = '' - Backend to use: glx or xrender. - ''; - }; - - vSync = mkOption { - type = types.str; - default = "none"; - example = "opengl-swc"; - description = '' - Enable vertical synchronization using the specified method. - See the - - compton - 1 - - man page for available methods. - ''; - }; - - refreshRate = mkOption { - type = types.int; - default = 0; - example = 60; - description = '' - Screen refresh rate (0 = automatically detect). - ''; - }; - - package = mkOption { - type = types.package; - default = pkgs.compton; - defaultText = literalExample "pkgs.compton"; - example = literalExample "pkgs.compton"; - description = '' - Compton derivation to use. - ''; - }; - - extraOptions = mkOption { - type = types.str; - default = ""; - example = '' - unredir-if-possible = true; - dbe = true; - ''; - description = '' - Additional Compton configuration. - ''; - }; + options.services.compton.enable = mkEnableOption "Compton X11 compositor" // { + visible = false; }; - config = mkIf cfg.enable { - home.packages = [ cfg.package ]; + config = mkIf config.services.compton.enable { + warnings = [ + "Obsolete option `services.compton.enable' is used. It was renamed to `services.picom.enable'." + ]; - systemd.user.services.compton = { - Unit = { - Description = "Compton X11 compositor"; - After = [ "graphical-session-pre.target" ]; - PartOf = [ "graphical-session.target" ]; - }; - - Install = { WantedBy = [ "graphical-session.target" ]; }; - - Service = { - ExecStart = "${cfg.package}/bin/compton --config ${configFile}"; - Restart = "always"; - RestartSec = 3; - } // optionalAttrs (cfg.backend == "glx") { - # Temporarily fixes corrupt colours with Mesa 18. - Environment = [ "allow_rgb10_configs=false" ]; - }; - }; + services.picom.enable = true; }; } diff --git a/modules/services/picom.nix b/modules/services/picom.nix new file mode 100644 index 000000000..4c4da8de6 --- /dev/null +++ b/modules/services/picom.nix @@ -0,0 +1,311 @@ +{ config, lib, pkgs, ... }: + +with lib; +with builtins; + +let + + cfg = config.services.picom; + + configFile = pkgs.writeText "picom.conf" (optionalString cfg.fade '' + # fading + fading = true; + fade-delta = ${toString cfg.fadeDelta}; + fade-in-step = ${elemAt cfg.fadeSteps 0}; + fade-out-step = ${elemAt cfg.fadeSteps 1}; + fade-exclude = ${toJSON cfg.fadeExclude}; + '' + optionalString cfg.shadow '' + + # shadows + shadow = true; + shadow-offset-x = ${toString (elemAt cfg.shadowOffsets 0)}; + shadow-offset-y = ${toString (elemAt cfg.shadowOffsets 1)}; + shadow-opacity = ${cfg.shadowOpacity}; + shadow-exclude = ${toJSON cfg.shadowExclude}; + '' + optionalString cfg.blur '' + + # blur + blur-background = true; + blur-background-exclude = ${toJSON cfg.blurExclude}; + '' + '' + + # opacity + active-opacity = ${cfg.activeOpacity}; + inactive-opacity = ${cfg.inactiveOpacity}; + inactive-dim = ${cfg.inactiveDim}; + opacity-rule = ${toJSON cfg.opacityRule}; + + wintypes: + { + dock = { shadow = ${toJSON (!cfg.noDockShadow)}; }; + dnd = { shadow = ${toJSON (!cfg.noDNDShadow)}; }; + popup_menu = { opacity = ${cfg.menuOpacity}; }; + dropdown_menu = { opacity = ${cfg.menuOpacity}; }; + }; + + # other options + backend = ${toJSON cfg.backend}; + vsync = ${toJSON cfg.vSync}; + refresh-rate = ${toString cfg.refreshRate}; + '' + cfg.extraOptions); + +in { + + options.services.picom = { + enable = mkEnableOption "Picom X11 compositor"; + + blur = mkOption { + type = types.bool; + default = false; + description = '' + Enable background blur on transparent windows. + ''; + }; + + blurExclude = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "class_g = 'slop'" "class_i = 'polybar'" ]; + description = '' + List of windows to exclude background blur. + See the + + picom + 1 + + man page for more examples. + ''; + }; + + experimentalBackends = mkOption { + type = types.bool; + default = false; + description = '' + Whether to use the new experimental backends. + ''; + }; + + fade = mkOption { + type = types.bool; + default = false; + description = '' + Fade windows in and out. + ''; + }; + + fadeDelta = mkOption { + type = types.int; + default = 10; + example = 5; + description = '' + Time between fade animation step (in ms). + ''; + }; + + fadeSteps = mkOption { + type = types.listOf types.str; + 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 the + + picom + 1 + + man page for more examples. + ''; + }; + + shadow = mkOption { + type = types.bool; + default = false; + description = '' + Draw window shadows. + ''; + }; + + shadowOffsets = mkOption { + type = types.listOf types.int; + default = [ (-15) (-15) ]; + example = [ (-10) (-15) ]; + description = '' + Horizontal and vertical offsets for shadows (in pixels). + ''; + }; + + shadowOpacity = mkOption { + type = types.str; + default = "0.75"; + example = "0.8"; + description = '' + Window shadows opacity (number in range 0 - 1). + ''; + }; + + 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 the + + picom + 1 + + man page for more examples. + ''; + }; + + noDockShadow = mkOption { + type = types.bool; + default = true; + description = '' + Avoid shadow on docks. + ''; + }; + + noDNDShadow = mkOption { + type = types.bool; + default = true; + description = '' + Avoid shadow on drag-and-drop windows. + ''; + }; + + activeOpacity = mkOption { + type = types.str; + default = "1.0"; + example = "0.8"; + description = '' + Opacity of active windows. + ''; + }; + + inactiveDim = mkOption { + type = types.str; + default = "0.0"; + example = "0.2"; + description = '' + Dim inactive windows. + ''; + }; + + inactiveOpacity = mkOption { + type = types.str; + default = "1.0"; + example = "0.8"; + description = '' + Opacity of inactive windows. + ''; + }; + + menuOpacity = mkOption { + type = types.str; + default = "1.0"; + example = "0.8"; + description = '' + Opacity of dropdown and popup menu. + ''; + }; + + opacityRule = mkOption { + type = types.listOf types.str; + default = [ ]; + example = [ "87:class_i ?= 'scratchpad'" "91:class_i ?= 'xterm'" ]; + description = '' + List of opacity rules. + See the + + picom + 1 + + man page for more examples. + ''; + }; + + backend = mkOption { + type = types.str; + default = "glx"; + description = '' + Backend to use: glx or xrender. + ''; + }; + + vSync = mkOption { + type = types.bool; + default = false; + description = '' + Enable vertical synchronization. + ''; + }; + + refreshRate = mkOption { + type = types.int; + default = 0; + example = 60; + description = '' + Screen refresh rate (0 = automatically detect). + ''; + }; + + package = mkOption { + type = types.package; + default = pkgs.picom; + defaultText = literalExample "pkgs.picom"; + example = literalExample "pkgs.picom"; + description = '' + picom derivation to use. + ''; + }; + + extraOptions = mkOption { + type = types.str; + default = ""; + example = '' + unredir-if-possible = true; + dbe = true; + ''; + description = '' + Additional Picom configuration. + ''; + }; + }; + + config = mkIf cfg.enable { + home.packages = [ cfg.package ]; + + systemd.user.services.picom = { + Unit = { + Description = "Picom X11 compositor"; + After = [ "graphical-session-pre.target" ]; + PartOf = [ "graphical-session.target" ]; + }; + + Install = { WantedBy = [ "graphical-session.target" ]; }; + + Service = let + experimentalBackendsFlag = + if cfg.experimentalBackends then " --experimental-backends" else ""; + in { + ExecStart = "${cfg.package}/bin/picom --config ${configFile}" + + experimentalBackendsFlag; + Restart = "always"; + RestartSec = 3; + } // optionalAttrs (cfg.backend == "glx") { + # Temporarily fixes corrupt colours with Mesa 18. + Environment = [ "allow_rgb10_configs=false" ]; + }; + }; + }; +}