问题
One of the key bindings in my ~/.xmonad/xmonad.hs
file is this:
((modMask .|. shiftMask, xK_q), io (exitWith ExitSuccess))
So, I tried to use this pattern to make a binding that would cycle through keyboard layouts. I have cycleKLayouts :: IO ()
, which works perfectly when run from ghci
. Then, I write:
((modMask, xK_minus), io cycleKLayouts)
This compiles fine, but when I try the key, the only thing that happens is that the current terminal and the one the mouse is under (both Terminology) flash faintly. This is different to what happens with an unbound key, which just passes the letter through to the application.
I've also tried liftIO
, rather than io
, with the same results. I also have a direct spawn
binding:
((modMask, xK_equal), spawn "setxkbmap -v gb -variant colemak")
which works, but provides a different behaviour. (cycleKLayouts
runs setxkbmap
at some point).
Edit: definition of cycleKLayouts
:
module Keyboards where
import System.Process
import Control.Applicative
kLayouts = [("gb(colemak)", "UK-CO")
,("gb", "UK-QW")
,("us(colemak)", "US-CO")
,("us", "US-QW")]
getKLayout :: IO String
getKLayout = f . (!! 4) . lines <$> readProcess "setxkbmap" ["-print"] []
where
f ('+':cs) = g cs
f (_:cs) = f cs
f _ = ""
g ('+':_) = ""
g (c:cs) = c:g cs
g _ = ""
getNextKLayout :: IO String
getNextKLayout = do
l <- getKLayout
let kLayoutNames = map fst kLayouts
let f (x:y:xs) = if x == l then y else f (y:xs)
f _ = head kLayoutNames
return $ f kLayoutNames
setKLayout :: String -> IO ()
setKLayout l = readProcess "setxkbmap" ["-v", l] [] >> return ()
cycleKLayouts :: IO ()
cycleKLayouts = setKLayout =<< getNextKLayout
回答1:
Rewriting cycleKLayouts
in such a way that it has type X ()
and runs your command with spawn
, certainly should help. I guess the problem lies in the way that cycleKLayouts
runs the command. Probably in result setxkbmap
doesn't have access to your environment variables, or gets forked and then terminated.
If you post the source of cycleKLayouts
I probably would be able to give more specific answer.
Update:
Well, I've just tried to add this to my configuration:
((modMask, xK_a), liftIO (readProcess "setxkbmap" ["-print"] "" >>= putStrLn))
Whenever I was pressing M-a
an error message "waitForProcess: does not exist (no child process)". I can't really explain a reason for that, but I guess it has to do with the way Xmonad spawns keybinded actions (probably it's a potential bug).
However, replacing readProcess
to runProcessWithInput
(from Xmonad.Util.Run) solved the problem completely:
((modMask, xK_a), liftIO (runProcessWithInput "setxkbmap" ["-print"] "" >>= putStrLn))
Try this to make sure that we catched on the same problem.
来源:https://stackoverflow.com/questions/26562522/xmonad-io-binding-not-working