Linux – XMonad, spawn mutliple terminals on startup on different workspaces

haskelllinuxUbuntuxmonad

Is it possible to spawn multiple terminals on startup on different workspaces?
I have a bunch of terminals and Firefox which I would like to have running on startup. XMonad places Firefox correctly, but places all the terminals in one workspace. Why is this happening? If my approach is not possible, is there another one? Thank you for your help.

Here is the important part of my XMonad.hs:

main = do
       xmproc <- spawnPipe "/home/x/.local/bin/xmobar /home/x/.xmobar/.xmobarrc"
    xmonad $ ewmh $ defaultConfig
  --  { manageHook          = manageDocks <+> manageHook defaultConfig <+> manageSpawn       -- myManageHook  
  --  { manageHook          = manageSpawn <+> manageDocks <+> manageHook defaultConfig       -- myManageHook 
      { manageHook          = manageDocks <+> manageSpawn <+> manageHook defaultConfig       -- myManageHook 
      , layoutHook          = myLayout
      , handleEventHook     = handleEventHook defaultConfig <+> docksEventHook
      , logHook             = myLogHook xmproc
      , modMask             = myModMask
      , terminal            = myTerminal
      , workspaces          = myWorkspaces
      , startupHook         = myStartupHook
      }  `additionalKeys` myKeys

 myLayout = avoidStruts $ layoutHook defaultConfig

 myWorkspaces :: [WorkspaceId]
 myWorkspaces = ["1:system", "2:network", "3:browser", "4:work1", "5:terminal", "6:work2", "7:files", "8:tutorial", "9:music"]

 myModMask = mod4Mask
 myTerminal = "gnome-terminal"

 myStartupHook :: X ()
 myStartupHook = do
                setWMName "LG3D"
                setDefaultCursor xC_left_ptr
            --  spawnOnce "redshift -l 40.7142:-74.0064 -t 6500:4800"
                spawnOnce "feh --bg-scale Pictures/los.jpg"
                spawnOnce "stalonetray --dockapp-mode simple -c ~/.xmobar/.stalonetrayrc"
                mySpawn "1:system"   "gnome-terminal --tab -e \"/bin/bash -c 'htop; exec /bin/bash -i'\""
                mySpawn "1:system"   "gnome-terminal --tab -e \"/bin/bash -c 'dmesg -TL --follow; exec /bin/bash -i'\""
                mySpawn "2:network"  "gnome-terminal"
                mySpawn "3:browser"  "firefox"
                mySpawn "4:work1"    "gnome-terminal"
                mySpawn "5:terminal" "gnome-terminal"
                mySpawn "6:work2"    "gnome-terminal"
                mySpawn "7:files"    "gnome-terminal --tab -e \"/bin/bash -c 'nnn; exec /bin/bash -i'\""
                mySpawn "8:tutorial" "gnome-terminal --tab -e \"/bin/bash -c 'vim tutorial.txt/; exec /bin/bash -i'\""
                mySpawn "9:music"    "gnome-terminal --tab -e \"/bin/bash -c 'cmus; exec /bin/bash -i'\""


mySpawn :: String -> String -> X ()
mySpawn workspace program = do
                            --spawn program   
                            --windows $ W.greedyView workspace
                            spawnOn workspace program

Best Answer

Yes it is possible.

One way to do it is with the xmonad-contrib package using spawnOn

Here is how I used it in a triple monitor setup to start a terminal on each screen on startup.

import XMonad
import XMonad.Hooks.EwmhDesktops
import XMonad.Hooks.SetWMName
import qualified Data.Map as M
import XMonad.Prompt.XMonad
import XMonad.Actions.SpawnOn -- *[This is the important part]*

main :: IO()
main =
  xmonad $
  ewmh
    def
      { modMask = mod4Mask -- Use Super instead of Alt
      , terminal = "urxvt"
      , startupHook = myStartupHook
      , manageHook = manageSpawn <+> myManageHooks
      , borderWidth = 1
      , normalBorderColor = "#000000"
      , focusedBorderColor = "#FFFF00"
      , keys = myKeys <+> keys def
      }

myKeys :: XConfig t -> M.Map (KeyMask, KeySym) (X ())
myKeys conf@(XConfig {XMonad.modMask = modm}) =
  M.fromList
    [ ((modm, xK_F12), xmonadPrompt def)
    , ((modm, xK_b), spawn "/usr/bin/firefox")
    , ((modm, xK_p), spawn "/usr/bin/keepassxc")
    ]

myManageHooks :: ManageHook
myManageHooks = composeAll [ stringProperty "_NET_WM_NAME" =? "Emulator" --> doFloat ]

myStartupHook :: X ()
myStartupHook = composeAll
  [ setWMName "LG3D"
  , spawnOn "1" "/usr/bin/urxvt" -- *[Pass the workspace id and the program to spawn]*
  , spawnOn "2" "/usr/bin/urxvt"
  , spawnOn "3" "/usr/bin/urxvt"
  ]                                                                           
Related Question