mirror of
https://github.com/nix-community/home-manager
synced 2024-11-15 23:59:45 +01:00
9f9e277b60
These (and the `*MD` functions apart from `literalMD`) are now no-ops in nixpkgs and serve no purpose other than to add additional noise and potentially mislead people into thinking unmarked DocBook documentation will still be accepted. Note that if backporting changes including documentation to 23.05, the `mdDoc` calls will need to be re-added. To reproduce this commit, run: $ NIX_PATH=nixpkgs=flake:nixpkgs/e7e69199f0372364a6106a1e735f68604f4c5a25 \ nix shell nixpkgs#coreutils \ -c find . -name '*.nix' \ -exec nix run -- github:emilazy/nix-doc-munge/98dadf1f77351c2ba5dcb709a2a171d655f15099 \ --strip {} + $ ./format
380 lines
10 KiB
Nix
380 lines
10 KiB
Nix
{ config, lib, pkgs, stdenv, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
cfg = config.services.twmn;
|
|
|
|
animationOpts = {
|
|
curve = mkOption {
|
|
type = types.ints.between 0 40;
|
|
default = 38;
|
|
example = 19;
|
|
description = ''
|
|
The qt easing-curve animation to use for the animation. See
|
|
[
|
|
QEasingCurve documentation](https://doc.qt.io/qt-5/qeasingcurve.html#Type-enum).
|
|
'';
|
|
};
|
|
|
|
duration = mkOption {
|
|
type = types.ints.unsigned;
|
|
default = 1000;
|
|
example = 618;
|
|
description = "The animation duration in milliseconds.";
|
|
};
|
|
};
|
|
|
|
in {
|
|
meta.maintainers = [ hm.maintainers.austreelis ];
|
|
|
|
options.services.twmn = {
|
|
enable = mkEnableOption "twmn, a tiling window manager notification daemon";
|
|
|
|
duration = mkOption {
|
|
type = types.ints.unsigned;
|
|
default = 3000;
|
|
example = 5000;
|
|
description = ''
|
|
The time each notification remains visible, in milliseconds.
|
|
'';
|
|
};
|
|
|
|
extraConfig = mkOption {
|
|
type = types.attrs;
|
|
default = { };
|
|
example = literalExpression
|
|
''{ main.activation_command = "\${pkgs.hello}/bin/hello"; }'';
|
|
description = ''
|
|
Extra configuration options to add to the twmnd config file. See
|
|
<https://github.com/sboli/twmn/blob/master/README.md>
|
|
for details.
|
|
'';
|
|
};
|
|
|
|
host = mkOption {
|
|
type = types.str;
|
|
default = "127.0.0.1";
|
|
example = "laptop.lan";
|
|
description = "Host address to listen on for notifications.";
|
|
};
|
|
|
|
icons = {
|
|
critical = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = "Path to the critical notifications' icon.";
|
|
};
|
|
|
|
info = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = "Path to the informative notifications' icon.";
|
|
};
|
|
|
|
warning = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = "Path to the warning notifications' icon.";
|
|
};
|
|
};
|
|
|
|
port = mkOption {
|
|
type = types.port;
|
|
default = 9797;
|
|
description = "UDP port to listen on for notifications.";
|
|
};
|
|
|
|
screen = mkOption {
|
|
type = types.nullOr types.int;
|
|
default = null;
|
|
example = 0;
|
|
description = ''
|
|
Screen number to display notifications on when using a multi-head
|
|
desktop.
|
|
'';
|
|
};
|
|
|
|
soundCommand = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = "Command to execute to play a notification's sound.";
|
|
};
|
|
|
|
text = {
|
|
color = mkOption {
|
|
type = types.str;
|
|
default = "#999999";
|
|
example = "lightgray";
|
|
description = ''
|
|
Notification's text color. RGB hex and keywords (e.g. `lightgray`)
|
|
are supported.
|
|
'';
|
|
};
|
|
|
|
font = {
|
|
package = mkOption {
|
|
type = types.nullOr types.package;
|
|
default = null;
|
|
example = literalExpression "pkgs.dejavu_fonts";
|
|
description = ''
|
|
Notification text's font package. If `null` then
|
|
the font is assumed to already be available in your profile.
|
|
'';
|
|
};
|
|
|
|
family = mkOption {
|
|
type = types.str;
|
|
default = "Sans";
|
|
example = "Noto Sans";
|
|
description = "Notification text's font family.";
|
|
};
|
|
|
|
size = mkOption {
|
|
type = types.ints.unsigned;
|
|
default = 13;
|
|
example = 42;
|
|
description = "Notification text's font size.";
|
|
};
|
|
|
|
variant = mkOption {
|
|
# These are the font variant supported by twmn
|
|
# See https://github.com/sboli/twmn/blob/master/README.md?plain=1#L42
|
|
type = types.enum [
|
|
"oblique"
|
|
"italic"
|
|
"ultra-light"
|
|
"light"
|
|
"medium"
|
|
"semi-bold"
|
|
"bold"
|
|
"ultra-bold"
|
|
"heavy"
|
|
"ultra-condensed"
|
|
"extra-condensed"
|
|
"condensed"
|
|
"semi-condensed"
|
|
"semi-expanded"
|
|
"expanded"
|
|
"extra-expanded"
|
|
"ultra-expanded"
|
|
];
|
|
default = "medium";
|
|
example = "heavy";
|
|
description = "Notification text's font variant.";
|
|
};
|
|
};
|
|
|
|
maxLength = mkOption {
|
|
type = types.nullOr types.ints.unsigned;
|
|
default = null;
|
|
example = 80;
|
|
description = ''
|
|
Maximum length of the text before it is cut and suffixed with "...".
|
|
Never cuts if `null`.
|
|
'';
|
|
};
|
|
};
|
|
|
|
window = {
|
|
alwaysOnTop =
|
|
mkEnableOption "forcing the notification window to always be on top";
|
|
|
|
animation = {
|
|
easeIn = mkOption {
|
|
type = types.submodule { options = animationOpts; };
|
|
default = { };
|
|
example = literalExpression ''
|
|
{
|
|
curve = 19;
|
|
duration = 618;
|
|
}
|
|
'';
|
|
description = "Options for the notification appearance's animation.";
|
|
};
|
|
|
|
easeOut = mkOption {
|
|
type = types.submodule { options = animationOpts; };
|
|
default = { };
|
|
example = literalExpression ''
|
|
{
|
|
curve = 19;
|
|
duration = 618;
|
|
}
|
|
'';
|
|
description =
|
|
"Options for the notification disappearance's animation.";
|
|
};
|
|
|
|
bounce = {
|
|
enable = mkEnableOption
|
|
"notification bounce when displaying next notification directly";
|
|
|
|
duration = mkOption {
|
|
type = types.ints.unsigned;
|
|
default = 500;
|
|
example = 618;
|
|
description = "The bounce animation duration in milliseconds.";
|
|
};
|
|
};
|
|
};
|
|
|
|
color = mkOption {
|
|
type = types.str;
|
|
default = "#000000";
|
|
example = "lightgray";
|
|
description = ''
|
|
Notification's background color. RGB hex and keywords (e.g.
|
|
`lightgray`) are supported.
|
|
'';
|
|
};
|
|
|
|
height = mkOption {
|
|
type = types.ints.unsigned;
|
|
default = 18;
|
|
example = 42;
|
|
description = ''
|
|
Height of the slide bar. Useful to match your tiling window
|
|
manager's bar.
|
|
'';
|
|
};
|
|
|
|
offset = {
|
|
x = mkOption {
|
|
type = types.int;
|
|
default = 0;
|
|
example = 50;
|
|
description = ''
|
|
Offset of the notification's slide starting point in pixels on the
|
|
horizontal axis (positive is rightward).
|
|
'';
|
|
};
|
|
|
|
y = mkOption {
|
|
type = types.int;
|
|
default = 0;
|
|
example = -100;
|
|
description = ''
|
|
Offset of the notification's slide starting point in pixels on the
|
|
vertical axis (positive is upward).
|
|
'';
|
|
};
|
|
};
|
|
|
|
opacity = mkOption {
|
|
type = types.ints.between 0 100;
|
|
default = 100;
|
|
example = 80;
|
|
description = "The notification window's opacity.";
|
|
};
|
|
|
|
position = mkOption {
|
|
type = types.enum [
|
|
"tr"
|
|
"top_right"
|
|
"tl"
|
|
"top_left"
|
|
"br"
|
|
"bottom_right"
|
|
"bl"
|
|
"bottom_left"
|
|
"tc"
|
|
"top_center"
|
|
"bc"
|
|
"bottom_center"
|
|
"c"
|
|
"center"
|
|
];
|
|
default = "top_right";
|
|
example = "bottom_left";
|
|
description = ''
|
|
Position of the notification slide. The notification will slide
|
|
in vertically from the border if placed in
|
|
`top_center` or `bottom_center`,
|
|
horizontally otherwise.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
|
|
#################
|
|
# Implementation
|
|
|
|
config = mkIf cfg.enable {
|
|
assertions = [
|
|
(lib.hm.assertions.assertPlatform "services.twmn" pkgs
|
|
lib.platforms.linux)
|
|
];
|
|
|
|
home.packages =
|
|
lib.optional (!isNull cfg.text.font.package) cfg.text.font.package
|
|
++ [ pkgs.twmn ];
|
|
|
|
xdg.configFile."twmn/twmn.conf".text = let
|
|
conf = recursiveUpdate {
|
|
gui = {
|
|
always_on_top = if cfg.window.alwaysOnTop then "true" else "false";
|
|
background_color = cfg.window.color;
|
|
bounce =
|
|
if cfg.window.animation.bounce.enable then "true" else "false";
|
|
bounce_duration = toString cfg.window.animation.bounce.duration;
|
|
font = cfg.text.font.family;
|
|
font_size = toString cfg.text.font.size;
|
|
font_variant = cfg.text.font.variant;
|
|
foreground_color = cfg.text.color;
|
|
height = toString cfg.window.height;
|
|
in_animation = toString cfg.window.animation.easeIn.curve;
|
|
in_animation_duration = toString cfg.window.animation.easeIn.duration;
|
|
max_length = toString
|
|
(if isNull cfg.text.maxLength then -1 else cfg.text.maxLength);
|
|
offset_x = with cfg.window.offset;
|
|
if x < 0 then toString x else "+${toString x}";
|
|
offset_y = with cfg.window.offset;
|
|
if y < 0 then toString y else "+${toString y}";
|
|
opacity = toString cfg.window.opacity;
|
|
out_animation = toString cfg.window.animation.easeOut.curve;
|
|
out_animation_duration =
|
|
toString cfg.window.animation.easeOut.duration;
|
|
position = cfg.window.position;
|
|
screen = toString cfg.screen;
|
|
};
|
|
# map null values to empty strings because formats.toml generator fails
|
|
# when encountering a null.
|
|
icons = mapAttrs (_: toString) cfg.icons;
|
|
main = {
|
|
duration = toString cfg.duration;
|
|
host = cfg.host;
|
|
port = toString cfg.port;
|
|
sound_command = cfg.soundCommand;
|
|
};
|
|
} cfg.extraConfig;
|
|
|
|
mkLine = name: value: "${name}=${value}";
|
|
|
|
mkSection = section: conf: ''
|
|
[${section}]
|
|
${concatStringsSep "\n" (mapAttrsToList mkLine conf)}
|
|
'';
|
|
in concatStringsSep "\n" (mapAttrsToList mkSection conf) + "\n";
|
|
|
|
systemd.user.services.twmnd = {
|
|
Unit = {
|
|
Description = "twmn daemon";
|
|
After = [ "graphical-session-pre.target" ];
|
|
PartOf = [ "graphical-session.target" ];
|
|
X-Restart-Triggers =
|
|
[ "${config.xdg.configFile."twmn/twmn.conf".source}" ];
|
|
};
|
|
|
|
Install.WantedBy = [ "graphical-session.target" ];
|
|
|
|
Service = {
|
|
ExecStart = "${pkgs.twmn}/bin/twmnd";
|
|
Restart = "on-failure";
|
|
Type = "simple";
|
|
StandardOutput = "null";
|
|
};
|
|
};
|
|
};
|
|
}
|