{-# LANGUAGE CPP #-}
module Ui.Fltk (
Fltk, fltk, Channel, event_loop, send_action, quit_ui_thread
) where
#ifdef STUB_OUT_FLTK
import Ui.FltkStub
#else
import qualified Control.Concurrent.MVar as MVar
import qualified Control.Concurrent.STM as STM
import qualified Control.Exception as Exception
import qualified Foreign
import qualified Foreign.C as C
import qualified Util.FFI as FFI
import qualified Util.Log as Log
import qualified Ui.UiMsg as UiMsg
import qualified Ui.UiMsgC as UiMsgC
import Global
action_timing :: Bool
action_timing :: Bool
action_timing = Bool
False
newtype Fltk a = Fltk (IO a)
deriving (Functor Fltk
forall a. a -> Fltk a
forall a b. Fltk a -> Fltk b -> Fltk a
forall a b. Fltk a -> Fltk b -> Fltk b
forall a b. Fltk (a -> b) -> Fltk a -> Fltk b
forall a b c. (a -> b -> c) -> Fltk a -> Fltk b -> Fltk c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: forall a b. Fltk a -> Fltk b -> Fltk a
$c<* :: forall a b. Fltk a -> Fltk b -> Fltk a
*> :: forall a b. Fltk a -> Fltk b -> Fltk b
$c*> :: forall a b. Fltk a -> Fltk b -> Fltk b
liftA2 :: forall a b c. (a -> b -> c) -> Fltk a -> Fltk b -> Fltk c
$cliftA2 :: forall a b c. (a -> b -> c) -> Fltk a -> Fltk b -> Fltk c
<*> :: forall a b. Fltk (a -> b) -> Fltk a -> Fltk b
$c<*> :: forall a b. Fltk (a -> b) -> Fltk a -> Fltk b
pure :: forall a. a -> Fltk a
$cpure :: forall a. a -> Fltk a
Applicative, forall a b. a -> Fltk b -> Fltk a
forall a b. (a -> b) -> Fltk a -> Fltk b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: forall a b. a -> Fltk b -> Fltk a
$c<$ :: forall a b. a -> Fltk b -> Fltk a
fmap :: forall a b. (a -> b) -> Fltk a -> Fltk b
$cfmap :: forall a b. (a -> b) -> Fltk a -> Fltk b
Functor, Applicative Fltk
forall a. a -> Fltk a
forall a b. Fltk a -> Fltk b -> Fltk b
forall a b. Fltk a -> (a -> Fltk b) -> Fltk b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: forall a. a -> Fltk a
$creturn :: forall a. a -> Fltk a
>> :: forall a b. Fltk a -> Fltk b -> Fltk b
$c>> :: forall a b. Fltk a -> Fltk b -> Fltk b
>>= :: forall a b. Fltk a -> (a -> Fltk b) -> Fltk b
$c>>= :: forall a b. Fltk a -> (a -> Fltk b) -> Fltk b
Monad, Monad Fltk
forall a. IO a -> Fltk a
forall (m :: * -> *).
Monad m -> (forall a. IO a -> m a) -> MonadIO m
liftIO :: forall a. IO a -> Fltk a
$cliftIO :: forall a. IO a -> Fltk a
MonadIO)
fltk :: IO a -> Fltk a
fltk :: forall a. IO a -> Fltk a
fltk = forall a. IO a -> Fltk a
Fltk
type Channel = MVar.MVar [(Fltk (), Text)]
type QuitRequest = MVar.MVar ()
event_loop :: Channel -> QuitRequest -> STM.TChan UiMsg.UiMsg -> IO ()
event_loop :: Channel -> QuitRequest -> TChan UiMsg -> IO ()
event_loop Channel
ui_chan QuitRequest
quit_request TChan UiMsg
msg_chan = do
FunPtr (FunPtrFinalizer Any)
finalizer <- forall a. FunPtrFinalizer a -> IO (FunPtr (FunPtrFinalizer a))
c_make_free_fun_ptr forall a. FunPtr a -> IO ()
FFI.freeFunPtr
forall a. FunPtr (FunPtrFinalizer a) -> IO ()
c_initialize FunPtr (FunPtrFinalizer Any)
finalizer
forall (m :: * -> *) a. Monad m => m Bool -> m a -> m ()
while_ (forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Bool -> Bool
not (forall a. MVar a -> IO Bool
MVar.isEmptyMVar QuitRequest
quit_request)) forall a b. (a -> b) -> a -> b
$
Channel -> TChan UiMsg -> IO ()
fltk_event_loop Channel
ui_chan TChan UiMsg
msg_chan
type FunPtrFinalizer a = Foreign.FunPtr a -> IO ()
foreign import ccall "wrapper"
c_make_free_fun_ptr :: FunPtrFinalizer a
-> IO (Foreign.FunPtr (FunPtrFinalizer a))
send_action :: Channel -> Text -> Fltk () -> IO ()
send_action :: Channel -> Text -> Fltk () -> IO ()
send_action Channel
ui_chan Text
description Fltk ()
act = do
forall a. MVar a -> (a -> IO a) -> IO ()
MVar.modifyMVar_ Channel
ui_chan forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *) a. Monad m => a -> m a
return forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Fltk ()
act, Text
description) :)
IO ()
awake
fltk_event_loop :: Channel -> STM.TChan UiMsg.UiMsg -> IO ()
fltk_event_loop :: Channel -> TChan UiMsg -> IO ()
fltk_event_loop Channel
ui_chan TChan UiMsg
msg_chan = do
IO ()
wait
Channel -> IO ()
handle_actions Channel
ui_chan
[UiMsg]
ui_msgs <- IO [UiMsg]
UiMsgC.get_ui_msgs
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (forall (t :: * -> *) a. Foldable t => t a -> Bool
null [UiMsg]
ui_msgs) forall a b. (a -> b) -> a -> b
$
forall a. STM a -> IO a
STM.atomically forall a b. (a -> b) -> a -> b
$ forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (forall a. TChan a -> a -> STM ()
STM.writeTChan TChan UiMsg
msg_chan) [UiMsg]
ui_msgs
handle_actions :: Channel -> IO ()
handle_actions :: Channel -> IO ()
handle_actions Channel
ui_chan = forall a. MVar a -> (a -> IO a) -> IO ()
MVar.modifyMVar_ Channel
ui_chan forall a b. (a -> b) -> a -> b
$ \[(Fltk (), Text)]
actions -> do
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
Exception.handle SomeException -> IO ()
handle forall a b. (a -> b) -> a -> b
$
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ (forall a. [a] -> [a]
reverse [(Fltk (), Text)]
actions) forall a b. (a -> b) -> a -> b
$ \(Fltk IO ()
action, Text
name) -> do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
action_timing forall a b. (a -> b) -> a -> b
$ forall a. Text -> (CString -> IO a) -> IO a
FFI.withText Text
name forall a b. (a -> b) -> a -> b
$ \CString
namep ->
CInt -> CString -> IO ()
c_timing CInt
1 CString
namep
IO ()
action
forall (m :: * -> *) a. Monad m => a -> m a
return []
where
handle :: Exception.SomeException -> IO ()
handle :: SomeException -> IO ()
handle SomeException
exc = forall (m :: * -> *). (Stack, LogMonad m) => Text -> m ()
Log.error forall a b. (a -> b) -> a -> b
$ Text
"exception in event_loop: " forall a. Semigroup a => a -> a -> a
<> forall a. Show a => a -> Text
showt SomeException
exc
quit_ui_thread :: QuitRequest -> IO ()
quit_ui_thread :: QuitRequest -> IO ()
quit_ui_thread QuitRequest
quit_request = do
forall a. MVar a -> IO (Maybe a)
MVar.tryTakeMVar QuitRequest
quit_request
IO ()
awake
foreign import ccall "initialize"
c_initialize :: Foreign.FunPtr (FunPtrFinalizer a) -> IO ()
foreign import ccall "ui_wait" wait :: IO ()
foreign import ccall "ui_awake" awake :: IO ()
foreign import ccall unsafe "timing" c_timing :: C.CInt -> C.CString -> IO ()
#endif