kmonad-0.4.2: src/KMonad/Keyboard/IO/Mac/KextSink.hs
module KMonad.Keyboard.IO.Mac.KextSink
( kextSink
)
where
import KMonad.Prelude
import Foreign.Ptr
import Foreign.Marshal
import Foreign.Storable
import KMonad.Keyboard
import KMonad.Keyboard.IO
import KMonad.Keyboard.IO.Mac.Types
foreign import ccall "send_key"
send_key :: Ptr MacKeyEvent -> IO ()
newtype EvBuf = EvBuf
{ _buffer :: Ptr MacKeyEvent -- ^ The pointer we write events to
}
makeClassy ''EvBuf
kextSink :: HasLogFunc e => RIO e (Acquire KeySink)
kextSink = mkKeySink skOpen skClose skSend
-- | Create the 'EvBuf' environment
skOpen :: HasLogFunc e => RIO e EvBuf
skOpen = do
logInfo "Initializing Mac key sink"
liftIO $ EvBuf <$> mallocBytes (sizeOf (undefined :: MacKeyEvent))
-- | Close the 'EvBuf' environment
skClose :: HasLogFunc e => EvBuf -> RIO e ()
skClose sk = do
logInfo "Closing Mac key sink"
liftIO . free $ sk^.buffer
-- | Write an event to the pointer and prompt windows to inject it
--
-- NOTE: This can throw an error if event-conversion fails.
skSend :: HasLogFunc e => EvBuf -> KeyEvent -> RIO e ()
skSend sk e = either throwIO go $ toMacKeyEvent e
where go e' = liftIO $ do
poke (sk^.buffer) e'
send_key $ sk^.buffer