diff options
author | Josh Rahm <joshuarahm@gmail.com> | 2024-02-28 12:37:51 -0700 |
---|---|---|
committer | Josh Rahm <joshuarahm@gmail.com> | 2024-02-28 12:40:50 -0700 |
commit | e7300f03dcf0af7d968977000a10e8a8befdb60a (patch) | |
tree | 8f853663851a27b8914e429eda45b0c1fb97dd0b /src/Wetterhorn/Foreign/ForeignInterface.hs | |
parent | b444f874bc12cb8710068200500f14fd1e5f6776 (diff) | |
download | wetterhorn-e7300f03dcf0af7d968977000a10e8a8befdb60a.tar.gz wetterhorn-e7300f03dcf0af7d968977000a10e8a8befdb60a.tar.bz2 wetterhorn-e7300f03dcf0af7d968977000a10e8a8befdb60a.zip |
This adds new layout configuration, preparing for actually using the
layouts. This also restructures the code and tries to keep code
interfacing with the foreign structures together and rename them to more
sensible names.
Diffstat (limited to 'src/Wetterhorn/Foreign/ForeignInterface.hs')
-rw-r--r-- | src/Wetterhorn/Foreign/ForeignInterface.hs | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/Wetterhorn/Foreign/ForeignInterface.hs b/src/Wetterhorn/Foreign/ForeignInterface.hs new file mode 100644 index 0000000..471e3a9 --- /dev/null +++ b/src/Wetterhorn/Foreign/ForeignInterface.hs @@ -0,0 +1,81 @@ +module Wetterhorn.Foreign.ForeignInterface + ( getForeignInterface, + ForeignInterface (..), + ForeignDemarshal (..), + runForeignDemarshal, + demarshal, + doShellExec, + ) +where + +import Control.Monad.State (MonadState (get, put), MonadTrans (lift), StateT, evalStateT) +import Data.Void (Void) +import Foreign (Ptr, Storable (peek, sizeOf), castPtr, plusPtr) +import Foreign.C (CChar, CInt (..)) +import Foreign.C.String +import GHC.Exts (FunPtr) +import Wetterhorn.Foreign.WlRoots + +newtype ForeignDemarshal a = ForeignDemarshal (StateT (Ptr ()) IO a) + deriving (Functor, Monad, Applicative, MonadState (Ptr ())) + +runForeignDemarshal :: Ptr b -> ForeignDemarshal a -> IO a +runForeignDemarshal p (ForeignDemarshal dm) = evalStateT dm (castPtr p) + +demarshal :: (Storable a) => ForeignDemarshal a +demarshal = do + ptr <- get + val <- ForeignDemarshal $ lift $ peek $ castPtr ptr + put (plusPtr ptr (sizeOf val)) + return val + +type CtxT = Ptr Void + +type ForeignCallGetPtr = CtxT -> IO (Ptr ()) + +type ForeignCall = CtxT -> IO () + +type ForeignCallStr = CtxT -> CString -> IO () + +type ForeignCallInt = CtxT -> CInt -> IO () + +foreign import ccall "get_foreign_interface" foreignInterfacePtr :: IO (Ptr ()) + +foreign import ccall "dynamic" toForeignCall :: FunPtr ForeignCall -> ForeignCall + +foreign import ccall "dynamic" toForeignCallStr :: FunPtr ForeignCallStr -> ForeignCallStr + +foreign import ccall "dynamic" toForeignCallInt :: FunPtr ForeignCallInt -> ForeignCallInt + +foreign import ccall "dynamic" toForeignCallGetPtr :: FunPtr ForeignCallGetPtr -> ForeignCallGetPtr + +foreign import ccall "shell_exec" shellExec :: Ptr CChar -> IO () + +data ForeignInterface = ForeignInterface + { requestHotReload :: IO (), + requestLog :: String -> IO (), + requestExit :: Int -> IO (), + getSeat :: IO (Ptr WlrSeat) + } + +doShellExec :: String -> IO () +doShellExec str = withCString str shellExec + +getForeignInterface :: IO ForeignInterface +getForeignInterface = do + ptr <- foreignInterfacePtr + runForeignDemarshal ptr $ do + ctx <- demarshal + requestHotReloadFn <- demarshal + doLogFn <- demarshal + doRequestExit <- demarshal + getSeatFn <- demarshal + + return $ + ForeignInterface + { requestHotReload = toForeignCall requestHotReloadFn ctx, + requestLog = \str -> + withCString str $ \cs -> toForeignCallStr doLogFn ctx cs, + requestExit = toForeignCallInt doRequestExit ctx . fromIntegral, + getSeat = castPtr <$> toForeignCallGetPtr getSeatFn ctx + } |