From 78a0bbb38bb8d2523b1f9007d9460d6185133b61 Mon Sep 17 00:00:00 2001 From: Ruby Iris Juric Date: Mon, 23 Mar 2020 10:56:34 +1100 Subject: [PATCH] picom: add module Nixpkgs no longer packages compton, and instead packages picom, a (mostly) compatible fork of compton, providing an alias from compton to picom. Because some configuration options have been changed, and all references to "compton" have been made deprecated and replaced with "picom", 'services.compton' has been deprecated in favor of the new 'services.picom'. Resolves #878 PR #1101 --- doc/release-notes/rl-2003.adoc | 5 + modules/misc/news.nix | 28 +++ modules/modules.nix | 1 + modules/services/compton.nix | 328 ++++----------------------------- modules/services/picom.nix | 311 +++++++++++++++++++++++++++++++ 5 files changed, 380 insertions(+), 293 deletions(-) create mode 100644 modules/services/picom.nix 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" ]; + }; + }; + }; +}