diff --git a/nixos/modules/services/x11/window-managers/xmonad.nix b/nixos/modules/services/x11/window-managers/xmonad.nix index dba25da8260..b9013ca1ff9 100644 --- a/nixos/modules/services/x11/window-managers/xmonad.nix +++ b/nixos/modules/services/x11/window-managers/xmonad.nix @@ -4,13 +4,15 @@ with lib; let inherit (lib) mkOption mkIf optionals literalExample; cfg = config.services.xserver.windowManager.xmonad; - xmonad = pkgs.xmonad-with-packages.override { + + xmonad-vanilla = pkgs.xmonad-with-packages.override { ghcWithPackages = cfg.haskellPackages.ghcWithPackages; packages = self: cfg.extraPackages self ++ optionals cfg.enableContribAndExtras [ self.xmonad-contrib self.xmonad-extras ]; }; - xmonadBin = pkgs.writers.writeHaskell "xmonad" { + + xmonad-config = pkgs.writers.writeHaskellBin "xmonad" { ghc = cfg.haskellPackages.ghc; libraries = [ cfg.haskellPackages.xmonad ] ++ cfg.extraPackages cfg.haskellPackages ++ @@ -19,8 +21,10 @@ let inherit (cfg) ghcArgs; } cfg.config; -in -{ + xmonad = if (cfg.config != null) then xmonad-config else xmonad-vanilla; +in { + meta.maintainers = with maintainers; [ lassulus xaverdh ]; + options = { services.xserver.windowManager.xmonad = { enable = mkEnableOption "xmonad"; @@ -62,19 +66,50 @@ in default = null; type = with lib.types; nullOr (either path str); description = '' - Configuration from which XMonad gets compiled. If no value - is specified, the xmonad config from $HOME/.xmonad is taken. - If you use xmonad --recompile, $HOME/.xmonad will be taken as - the configuration, but on the next restart of display-manager - this config will be reapplied. + Configuration from which XMonad gets compiled. If no value is + specified, a vanilla xmonad binary is put in PATH, which will + attempt to recompile and exec your xmonad config from $HOME/.xmonad. + This setup is then analogous to other (non-NixOS) linux distributions. + + If you do set this option, you likely want to use "launch" as your + entry point for xmonad (as in the example), to avoid xmonads + recompilation logic on startup. Doing so will render the default + "mod+q" restart key binding dysfunctional though, because that attempts + to call your binary with the "--restart" command line option, unless + you implement that yourself. You way mant to bind "mod+q" to + (restart "xmonad" True) instead, which will just restart + xmonad from PATH. This allows e.g. switching to the new xmonad binary, + after rebuilding your system with nixos-rebuild. + + If you actually want to run xmonad with a config specified here, but + also be able to recompile and restart it from a copy of that source in + $HOME/.xmonad on the fly, you will have to implement that yourself + using something like "compileRestart" from the example. + This should allow you to switch at will between the local xmonad and + the one NixOS puts in your PATH. ''; example = '' import XMonad + import XMonad.Util.EZConfig (additionalKeys) + import Text.Printf (printf) + import System.Posix.Process (executeFile) + import System.Info (arch,os) + import System.Environment (getArgs) + import System.FilePath (()) + + compiledConfig = printf "xmonad-%s-%s" arch os + + compileRestart = whenX (recompile True) . catchIO $ do + dir <- getXMonadDataDir + args <- getArgs + executeFile (dir compiledConfig) False args Nothing main = launch defaultConfig - { modMask = mod4Mask -- Use Super instead of Alt - , terminal = "urxvt" - } + { modMask = mod4Mask -- Use Super instead of Alt + , terminal = "urxvt" } + `additionalKeys` + [ ( (mod4Mask,xK_r), compileRestart ) + , ( (mod4Mask,xK_q), restart "xmonad" True ) ] ''; }; @@ -101,10 +136,8 @@ in services.xserver.windowManager = { session = [{ name = "xmonad"; - start = let - xmonadCommand = if (cfg.config != null) then xmonadBin else "${xmonad}/bin/xmonad"; - in '' - systemd-cat -t xmonad -- ${xmonadCommand} ${lib.escapeShellArgs cfg.xmonadCliArgs} & + start = '' + systemd-cat -t xmonad -- ${xmonad}/bin/xmonad ${lib.escapeShellArgs cfg.xmonadCliArgs} & waitPID=$! ''; }]; diff --git a/nixos/tests/xmonad.nix b/nixos/tests/xmonad.nix index 56baae8b9d3..308dbca154f 100644 --- a/nixos/tests/xmonad.nix +++ b/nixos/tests/xmonad.nix @@ -14,9 +14,16 @@ import ./make-test-python.nix ({ pkgs, ...} : { extraPackages = with pkgs.haskellPackages; haskellPackages: [ xmobar ]; config = '' import XMonad + import XMonad.Operations (restart) import XMonad.Util.EZConfig - main = launch $ def `additionalKeysP` myKeys - myKeys = [ ("M-C-x", spawn "xterm") ] + import XMonad.Util.SessionStart + + main = launch $ def { startupHook = startup } `additionalKeysP` myKeys + + startup = isSessionStart >>= \sessInit -> + if sessInit then setSessionStarted else spawn "xterm" + + myKeys = [ ("M-C-x", spawn "xterm"), ("M-q", restart "xmonad" True) ] ''; }; }; @@ -30,12 +37,11 @@ import ./make-test-python.nix ({ pkgs, ...} : { machine.send_key("alt-ctrl-x") machine.wait_for_window("${user.name}.*machine") machine.sleep(1) - machine.screenshot("terminal") - machine.wait_until_succeeds("xmonad --restart") + machine.screenshot("terminal1") + machine.send_key("alt-q") machine.sleep(3) - machine.send_key("alt-shift-ret") machine.wait_for_window("${user.name}.*machine") machine.sleep(1) - machine.screenshot("terminal") + machine.screenshot("terminal2") ''; })