2020-04-12 15:42:43 +02:00
|
|
|
{ config, lib, pkgs, ... }:
|
|
|
|
|
|
|
|
with lib;
|
|
|
|
|
|
|
|
let
|
|
|
|
|
|
|
|
cfg = config.services.kanshi;
|
|
|
|
|
|
|
|
outputModule = types.submodule {
|
|
|
|
options = {
|
|
|
|
|
|
|
|
criteria = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
description = ''
|
|
|
|
The criteria can either be an output name, an output description or "*".
|
|
|
|
The latter can be used to match any output.
|
|
|
|
|
|
|
|
On
|
|
|
|
<citerefentry>
|
|
|
|
<refentrytitle>sway</refentrytitle>
|
|
|
|
<manvolnum>1</manvolnum>
|
|
|
|
</citerefentry>,
|
|
|
|
output names and descriptions can be obtained via
|
|
|
|
<literal>swaymsg -t get_outputs</literal>.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
status = mkOption {
|
|
|
|
type = types.nullOr (types.enum [ "enable" "disable" ]);
|
|
|
|
default = null;
|
|
|
|
description = ''
|
|
|
|
Enables or disables the specified output.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
mode = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
example = "1920x1080@60Hz";
|
|
|
|
description = ''
|
|
|
|
<width>x<height>[@<rate>[Hz]]
|
|
|
|
</para><para>
|
|
|
|
Configures the specified output to use the specified mode.
|
|
|
|
Modes are a combination of width and height (in pixels) and
|
|
|
|
a refresh rate (in Hz) that your display can be configured to use.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
position = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
example = "1600,0";
|
|
|
|
description = ''
|
|
|
|
<x>,<y>
|
|
|
|
</para><para>
|
|
|
|
Places the output at the specified position in the global coordinates
|
|
|
|
space.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
scale = mkOption {
|
|
|
|
type = types.nullOr types.float;
|
|
|
|
default = null;
|
|
|
|
example = 2;
|
|
|
|
description = ''
|
|
|
|
Scales the output by the specified scale factor.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
transform = mkOption {
|
|
|
|
type = types.nullOr (types.enum [
|
|
|
|
"normal"
|
|
|
|
"90"
|
|
|
|
"180"
|
|
|
|
"270"
|
|
|
|
"flipped"
|
|
|
|
"flipped-90"
|
|
|
|
"flipped-180"
|
|
|
|
"flipped-270"
|
|
|
|
]);
|
|
|
|
default = null;
|
|
|
|
description = ''
|
|
|
|
Sets the output transform.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
outputStr = { criteria, status, mode, position, scale, transform, ... }:
|
|
|
|
''output "${criteria}"'' + optionalString (status != null) " ${status}"
|
|
|
|
+ optionalString (mode != null) " mode ${mode}"
|
|
|
|
+ optionalString (position != null) " position ${position}"
|
|
|
|
+ optionalString (scale != null) " scale ${toString scale}"
|
|
|
|
+ optionalString (transform != null) " transform ${transform}";
|
|
|
|
|
|
|
|
profileModule = types.submodule {
|
|
|
|
options = {
|
|
|
|
outputs = mkOption {
|
|
|
|
type = types.listOf outputModule;
|
|
|
|
default = [ ];
|
|
|
|
description = ''
|
|
|
|
Outputs configuration.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
exec = mkOption {
|
2021-10-02 23:22:36 +02:00
|
|
|
type = with types; coercedTo str singleton (listOf str);
|
|
|
|
default = [ ];
|
2020-04-12 15:42:43 +02:00
|
|
|
example =
|
2021-10-02 23:22:36 +02:00
|
|
|
"[ \${pkg.sway}/bin/swaymsg workspace 1, move workspace to eDP-1 ]";
|
2020-04-12 15:42:43 +02:00
|
|
|
description = ''
|
2021-10-02 23:22:36 +02:00
|
|
|
Commands executed after the profile is succesfully applied.
|
|
|
|
Note that if you provide multiple commands, they will be
|
|
|
|
executed asynchronously with no guaranteed ordering.
|
2020-04-12 15:42:43 +02:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
profileStr = name:
|
2021-10-02 23:22:36 +02:00
|
|
|
{ outputs, exec, ... }: ''
|
2020-04-12 15:42:43 +02:00
|
|
|
profile ${name} {
|
2021-10-02 23:22:36 +02:00
|
|
|
${
|
|
|
|
concatStringsSep "\n "
|
|
|
|
(map outputStr outputs ++ map (cmd: "exec ${cmd}") exec)
|
|
|
|
}
|
2020-04-12 15:42:43 +02:00
|
|
|
}
|
|
|
|
'';
|
|
|
|
in {
|
|
|
|
|
2021-12-25 19:37:21 +01:00
|
|
|
meta.maintainers = [ hm.maintainers.nurelin ];
|
2020-04-12 15:42:43 +02:00
|
|
|
|
|
|
|
options.services.kanshi = {
|
|
|
|
enable = mkEnableOption
|
|
|
|
"kanshi, a Wayland daemon that automatically configures outputs";
|
|
|
|
|
|
|
|
package = mkOption {
|
|
|
|
type = types.package;
|
|
|
|
default = pkgs.kanshi;
|
2021-10-09 11:14:08 +02:00
|
|
|
defaultText = literalExpression "pkgs.kanshi";
|
2020-04-12 15:42:43 +02:00
|
|
|
description = ''
|
|
|
|
kanshi derivation to use.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
profiles = mkOption {
|
|
|
|
type = types.attrsOf profileModule;
|
|
|
|
default = { };
|
|
|
|
description = ''
|
|
|
|
List of profiles.
|
|
|
|
'';
|
2021-10-09 11:14:08 +02:00
|
|
|
example = literalExpression ''
|
2021-05-16 05:17:48 +02:00
|
|
|
undocked = {
|
|
|
|
outputs = [
|
|
|
|
{
|
|
|
|
criteria = "eDP-1";
|
|
|
|
}
|
|
|
|
];
|
|
|
|
};
|
|
|
|
docked = {
|
|
|
|
outputs = [
|
|
|
|
{
|
|
|
|
criteria = "eDP-1";
|
|
|
|
}
|
|
|
|
{
|
|
|
|
criteria = "Some Company ASDF 4242";
|
|
|
|
transform = "90";
|
|
|
|
}
|
|
|
|
];
|
|
|
|
};
|
|
|
|
'';
|
2020-04-12 15:42:43 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
extraConfig = mkOption {
|
|
|
|
type = types.lines;
|
|
|
|
default = "";
|
|
|
|
description = ''
|
|
|
|
Extra configuration lines to append to the kanshi
|
|
|
|
configuration file.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
systemdTarget = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = "sway-session.target";
|
|
|
|
description = ''
|
|
|
|
Systemd target to bind to.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkIf cfg.enable {
|
2021-07-07 23:24:27 +02:00
|
|
|
assertions = [
|
|
|
|
(lib.hm.assertions.assertPlatform "services.kanshi" pkgs
|
|
|
|
lib.platforms.linux)
|
|
|
|
];
|
2020-04-12 15:42:43 +02:00
|
|
|
|
|
|
|
xdg.configFile."kanshi/config".text = ''
|
|
|
|
${concatStringsSep "\n" (mapAttrsToList profileStr cfg.profiles)}
|
|
|
|
${cfg.extraConfig}
|
|
|
|
'';
|
|
|
|
|
|
|
|
systemd.user.services.kanshi = {
|
|
|
|
Unit = {
|
|
|
|
Description = "Dynamic output configuration";
|
|
|
|
Documentation = "man:kanshi(1)";
|
|
|
|
PartOf = cfg.systemdTarget;
|
|
|
|
Requires = cfg.systemdTarget;
|
|
|
|
After = cfg.systemdTarget;
|
|
|
|
};
|
|
|
|
|
|
|
|
Service = {
|
|
|
|
Type = "simple";
|
|
|
|
ExecStart = "${cfg.package}/bin/kanshi";
|
|
|
|
Restart = "always";
|
|
|
|
};
|
|
|
|
|
|
|
|
Install = { WantedBy = [ cfg.systemdTarget ]; };
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|