diff --git a/modules/misc/news.nix b/modules/misc/news.nix index 32394f335..bf2f4f09c 100644 --- a/modules/misc/news.nix +++ b/modules/misc/news.nix @@ -1827,6 +1827,21 @@ in { as systemd services. ''; } + + { + time = "2024-11-13T00:12:00+00:00"; + condition = hostPlatform.isLinux; + message = '' + A new module is available: 'wayland.windowManager.wayfire'. + + Wayfire is a 3D Wayland compositor, inspired by Compiz and based on + wlroots. It aims to create a customizable, extendable and lightweight + environment without sacrificing its appearance. + + This Home Manager module allows you to configure both wayfire itself, + as well as wf-shell. + ''; + } ]; }; } diff --git a/modules/modules.nix b/modules/modules.nix index 75f8ac461..cd51ecd4b 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -400,6 +400,7 @@ let ./services/window-managers/i3-sway/swaynag.nix ./services/window-managers/river.nix ./services/window-managers/spectrwm.nix + ./services/window-managers/wayfire.nix ./services/window-managers/xmonad.nix ./services/wlsunset.nix ./services/wob.nix diff --git a/modules/services/window-managers/wayfire.nix b/modules/services/window-managers/wayfire.nix new file mode 100644 index 000000000..c551eb05f --- /dev/null +++ b/modules/services/window-managers/wayfire.nix @@ -0,0 +1,200 @@ +{ lib, pkgs, config, ... }: { + meta.maintainers = [ lib.maintainers._0x5a4 ]; + + options.wayland.windowManager.wayfire = let + types = lib.types; + + configIniType = with types; + let + primitiveType = either str (either bool number); + sectionType = attrsOf primitiveType; + in attrsOf sectionType; + in { + enable = + lib.mkEnableOption "Wayfire, a wayland compositor based on wlroots"; + + package = lib.mkPackageOption pkgs "wayfire" { + nullable = true; + extraDescription = '' + Set to `null` to not add any wayfire package to your path. + This should be done if you want to use the NixOS wayfire module to install wayfire. + ''; + }; + + plugins = lib.mkOption { + type = lib.types.listOf lib.types.package; + default = with pkgs.wayfirePlugins; [ wf-shell ]; + defaultText = + lib.literalExpression "with pkgs.wayfirePlugins; [ wf-shell ]"; + example = lib.literalExpression '' + with pkgs.wayfirePlugins; [ + wcm + wf-shell + wayfire-plugins-extra + ]; + ''; + description = '' + Additional plugins to use with wayfire + ''; + }; + + xwayland.enable = lib.mkEnableOption "XWayland" // { default = true; }; + + settings = lib.mkOption { + type = types.submodule { + freeformType = configIniType; + + options.core.plugins = lib.mkOption { + type = types.separatedString " "; + description = "Load the specified plugins"; + }; + }; + default = { }; + description = '' + Wayfire configuration written in Nix. + + See + ''; + example = lib.literalExpression '' + { + core.plugins = "command expo cube"; + command = { + binding_terminal = "alacritty"; + command_terminal = "alacritty"; + }; + } + ''; + }; + + wf-shell = { + enable = lib.mkEnableOption "Manage wf-shell Configuration"; + + package = lib.mkPackageOption pkgs.wayfirePlugins "wf-shell" { }; + + settings = lib.mkOption { + type = configIniType; + default = { }; + description = '' + Wf-shell configuration written in Nix. + + See + ''; + example = lib.literalExpression '' + { + panel = { + widgets_left = "menu spacing4 launchers window-list"; + autohide = true; + }; + } + ''; + }; + }; + + systemd = { + enable = lib.mkEnableOption null // { + default = true; + description = '' + Whether to enable {file}`wayfire-session.target` on + wayfire startup. This links to {file}`graphical-session.target`}. + Some important environment variables will be imported to systemd + and D-Bus user environment before reaching the target, including + - `DISPLAY` + - `WAYLAND_DISPLAY` + - `XDG_CURRENT_DESKTOP` + - `NIXOS_OZONE_WL` + - `XCURSOR_THEME` + - `XCURSOR_SIZE` + ''; + }; + + variables = lib.mkOption { + type = types.listOf types.str; + default = [ + "DISPLAY" + "WAYLAND_DISPLAY" + "XDG_CURRENT_DESKTOP" + "NIXOS_OZONE_WL" + "XCURSOR_THEME" + "XCURSOR_SIZE" + ]; + example = [ "-all" ]; + description = '' + Environment variables to be imported in the systemd & D-Bus user + environment. + ''; + }; + + extraCommands = lib.mkOption { + type = types.listOf types.str; + default = [ + "systemctl --user stop wayfire-session.target" + "systemctl --user start wayfire-session.target" + ]; + description = "Extra commands to be run after D-Bus activation."; + }; + }; + }; + + config = let + cfg = config.wayland.windowManager.wayfire; + + variables = builtins.concatStringsSep " " cfg.systemd.variables; + extraCommands = builtins.concatStringsSep " " + (map (f: "&& ${f}") cfg.systemd.extraCommands); + systemdActivation = + "${pkgs.dbus}/bin/dbus-update-activation-environment --systemd ${variables} ${extraCommands}"; + + finalPackage = pkgs.wayfire-with-plugins.override { + wayfire = cfg.package; + plugins = cfg.plugins; + }; + in lib.mkIf cfg.enable { + assertions = [ + (lib.hm.assertions.assertPlatform "wayland.windowManager.wayfire" pkgs + lib.platforms.linux) + ]; + + home.packages = lib.mkIf (cfg.package != null) (lib.concatLists [ + (lib.singleton finalPackage) + (lib.optional (cfg.xwayland.enable) pkgs.xwayland) + ]); + + wayland.windowManager.wayfire = { + settings = { + autostart = lib.mkIf cfg.systemd.enable { inherit systemdActivation; }; + core = { + plugins = lib.concatStringsSep " " (lib.concatLists [ + (lib.optional (cfg.systemd.enable) "autostart") + (lib.optional (cfg.wf-shell.enable) "wayfire-shell") + ]); + xwayland = cfg.xwayland.enable; + }; + }; + + plugins = lib.optional cfg.wf-shell.enable cfg.wf-shell.package; + }; + + xdg.configFile."wayfire.ini".text = lib.generators.toINI { } cfg.settings; + + xdg.configFile."wf-shell.ini" = lib.mkIf cfg.wf-shell.enable { + text = lib.generators.toINI { } cfg.wf-shell.settings; + }; + + systemd.user.targets.wayfire-session = lib.mkIf cfg.systemd.enable { + Unit = { + Description = "wayfire compositor session"; + Documentation = [ "man:systemd.special(7)" ]; + BindsTo = [ "graphical-session.target" ]; + Wants = [ "graphical-session-pre.target" ]; + After = [ "graphical-session-pre.target" ]; + }; + }; + + systemd.user.targets.tray = { + Unit = { + Description = "Home Manager System Tray"; + Requires = [ "graphical-session-pre.target" ]; + }; + }; + }; +} diff --git a/tests/default.nix b/tests/default.nix index 2eaaaa436..207e383cb 100644 --- a/tests/default.nix +++ b/tests/default.nix @@ -293,6 +293,7 @@ in import nmtSrc { ./modules/services/window-managers/river ./modules/services/window-managers/spectrwm ./modules/services/window-managers/sway + ./modules/services/window-managers/wayfire ./modules/services/wlsunset ./modules/services/wob ./modules/services/xsettingsd diff --git a/tests/modules/services/window-managers/wayfire/configuration.ini b/tests/modules/services/window-managers/wayfire/configuration.ini new file mode 100644 index 000000000..a40480412 --- /dev/null +++ b/tests/modules/services/window-managers/wayfire/configuration.ini @@ -0,0 +1,10 @@ +[autostart] +systemdActivation=/nix/store/00000000000000000000000000000000-dbus/bin/dbus-update-activation-environment --systemd DISPLAY WAYLAND_DISPLAY XDG_CURRENT_DESKTOP NIXOS_OZONE_WL XCURSOR_THEME XCURSOR_SIZE && systemctl --user stop wayfire-session.target && systemctl --user start wayfire-session.target + +[command] +binding_terminal=alacritty +command_terminal=alacritty + +[core] +plugins=command expo cube autostart +xwayland=true diff --git a/tests/modules/services/window-managers/wayfire/configuration.nix b/tests/modules/services/window-managers/wayfire/configuration.nix new file mode 100644 index 000000000..07042329e --- /dev/null +++ b/tests/modules/services/window-managers/wayfire/configuration.nix @@ -0,0 +1,22 @@ +{ ... }: { + wayland.windowManager.wayfire = { + enable = true; + package = null; + settings = { + core.plugins = "command expo cube"; + command = { + binding_terminal = "alacritty"; + command_terminal = "alacritty"; + }; + }; + }; + + nmt.script = '' + wayfireConfig=home-files/.config/wayfire.ini + + assertFileExists "$wayfireConfig" + + normalizedConfig=$(normalizeStorePaths "$wayfireConfig") + assertFileContent "$normalizedConfig" "${./configuration.ini}" + ''; +} diff --git a/tests/modules/services/window-managers/wayfire/default.nix b/tests/modules/services/window-managers/wayfire/default.nix new file mode 100644 index 000000000..0e252bb19 --- /dev/null +++ b/tests/modules/services/window-managers/wayfire/default.nix @@ -0,0 +1,4 @@ +{ + wayfire-configuration = ./configuration.nix; + wayfire-wf-shell = ./wf-shell.nix; +} diff --git a/tests/modules/services/window-managers/wayfire/wf-shell.ini b/tests/modules/services/window-managers/wayfire/wf-shell.ini new file mode 100644 index 000000000..02472a68a --- /dev/null +++ b/tests/modules/services/window-managers/wayfire/wf-shell.ini @@ -0,0 +1,3 @@ +[panel] +autohide=true +widgets_left=menu spacing4 launchers window-list diff --git a/tests/modules/services/window-managers/wayfire/wf-shell.nix b/tests/modules/services/window-managers/wayfire/wf-shell.nix new file mode 100644 index 000000000..2c8221d80 --- /dev/null +++ b/tests/modules/services/window-managers/wayfire/wf-shell.nix @@ -0,0 +1,25 @@ +{ pkgs, ... }: { + wayland.windowManager.wayfire = { + enable = true; + package = null; + wf-shell = { + enable = true; + package = pkgs.mkStubPackage { }; + settings = { + panel = { + widgets_left = "menu spacing4 launchers window-list"; + autohide = true; + }; + }; + }; + }; + + nmt.script = '' + wfShellConfig=home-files/.config/wf-shell.ini + + assertFileExists "$wfShellConfig" + + normalizedConfig=$(normalizeStorePaths "$wfShellConfig") + assertFileContent "$normalizedConfig" "${./wf-shell.ini}" + ''; +}