I have an issue with a function I took from XMonad.Util.Dmenu, namely dmenuXinerama (see below). It seems like this is happening:
These functions block xmonad's event loop until dmenu exits; this means that programs will not be able to open new windows and you will not be able to change workspaces or input focus until you have responded to the prompt one way or another.
What happens is that I spawn a menu instance and it appears, but once I run something from there, everything is blocked, and I can't do anything.
This is the function:
dmenuXinerama :: [String] -> X String
dmenuXinerama opts = do
curscreen <- (fromIntegral . W.screen . W.current) `fmap` gets windowset :: X Int
io $ runProcessWithInput "dmenu_run" ["-m", show curscreen] (unlines opts)
... and a binding:
-- Spawn dmenu
, ((modMask, xK_p), void $ dmenuXinerama [])
I've also tried this:
dmenuXinerama :: [String] -> X String
dmenuXinerama opts = do
curscreen <-
(fromIntegral . W.screen . W.current) `fmap` gets windowset :: X Int
_ <-
runProcessWithInput "dmenu_run" ["-m", show curscreen] (unlines opts)
menuArgs "dmenu_run" ["-m", show curscreen] opts
-- | Like 'menu' but also takes a list of command line arguments.
menuArgs :: MonadIO m => String -> [String] -> [String] -> m String
menuArgs menuCmd args opts = liftM (filter (/='\n')) $
runProcessWithInput menuCmd args (unlines opts)
I'd appreciate it if someone explained what's going on and how can I overcome the issue.
I think dmenu_run
doesn't exit (until the program you start with it does), so it is not suitable for use with runProcessWithInput
. Use dmenu_path
and dmenu
instead, then spawn
the result.
pickExe :: X ()
pickExe = do
exes <- runProcessWithInput "dmenu_path" [] ""
exe <- dmenuXinerama (lines exes)
spawn exe
The dmenuXinerama
in the above snippet is the one you can import from XMonad.Util.Dmenu
, not your modified one from the question. (And spawn
is from XMonad.Core
.)
If you are comfortable with the Monad
interface, you might prefer to write that without the temporary names like this:
pickExe = spawn =<< dmenuXinerama . lines =<< runProcessWithInput "dmenu_path" [] ""