{-# LANGUAGE TypeApplications #-} module Termbox.Event ( Event (..), poll, PollError (..), ) where import Control.Exception (Exception, throwIO) import Data.Char (chr) import Data.Int (Int32) import Data.Semigroup (Semigroup (..)) import Data.Word (Word32) import Foreign.Marshal.Alloc (alloca) import Foreign.Storable (peek) import Termbox.Internal import Termbox.Key (Key (KeyChar), parseKey) import Termbox.Mouse (Mouse, parseMouse) import Prelude hiding (mod) -- | A input event. data Event = -- | Key event EventKey !Key | -- | Resize event (width, then height) EventResize !Int !Int | -- | Mouse event (column, then row) EventMouse !Mouse !Int !Int deriving (Eq, Show) -- | Block until an 'Event' arrives. -- -- /Throws/: 'PollError' poll :: IO Event poll = alloca $ \ptr -> tb_poll_event ptr >>= \case -1 -> throwIO PollError _ -> parseEvent <$> peek ptr -- | An error occurred when polling, due to mysterious circumstances that are not well-documented in the original C -- codebase. data PollError = PollError deriving (Show) instance Exception PollError -- | Parse an 'Event' from a 'TbEvent'. parseEvent :: TbEvent -> Event parseEvent (TbEvent typ _mod key ch w h x y) | typ == tB_EVENT_KEY = EventKey (if ch == 0 then parseKey key else KeyChar (chr (fromIntegral @Word32 @Int ch))) | typ == tB_EVENT_RESIZE = EventResize (fromIntegral @Int32 @Int w) (fromIntegral @Int32 @Int h) | typ == tB_EVENT_MOUSE = EventMouse (parseMouse key) (fromIntegral @Int32 @Int x) (fromIntegral @Int32 @Int y) | otherwise = error ("termbox: unknown event type " ++ show typ)