diff --git a/modules/modules.nix b/modules/modules.nix index 26d7692f3..e992e43d0 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -419,6 +419,7 @@ let ./services/safeeyes.nix ./services/screen-locker.nix ./services/sctd.nix + ./services/shikane.nix ./services/signaturepdf.nix ./services/skhd.nix ./services/snixembed.nix diff --git a/modules/services/shikane.nix b/modules/services/shikane.nix new file mode 100644 index 000000000..8d44a1dfa --- /dev/null +++ b/modules/services/shikane.nix @@ -0,0 +1,91 @@ +{ + config, + lib, + pkgs, + ... +}: +let + cfg = config.services.shikane; + tomlFormat = pkgs.formats.toml { }; +in +{ + meta.maintainers = [ lib.maintainers.therealr5 ]; + + options.services.shikane = { + + enable = lib.mkEnableOption "shikane, A dynamic output configuration tool that automatically detects and configures connected outputs based on a set of profiles."; + + package = lib.mkPackageOption pkgs "shikane" { }; + + settings = lib.mkOption { + type = tomlFormat.type; + default = { }; + example = lib.literalExpression '' + { + profile = [ + { + name = "external-monitor-default"; + output = [ + { + match = "eDP-1"; + enable = true; + } + { + match = "HDMI-A-1"; + enable = true; + position = { + x = 1920; + y = 0; + }; + } + ]; + } + { + name = "builtin-monitor-only"; + output = [ + { + match = "eDP-1"; + enable = true; + } + ]; + } + ]; + } + ''; + description = '' + Configuration written to + $XDG_CONFIG_HOME/shikane/config.toml. + + See + for more information. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.shikane" pkgs lib.platforms.linux) + ]; + + xdg.configFile."shikane/config.toml" = lib.mkIf (cfg.settings != { }) { + source = tomlFormat.generate "shikane-config" cfg.settings; + }; + + systemd.user.services.shikane = { + Unit = { + Description = "Dynamic output configuration tool"; + Documentation = "man:shikane(1)"; + After = [ config.wayland.systemd.target ]; + PartOf = [ config.wayland.systemd.target ]; + }; + + Service = { + ExecStart = lib.getExe cfg.package; + }; + + Install = { + WantedBy = [ config.wayland.systemd.target ]; + }; + }; + }; +} diff --git a/tests/default.nix b/tests/default.nix index 88b7ea2ac..48d3a2671 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -617,6 +617,7 @@ import nmtSrc { ./modules/services/remmina ./modules/services/restic ./modules/services/screen-locker + ./modules/services/shikane ./modules/services/signaturepdf ./modules/services/snixembed ./modules/services/swayidle diff --git a/tests/modules/services/shikane/basic-configuration.nix b/tests/modules/services/shikane/basic-configuration.nix new file mode 100644 index 000000000..4c01e44be --- /dev/null +++ b/tests/modules/services/shikane/basic-configuration.nix @@ -0,0 +1,47 @@ +{ config, ... }: +{ + config = { + services.shikane = { + enable = true; + package = config.lib.test.mkStubPackage { }; + settings = { + profile = [ + { + name = "external-monitor-default"; + output = [ + { + match = "eDP-1"; + enable = true; + } + { + match = "HDMI-A-1"; + enable = true; + position = { + x = 1920; + y = 0; + }; + } + ]; + } + { + name = "builtin"; + output = [ + { + match = "eDP-1"; + enable = true; + } + ]; + } + ]; + }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/shikane.service + assertFileExists $serviceFile + + assertFileExists home-files/.config/shikane/config.toml + assertFileContent home-files/.config/shikane/config.toml ${./expected.toml} + ''; + }; +} diff --git a/tests/modules/services/shikane/default.nix b/tests/modules/services/shikane/default.nix new file mode 100644 index 000000000..9047cd9b5 --- /dev/null +++ b/tests/modules/services/shikane/default.nix @@ -0,0 +1 @@ +{ shikane-basic-configuration = ./basic-configuration.nix; } diff --git a/tests/modules/services/shikane/expected.toml b/tests/modules/services/shikane/expected.toml new file mode 100644 index 000000000..042243101 --- /dev/null +++ b/tests/modules/services/shikane/expected.toml @@ -0,0 +1,21 @@ +[[profile]] +name = "external-monitor-default" + +[[profile.output]] +enable = true +match = "eDP-1" + +[[profile.output]] +enable = true +match = "HDMI-A-1" + +[profile.output.position] +x = 1920 +y = 0 + +[[profile]] +name = "builtin" + +[[profile.output]] +enable = true +match = "eDP-1"