{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LiberalTypeSynonyms #-} {-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE ViewPatterns #-} -- | A conduit interface to XInput events. module Data.Conduit.XInput (xinputSource ,Device(..) ,Event(..) ,KeyCode(..)) where import Control.Monad.IO.Class import Control.Monad.Trans.Class import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as S8 import Data.Conduit import qualified Data.Conduit.Binary as CB import qualified Data.Conduit.List as CL import Data.Conduit.Process import Data.Monoid import System.Exit -- | Device identifier. newtype Device = Device Int deriving (Num) -- | An event. data Event = Press | Release deriving (Enum,Bounded,Eq,Show) -- | Key code. newtype KeyCode = KeyCode Int deriving (Eq,Show,Num,Ord) -- | Source of xinput keys. xinputSource :: MonadIO m => Device -> ConduitM i (Event,KeyCode) m ExitCode xinputSource (Device device) = do (exitCode,()) <- sourceCmdWithConsumer ("unbuffer xinput test " <> show device) (CB.lines $= CL.mapMaybe parse $= awaitForever (lift . yield)) return exitCode -- | Parse an xinput test line. parse :: ByteString -> Maybe (Event,KeyCode) parse line = case S8.words (S8.drop 4 line) of [mode,S8.readInt -> Just (code,_)] -> return (if mode == "release" then Release else Press ,KeyCode code) _ -> Nothing