我当前正在使用
xmobar
参数运行在两台显示器上安装 -x
的系统。我的 xmonad
是使用堆栈自定义构建的,并生成两个独立的 xmobar 进程,如下所示:
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,
}
我想迁移到自定义构建我自己的 xmobar 实例,但如果我这样做,我将无法使用
-x <screen>
功能,除非我自己实现它。我想,如果我要自己做这件事,为什么不让我的自定义 xmobar 自动在多个屏幕上运行? 所以我把它作为我的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
并更新
app/xmonad/Main.hs
以使用 bar <- spawnPipe "~/.xmonad/xmobar"
除了有一些错误之外,这种方法是有效的:
Updating...
(我认为这只是缺少一个库)。UnsafeStdinReader
一次仅更新一根柱,有时根本不更新。我怀疑这是两个酒吧争夺标准输入的结果。是否可以从一个进程运行多个xmobars,而我只是做错了(如果是的话,怎么办)或者这整个尝试应该是一个死胡同,我应该实现一个自定义的
-x <SCREENID>
参数并回到我之前所做的事情?
我不必自己实现
-x <screen>
功能。我可以使用 configFromArgs
导出的 Xmobar
函数。
main :: IO ()
main = do
theme <- loadXResources
let config = maybe defaultConfig configFromTheme theme
xmobar =<< configFromArgs config
这就是我所需要的。