aboutsummaryrefslogtreecommitdiff
path: root/src/Wetterhorn/Foreign/ForeignInterface.hs
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-02-28 12:37:51 -0700
committerJosh Rahm <joshuarahm@gmail.com>2024-02-28 12:40:50 -0700
commite7300f03dcf0af7d968977000a10e8a8befdb60a (patch)
tree8f853663851a27b8914e429eda45b0c1fb97dd0b /src/Wetterhorn/Foreign/ForeignInterface.hs
parentb444f874bc12cb8710068200500f14fd1e5f6776 (diff)
downloadwetterhorn-e7300f03dcf0af7d968977000a10e8a8befdb60a.tar.gz
wetterhorn-e7300f03dcf0af7d968977000a10e8a8befdb60a.tar.bz2
wetterhorn-e7300f03dcf0af7d968977000a10e8a8befdb60a.zip
Huge refactor for the Haskell code.HEADmain
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.hs81
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
+ }