Reputation: 2917
I'm currently running a system installed xmobar
on both of my monitors by using the -x
parameter. My xmonad
is custom built with stack and spawns two separate xmobar processes like so:
main :: IO ()
main = do
bars <- traverse (spawnPipe . mappend "xmobar ~/.xmonad/resources/xmobar.hs -x ") ["0", "1"]
xmonad . plugins $
def
{ manageHook = myManageHook,
layoutHook = myLayout,
logHook = for_ bars myLogHook,
}
I want to migrate to custom building my own xmobar instance but if I do, I can't use the -x <screen>
feature unless I implement it myself. I figured, if I'm going to do this myself, why not have my custom xmobar automatically run on multiple screens? So I made this my App/xmobar/Main.hs
import Control.Concurrent (MVar, ThreadId, forkFinally, newEmptyMVar, newMVar, putMVar, takeMVar)
import Control.Concurrent.Async (forConcurrently_)
import XMonad.Theme.XMobar (configFromTheme)
import XMonad.Theme.XResources (loadXResources)
import Xmobar
import Xmobar.App.Opts
-- import Control.Concurrent (forkIO)
type ChildPool = MVar [MVar ()]
main :: IO ()
main = do
children <- newMVar []
config <- fmap configFromTheme <$> loadXResources
let configs = maybe [] (flip fmap [0, 1] . setScreen) config
forConcurrently_ configs $ forkChild children . xmobar
waitForChildren children
where
setScreen config sid = config {position = OnScreen sid (position config)}
forkChild :: ChildPool -> IO () -> IO ThreadId
forkChild children io = do
mvar <- newEmptyMVar
childs <- takeMVar children
putMVar children (mvar : childs)
forkFinally io (const $ putMVar mvar ())
waitForChildren :: ChildPool -> IO ()
waitForChildren children = do
cs <- takeMVar children
case cs of
[] -> return ()
m : ms -> do
putMVar children ms
takeMVar m
waitForChildren children
and updated app/xmonad/Main.hs
to use bar <- spawnPipe "~/.xmonad/xmobar"
This sort of works except there's some bugs:
Updating...
(I think this is just a missing library).UnsafeStdinReader
will only update for one bar at a time and will sometimes not update at all. I suspect this is from both bars fighting over stdin.Is running multiple xmobars from one process possible and I'm just doing it wrong (if so how) or should is this entire attempt a dead end and I should implement a custom -x <SCREENID>
argument and go back to what I was doing before?
Upvotes: 0
Views: 87
Reputation: 2917
I don't have to implement the -x <screen>
feature myself. I can just use the configFromArgs
function exported by Xmobar
.
main :: IO ()
main = do
theme <- loadXResources
let config = maybe defaultConfig configFromTheme theme
xmobar =<< configFromArgs config
is all I need.
Upvotes: 0