module Graphics.Vty ( Vty(..)
, mkVty
, mkVtyEscDelay
, module Graphics.Vty.Terminal
, module Graphics.Vty.Picture
, module Graphics.Vty.DisplayRegion
, Key(..)
, Modifier(..)
, Button(..)
, Event(..)
)
where
import Graphics.Vty.Terminal
import Graphics.Vty.Picture
import Graphics.Vty.DisplayRegion
import Graphics.Vty.LLInput
import Data.IORef
import qualified System.Console.Terminfo as Terminfo
data Vty = Vty
{
update :: Picture -> IO ()
, next_event :: IO Event
, terminal :: TerminalHandle
, refresh :: IO ()
, shutdown :: IO ()
}
mkVty :: IO Vty
mkVty = mkVtyEscDelay 0
mkVtyEscDelay :: Int -> IO Vty
mkVtyEscDelay escDelay = do
term_info <- Terminfo.setupTermFromEnv
t <- terminal_handle
reserve_display t
(kvar, endi) <- initTermInput escDelay term_info
intMkVty kvar ( endi >> release_display t >> release_terminal t ) t
intMkVty :: IO Event -> IO () -> TerminalHandle -> IO Vty
intMkVty kvar fend t = do
last_pic_ref <- newIORef Nothing
last_update_ref <- newIORef Nothing
let inner_update in_pic = do
b <- display_bounds t
let DisplayRegion w h = b
cursor = pic_cursor in_pic
in_pic' = case cursor of
Cursor x y ->
let
x' = case x of
_ | x >= 0x80000000 -> 0
| x >= w -> w 1
| otherwise -> x
y' = case y of
_ | y >= 0x80000000 -> 0
| y >= h -> h 1
| otherwise -> y
in in_pic { pic_cursor = Cursor x' y' }
_ -> in_pic
mlast_update <- readIORef last_update_ref
update_data <- case mlast_update of
Nothing -> do
d <- display_context t b
output_picture d in_pic'
return (b, d)
Just (last_bounds, last_context) -> do
if b /= last_bounds
then do
d <- display_context t b
output_picture d in_pic'
return (b, d)
else do
output_picture last_context in_pic'
return (b, last_context)
writeIORef last_update_ref $ Just update_data
writeIORef last_pic_ref $ Just in_pic'
let inner_refresh
= writeIORef last_update_ref Nothing
>> readIORef last_pic_ref
>>= maybe ( return () ) ( \pic -> inner_update pic )
let gkey = do k <- kvar
case k of
(EvResize _ _) -> inner_refresh
>> display_bounds t
>>= return . ( \(DisplayRegion w h)
-> EvResize (fromEnum w) (fromEnum h)
)
_ -> return k
return $ Vty { update = inner_update
, next_event = gkey
, terminal = t
, refresh = inner_refresh
, shutdown = fend
}