module Xmobar.Plugins.Kbd(Kbd(..)) where
import Data.List (isPrefixOf, findIndex)
import Data.Maybe (fromJust)
import Control.Monad (forever)
import Graphics.X11.Xlib
import Graphics.X11.Xlib.Extras
import Xmobar.Run.Exec
import Xmobar.X11.Events (nextEvent')
import Xmobar.System.Kbd
noLaySymbols :: [String]
noLaySymbols = ["group", "inet", "ctr", "pc", "ctrl"]
splitLayout :: String -> [String]
splitLayout s = splitLayout' noLaySymbols $ split s '+'
splitLayout' :: [String] -> [String] -> [String]
splitLayout' [] s = map (takeWhile (/= ':')) $ filter (not . null) s
splitLayout' bad s =
splitLayout' (tail bad) [x | x <- s, not $ isPrefixOf (head bad) x]
split :: String -> Char -> [String]
split [] _ = [""]
split (c:cs) delim
| c == delim = "" : rest
| otherwise = (c : head rest) : tail rest
where
rest = split cs delim
searchReplaceLayout :: KbdOpts -> String -> String
searchReplaceLayout opts s = let c = findIndex (\x -> fst x == s) opts in
case c of
Nothing -> s
x -> let i = fromJust x in snd $ opts!!i
getKbdLay :: Display -> KbdOpts -> IO String
getKbdLay dpy opts = do
lay <- getLayoutStr dpy
curLay <- getKbdLayout dpy
return $ searchReplaceLayout opts $ splitLayout lay!!curLay
newtype Kbd = Kbd [(String, String)]
deriving (Read, Show)
instance Exec Kbd where
alias (Kbd _) = "kbd"
start (Kbd opts) cb = do
dpy <- openDisplay ""
cb =<< getKbdLay dpy opts
_ <- xkbSelectEventDetails dpy xkbUseCoreKbd xkbStateNotify xkbAllStateComponentsMask xkbGroupStateMask
_ <- xkbSelectEvents dpy xkbUseCoreKbd xkbNewKeyboardNotifyMask xkbNewKeyboardNotifyMask
allocaXEvent $ \e -> forever $ do
nextEvent' dpy e
_ <- getEvent e
cb =<< getKbdLay dpy opts
closeDisplay dpy
return ()