diff --git a/modules/modules.nix b/modules/modules.nix index 08a539de..46633f8f 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -289,6 +289,7 @@ let ./services/gromit-mpx.nix ./services/home-manager-auto-upgrade.nix ./services/hound.nix + ./services/hyprland-per-window-layout.nix ./services/imapnotify.nix ./services/kanshi.nix ./services/kbfs.nix diff --git a/modules/services/hyprland-per-window-layout.nix b/modules/services/hyprland-per-window-layout.nix new file mode 100644 index 00000000..e1fb0080 --- /dev/null +++ b/modules/services/hyprland-per-window-layout.nix @@ -0,0 +1,86 @@ +{ config, lib, pkgs, ... }: +with lib; +let + cfg = config.services.hyprland-per-window-layout; + tomlFormat = pkgs.formats.toml { }; + + configFile = tomlFormat.generate "options.toml" cfg.settings; +in { + meta.maintainers = with lib.maintainers; [ azazak123 ]; + + options.services.hyprland-per-window-layout = { + enable = mkEnableOption + "hyprland-per-window-layout, per window keyboard layout (language) for Hyprland Wayland compositor"; + + package = mkPackageOption pkgs "hyprland-per-window-layout" { }; + + settings = mkOption { + type = tomlFormat.type; + default = { }; + example = literalExpression '' + { + # list of keyboards to operate on + # use `hyprctl devices -j` to list all keyboards + keyboards = [ + "lenovo-keyboard" + ]; + + # layout_index => window classes list + # use `hyprctl clients` to get class names + default_layouts = [{ + "1" = [ + "org.telegram.desktop" + ]; + }]; + } + ''; + description = '' + Configuration included in `options.toml`. + For available options see + ''; + }; + + systemdTarget = mkOption { + type = types.str; + default = "graphical-session.target"; + example = "hyprland-session.target"; + description = '' + The systemd target that will automatically start the hyprland-per-window-layout service. + + When setting this value to `"hyprland-session.target"`, + make sure to also enable {option}`wayland.windowManager.hyprland.systemd.enable`, + otherwise the service may never be started. + ''; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "services.hyprland-per-window-layout" + pkgs lib.platforms.linux) + ]; + + home.packages = [ cfg.package ]; + + xdg.configFile."hyprland-per-window-layout/options.toml" = + mkIf (cfg.settings != { }) { source = configFile; }; + + systemd.user.services.hyprland-per-window-layout = { + Unit = { + Description = + "Per window keyboard layout (language) for Hyprland Wayland compositor"; + PartOf = [ cfg.systemdTarget ]; + X-Restart-Triggers = mkIf (cfg.settings != { }) "${configFile}"; + }; + + Service = { + Type = "simple"; + Restart = "on-failure"; + Environment = [ "PATH=${pkgs.hyprland}/bin" ]; + ExecStart = "${cfg.package}/bin/hyprland-per-window-layout"; + }; + + Install = { WantedBy = [ cfg.systemdTarget ]; }; + }; + }; +} diff --git a/tests/default.nix b/tests/default.nix index 97fa3fbb..2b776219 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -228,6 +228,7 @@ in import nmtSrc { ./modules/services/gpg-agent ./modules/services/gromit-mpx ./modules/services/home-manager-auto-upgrade + ./modules/services/hyprland-per-window-layout ./modules/services/imapnotify ./modules/services/kanshi ./modules/services/lieer diff --git a/tests/modules/services/hyprland-per-window-layout/default.nix b/tests/modules/services/hyprland-per-window-layout/default.nix new file mode 100644 index 00000000..7c5ee3cf --- /dev/null +++ b/tests/modules/services/hyprland-per-window-layout/default.nix @@ -0,0 +1,3 @@ +{ + hyprland-per-window-layout-service = ./hyprland-per-window-layout-service.nix; +} diff --git a/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service-expected.service b/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service-expected.service new file mode 100644 index 00000000..dc047baf --- /dev/null +++ b/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service-expected.service @@ -0,0 +1,13 @@ +[Install] +WantedBy=hyprland-session.target + +[Service] +Environment=PATH=@hyprland@/bin +ExecStart=@hyprland-per-window-layout@/bin/hyprland-per-window-layout +Restart=on-failure +Type=simple + +[Unit] +Description=Per window keyboard layout (language) for Hyprland Wayland compositor +PartOf=hyprland-session.target +X-Restart-Triggers=/nix/store/00000000000000000000000000000000-options.toml diff --git a/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service-expected.toml b/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service-expected.toml new file mode 100644 index 00000000..d68a211a --- /dev/null +++ b/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service-expected.toml @@ -0,0 +1,3 @@ +keyboards = ["lenovo-keyboard"] +[[default_layouts]] +1 = ["org.telegram.desktop"] diff --git a/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service.nix b/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service.nix new file mode 100644 index 00000000..596aca8f --- /dev/null +++ b/tests/modules/services/hyprland-per-window-layout/hyprland-per-window-layout-service.nix @@ -0,0 +1,34 @@ +{ config, ... }: + +{ + services.hyprland-per-window-layout = { + enable = true; + systemdTarget = "hyprland-session.target"; + + settings = { + keyboards = [ "lenovo-keyboard" ]; + + default_layouts = [{ "1" = [ "org.telegram.desktop" ]; }]; + }; + }; + + test.stubs = { + hyprland = { }; + hyprland-per-window-layout = { }; + }; + + nmt.script = '' + serviceFile=home-files/.config/systemd/user/hyprland-per-window-layout.service + optionsFile=home-files/.config/hyprland-per-window-layout/options.toml + + assertFileExists $serviceFile + assertFileExists $optionsFile + + assertFileContent $(normalizeStorePaths $serviceFile) ${ + ./hyprland-per-window-layout-service-expected.service + } + assertFileContent $optionsFile ${ + ./hyprland-per-window-layout-service-expected.toml + } + ''; +}