aboutsummaryrefslogtreecommitdiff
path: root/plug
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2026-01-06 15:09:52 -0700
committerJosh Rahm <joshuarahm@gmail.com>2026-01-06 15:09:52 -0700
commit68dd63f6b3de774863051b66e609a0ca4f4ac2a1 (patch)
treea908ebced56be6fc14307b1a1dc304c47905f8e2 /plug
parent12f8ef6dbf8618aaa304d239fbfd3c1b7b4494d3 (diff)
downloadmontis-68dd63f6b3de774863051b66e609a0ca4f4ac2a1.tar.gz
montis-68dd63f6b3de774863051b66e609a0ca4f4ac2a1.tar.bz2
montis-68dd63f6b3de774863051b66e609a0ca4f4ac2a1.zip
[rebrand] to arken = runtime, montis = plugin
Diffstat (limited to 'plug')
-rw-r--r--plug/README.md1
-rw-r--r--plug/package.yaml87
-rw-r--r--plug/src/Config.hs33
-rw-r--r--plug/src/Link.hs18
-rw-r--r--plug/src/Montis/Base/Foreign/Runtime.hs37
-rw-r--r--plug/src/Montis/Base/Foreign/WlRoots.hs44
-rw-r--r--plug/src/Montis/Base/Foreign/WlRoots/Types.hs99
-rw-r--r--plug/src/Montis/Core.hs10
-rw-r--r--plug/src/Montis/Core/Events.hs46
-rw-r--r--plug/src/Montis/Core/Extensions.hs30
-rw-r--r--plug/src/Montis/Core/Internal/Foreign/Export.hs226
-rw-r--r--plug/src/Montis/Core/Monad.hs125
-rw-r--r--plug/src/Montis/Core/Plugin/Interface.hs20
-rw-r--r--plug/src/Montis/Core/Runtime.hs82
-rw-r--r--plug/src/Montis/Core/Start.hs38
-rw-r--r--plug/src/Montis/Core/State.hs116
-rw-r--r--plug/src/Montis/Core/State/Marshal.hs44
-rw-r--r--plug/src/Montis/Foreign/Marshal.hs20
-rw-r--r--plug/src/Montis/Standard/Drag.hs123
-rw-r--r--plug/src/Montis/Standard/Keys.hs110
-rw-r--r--plug/src/Montis/Standard/Mouse.hs50
-rw-r--r--plug/src/harness_adapter.c73
-rw-r--r--plug/stack.yaml67
-rw-r--r--plug/test/Spec.hs2
24 files changed, 0 insertions, 1501 deletions
diff --git a/plug/README.md b/plug/README.md
deleted file mode 100644
index 5592f08..0000000
--- a/plug/README.md
+++ /dev/null
@@ -1 +0,0 @@
-The Plugin for the Montis Runtime.
diff --git a/plug/package.yaml b/plug/package.yaml
deleted file mode 100644
index bd42ced..0000000
--- a/plug/package.yaml
+++ /dev/null
@@ -1,87 +0,0 @@
-name: montis
-
-github: "jrahm/montis"
-license: BSD-3-Clause
-author: "Author name here"
-maintainer: "example@example.com"
-copyright: "2024 Author name here"
-
-extra-source-files:
-- README.md
-
-# Metadata used when publishing your package
-# synopsis: Short description of your package
-# category: Web
-
-# To avoid duplicated efforts in documentation and dealing with the
-# complications of embedding Haddock markup inside cabal files, it is
-# common to point users to the README.md file.
-description: Please see the README on GitHub at <https://github.com/githubuser/montis#readme>
-
-
-dependencies:
-- base >= 4.7 && < 5
-- mtl
-- bytestring
-- containers
-- data-default-class
-- transformers
-- monad-loops
-- singletons
-
-
-ghc-options:
-- -Wall
-- -Wcompat
-- -Widentities
-- -Wincomplete-record-updates
-- -Wincomplete-uni-patterns
-- -Wmissing-export-lists
-- -Wmissing-home-modules
-- -Wpartial-fields
-- -Wredundant-constraints
-- -XGHC2021
-- -XTypeFamilies
-- -XUndecidableInstances
-- -XGADTs
-- -XFunctionalDependencies
-- -XUndecidableSuperClasses
-- -XDefaultSignatures
-- -XViewPatterns
-- -XDerivingVia
-- -XDisambiguateRecordFields
-- -XLambdaCase
-- -XDataKinds
-- -fPIC
-
-executables:
- montis.so:
- main: Config.hs
- source-dirs: src
- c-sources: src/harness_adapter.c
- ghc-options:
- - -shared
- - -dynamic
- - -no-hs-main
- - -lHSrts-1.0.2-ghc9.4.7
- - -O3
- cc-options:
- - -g3
- - -O2
- - -shared
- - -I../build/
- - -I../rt/include/
- - -I../build/wlroots/include
- - -I../build/wlroots-src/include
- - -DWLR_USE_UNSTABLE
-
-tests:
- montis-test:
- main: Spec.hs
- source-dirs: test
- ghc-options:
- - -threaded
- - -rtsopts
- - -with-rtsopts=-N
- dependencies:
- - montis
diff --git a/plug/src/Config.hs b/plug/src/Config.hs
deleted file mode 100644
index 8ec06dd..0000000
--- a/plug/src/Config.hs
+++ /dev/null
@@ -1,33 +0,0 @@
-module Config (config) where
-
-import Control.Monad.IO.Class (liftIO)
-import Data.Bits (shiftL, (.&.))
-import Data.Word (Word32)
-import Montis.Core
-import Montis.Core.Runtime (warpCursor)
-import Montis.Standard.Drag (DragConfig (DragConfig))
-import Montis.Standard.Keys (KeysConfig (KeysConfig), subkeys)
-import Montis.Standard.Mouse (MouseConfig (MouseConfig))
-
-keys :: KeyEvent -> Montis Bool
-keys ev
- | keyEvent_modifiers ev .&. mod1Mask == 0 = return False
- | otherwise = case keyEvent_codepoint ev of
- 'j' -> do
- liftIO (putStrLn "j was pressed!")
- subkeys $ \ev -> case keyEvent_codepoint ev of
- 'k' -> do
- liftIO (putStrLn "k was pressed after j!")
- warpCursor 0 0
- return True
- _ -> return False
- _ -> return False
-
-mod1Mask :: Word32
-mod1Mask = 1 `shiftL` 3 -- WLR_MODIFIER_ALT
-
-config :: MontisConfig
-config =
- install MouseConfig $
- install (DragConfig mod1Mask) $
- install (KeysConfig keys) defaultConfig
diff --git a/plug/src/Link.hs b/plug/src/Link.hs
deleted file mode 100644
index 4ac3f5c..0000000
--- a/plug/src/Link.hs
+++ /dev/null
@@ -1,18 +0,0 @@
--- | Module that provides the start hooks using the config required to link the
--- plugin's shared library.
-module Link () where
-
-import Config (config)
-import Montis.Core
-
-foreign export ccall "plugin_cold_start"
- coldStart :: MontisColdStart
-
-foreign export ccall "plugin_hot_start"
- hotStart :: MontisHotStart
-
-coldStart :: MontisColdStart
-coldStart = coldStartMontis config
-
-hotStart :: MontisHotStart
-hotStart = hotStartMontis config
diff --git a/plug/src/Montis/Base/Foreign/Runtime.hs b/plug/src/Montis/Base/Foreign/Runtime.hs
deleted file mode 100644
index 427545a..0000000
--- a/plug/src/Montis/Base/Foreign/Runtime.hs
+++ /dev/null
@@ -1,37 +0,0 @@
-module Montis.Base.Foreign.Runtime where
-
-import Data.Void
-import Foreign.C (CInt (..), CString, CDouble (..))
-import Foreign.Ptr
-
-data ForeignMontisToplevel
-
-foreign import ccall "montis_do_request_hot_reload" foreign_doRequestHotReload :: Ptr Void -> IO ()
-
-foreign import ccall "montis_do_request_log" foreign_doRequestLog :: Ptr Void -> CString -> IO ()
-
-foreign import ccall "montis_do_request_exit" foreign_doRequestExit :: Ptr Void -> CInt -> IO ()
-
-foreign import ccall "montis_plugin_get_seat" foreign_getSeat :: Ptr Void -> IO (Ptr Void)
-
-foreign import ccall "montis_plugin_toplevel_at"
- foreign_toplevelAt :: Ptr Void -> CDouble -> CDouble -> IO (Ptr ForeignMontisToplevel)
-
-foreign import ccall "montis_plugin_get_toplevel_position"
- foreign_getToplevelPosition :: Ptr ForeignMontisToplevel -> Ptr CDouble -> Ptr CDouble -> IO ()
-
-foreign import ccall "montis_plugin_set_toplevel_position"
- foreign_setToplevelPosition :: Ptr ForeignMontisToplevel -> CDouble -> CDouble -> IO ()
-
-foreign import ccall "montis_plugin_get_toplevel_geometry"
- foreign_getToplevelGeometry ::
- Ptr ForeignMontisToplevel -> Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> Ptr CDouble -> IO ()
-
-foreign import ccall "montis_plugin_set_toplevel_geometry"
- foreign_setToplevelGeometry :: Ptr ForeignMontisToplevel -> CDouble -> CDouble -> CDouble -> CDouble -> IO ()
-
-foreign import ccall "montis_plugin_focus_toplevel"
- foreign_focusToplevel :: Ptr ForeignMontisToplevel -> IO ()
-
-foreign import ccall "montis_plugin_warp_cursor"
- foreign_warpCursor :: Ptr Void -> CDouble -> CDouble -> IO ()
diff --git a/plug/src/Montis/Base/Foreign/WlRoots.hs b/plug/src/Montis/Base/Foreign/WlRoots.hs
deleted file mode 100644
index 272567f..0000000
--- a/plug/src/Montis/Base/Foreign/WlRoots.hs
+++ /dev/null
@@ -1,44 +0,0 @@
--- | Contains functions and thin wrappers via ffi to the wlroots API.
-module Montis.Base.Foreign.WlRoots where
-
-import Foreign (Ptr, Word32, nullPtr)
-import Montis.Base.Foreign.WlRoots.Types
-
--- | Converts a null pointer into 'Nothing' to avoid dangling FFI handles.
-guardNull :: Ptr a -> Maybe (Ptr a)
-guardNull p | p == nullPtr = Nothing
-guardNull p = Just p
-
-foreign import ccall "wlr_seat_set_keyboard"
- foreign_wlrSetSeatKeyboard ::
- Ptr ForeignWlrSeat -> Ptr ForeignWlrInputDevice -> IO ()
-
--- | Binds the given input device as the active keyboard for a seat.
-setSeatKeyboard :: WlrSeat -> WlrInputDevice -> IO ()
-setSeatKeyboard (WlrSeat p1) (WlrInputDevice p2) =
- foreign_wlrSetSeatKeyboard p1 p2
-
-foreign import ccall "wlr_seat_get_keyboard"
- foreign_wlrSeatGetKeyboard ::
- Ptr ForeignWlrSeat -> IO (Ptr ForeignWlrKeyboard)
-
--- | Looks up the current keyboard for a seat, if one exists.
-getSeatKeyboard :: WlrSeat -> IO (Maybe WlrKeyboard)
-getSeatKeyboard (WlrSeat p) =
- fmap WlrKeyboard . guardNull <$> foreign_wlrSeatGetKeyboard p
-
-foreign import ccall "wlr_keyboard_get_modifiers"
- foreign_wlrKeyboardGetModifiers ::
- Ptr ForeignWlrKeyboard -> IO Word32
-
--- | Returns the current keyboard modifier mask for the keyboard.
-getKeyboardModifiers :: WlrKeyboard -> IO Word32
-getKeyboardModifiers (WlrKeyboard p) = foreign_wlrKeyboardGetModifiers p
-
-foreign import ccall "wlr_seat_keyboard_notify_key"
- foreign_wlrSeatKeyboardNotifyKey ::
- Ptr ForeignWlrSeat -> Word32 -> Word32 -> Word32 -> IO ()
-
--- | Forwards a key event to the seat with time, keycode, and state.
-seatKeyboardNotifyKey :: WlrSeat -> Word32 -> Word32 -> Word32 -> IO ()
-seatKeyboardNotifyKey (WlrSeat p) = foreign_wlrSeatKeyboardNotifyKey p
diff --git a/plug/src/Montis/Base/Foreign/WlRoots/Types.hs b/plug/src/Montis/Base/Foreign/WlRoots/Types.hs
deleted file mode 100644
index c109653..0000000
--- a/plug/src/Montis/Base/Foreign/WlRoots/Types.hs
+++ /dev/null
@@ -1,99 +0,0 @@
-module Montis.Base.Foreign.WlRoots.Types where
-
-import Foreign (IntPtr, Ptr, intPtrToPtr, ptrToIntPtr)
-import Text.Read
-
--- | Opaque foreign type for a wlroots keyboard.
-data ForeignWlrKeyboard
-
-newtype WlrKeyboard where
- WlrKeyboard :: Ptr ForeignWlrKeyboard -> WlrKeyboard
- deriving (Show, Ord, Eq)
-
--- | Opaque foreign type for a wlroots pointer.
-data ForeignWlrPointer
-
-newtype WlrPointer where
- WlrPointer :: Ptr ForeignWlrPointer -> WlrPointer
- deriving (Show, Ord, Eq)
-
--- | Opaque foreign type for wlroots pointer button events.
-data ForeignWlrPointerButtonEvent
-
-newtype WlrPointerButtonEvent where
- WlrPointerButtonEvent :: Ptr ForeignWlrPointerButtonEvent -> WlrPointerButtonEvent
- deriving (Show, Ord, Eq)
-
--- | Opaque foreign type for wlroots pointer motion events.
-data ForeignWlrPointerMotionEvent
-
-newtype WlrPointerMotionEvent where
- WlrPointerMotionEvent :: Ptr ForeignWlrPointerMotionEvent -> WlrPointerMotionEvent
- deriving (Show, Ord, Eq)
-
--- | Opaque foreign type for wlroots absolute pointer motion events.
-data ForeignWlrPointerMotionAbsoluteEvent
-
-newtype WlrPointerMotionAbsoluteEvent where
- WlrPointerMotionAbsoluteEvent :: Ptr ForeignWlrPointerMotionAbsoluteEvent -> WlrPointerMotionAbsoluteEvent
- deriving (Show, Ord, Eq)
-
--- | Opaque foreign type for a wlroots seat.
-data ForeignWlrSeat
-
-newtype WlrSeat where
- WlrSeat :: Ptr ForeignWlrSeat -> WlrSeat
- deriving (Show, Ord, Eq)
-
--- | Opaque foreign type for a wlroots input device.
-data ForeignWlrInputDevice
-
-newtype WlrInputDevice where
- WlrInputDevice :: Ptr ForeignWlrInputDevice -> WlrInputDevice
- deriving (Show, Ord, Eq)
-
--- | Opaque foreign type for wlroots keyboard key events.
-data ForeignWlrEventKeyboardKey
-
-newtype WlrEventKeyboardKey where
- WlrEventKeyboardKey :: Ptr ForeignWlrEventKeyboardKey -> WlrEventKeyboardKey
- deriving (Show, Ord, Eq)
-
--- | Opaque foreign type for xdg-shell surfaces.
-data ForeignWlrXdgSurface
-
--- | Opaque foreign type for XWayland surfaces.
-data ForeignWlrXWaylandSurface
-
--- | Tagged wrapper over surface pointer variants.
-data Surface where
- XdgSurface :: Ptr ForeignWlrXdgSurface -> Surface
- XWaylandSurface :: Ptr ForeignWlrXWaylandSurface -> Surface
- deriving (Ord, Eq)
-
-instance Show Surface where
- show (XdgSurface p) = show (XdgSerializeSurface (ptrToIntPtr p))
- show (XWaylandSurface p) = show (XWaylandSerializeSurface (ptrToIntPtr p))
-
-instance Read Surface where
- readPrec = fmap toSurf readPrec
- where
- -- Rebuild constructors from serialized pointers.
- toSurf (XdgSerializeSurface ip) = XdgSurface (intPtrToPtr ip)
- toSurf (XWaylandSerializeSurface ip) = XWaylandSurface (intPtrToPtr ip)
-
--- | Serializable version of 'Surface' to enable Read/Show.
-data SerializableSurface
- = XdgSerializeSurface IntPtr
- | XWaylandSerializeSurface IntPtr
- deriving (Read, Show)
-
-class ForeignSurface a where
- -- | Converts a foreign surface pointer into the tagged wrapper.
- toSurface :: Ptr a -> Surface
-
-instance ForeignSurface ForeignWlrXdgSurface where
- toSurface = XdgSurface
-
-instance ForeignSurface ForeignWlrXWaylandSurface where
- toSurface = XWaylandSurface
diff --git a/plug/src/Montis/Core.hs b/plug/src/Montis/Core.hs
deleted file mode 100644
index 5399f1e..0000000
--- a/plug/src/Montis/Core.hs
+++ /dev/null
@@ -1,10 +0,0 @@
-module Montis.Core
- ( module X,
- )
-where
-
-import Montis.Core.Events as X
-import Montis.Core.Monad as X
-import Montis.Core.Runtime as X
-import Montis.Core.Start as X
-import Montis.Core.State as X
diff --git a/plug/src/Montis/Core/Events.hs b/plug/src/Montis/Core/Events.hs
deleted file mode 100644
index 91b8618..0000000
--- a/plug/src/Montis/Core/Events.hs
+++ /dev/null
@@ -1,46 +0,0 @@
-module Montis.Core.Events where
-
-import Data.Word (Word32)
-import Montis.Base.Foreign.WlRoots.Types
-
-data KeyState = KeyPressed | KeyReleased deriving (Show, Read, Eq, Enum, Ord)
-
-data KeyEvent = KeyEvent
- { keyEvent_timeMs :: Word32,
- keyEvent_keycode :: Word32,
- keyEvent_state :: KeyState,
- keyEvent_modifiers :: Word32,
- keyEvent_keysym :: Word32,
- keyEvent_codepoint :: Char,
- keyEvent_device :: WlrInputDevice
- }
- deriving (Show, Ord, Eq)
-
-data ButtonState = ButtonReleased | ButtonPressed deriving (Show, Read, Eq, Enum, Ord)
-
-data ButtonEvent = ButtonEvent
- { buttonEvent_pointer :: WlrPointer,
- buttonEvent_timeMs :: Word32,
- buttonEvent_button :: Word32,
- buttonEvent_modifiers :: Word32,
- buttonEvent_state :: ButtonState
- }
- deriving (Eq, Show, Ord)
-
-data MotionEvent = MotionEvent
- { motionEvent_pointer :: WlrPointer,
- motionEvent_timeMs :: Word32,
- motionEvent_modifiers :: Word32,
- motionEvent_absolute :: (Double, Double),
- motionEvent_raw :: (Double, Double)
- }
- deriving (Eq, Show, Ord)
-
-data SurfaceState = Map | Unmap | Destroy
- deriving (Eq, Ord, Show, Read, Enum)
-
-data SurfaceEvent = SurfaceEvent
- { surfaceEvent_state :: SurfaceState,
- surfaceEvent_surface :: Surface
- }
- deriving (Eq, Ord, Show)
diff --git a/plug/src/Montis/Core/Extensions.hs b/plug/src/Montis/Core/Extensions.hs
deleted file mode 100644
index 0e8384f..0000000
--- a/plug/src/Montis/Core/Extensions.hs
+++ /dev/null
@@ -1,30 +0,0 @@
-module Montis.Core.Extensions where
-
-import Data.Data
- ( Typeable,
- tyConModule,
- tyConName,
- tyConPackage,
- )
-import Data.Kind (Constraint, Type)
-import Text.Printf (printf)
-import Type.Reflection (someTypeRep, someTypeRepTyCon)
-
--- | A key to key into the Extension maps.
-data ExtensionKey where
- ExtensionKey :: {extensionKeyValue :: String} -> ExtensionKey
- deriving (Eq, Ord, Show)
-
-data Extension (c :: Type -> Constraint) where
- Extension :: (Typeable a, c a) => a -> Extension c
-
-class Nil a
-instance Nil a
-
--- | Produces a string representation of a type used to key into the extensible
--- state map.
-typeRepr :: forall proxy a. (Typeable a) => proxy a -> ExtensionKey
-typeRepr proxy = ExtensionKey $ tyconToStr $ someTypeRepTyCon (someTypeRep proxy)
- where
- tyconToStr tc =
- printf "%s.%s.%s" (tyConPackage tc) (tyConModule tc) (tyConName tc)
diff --git a/plug/src/Montis/Core/Internal/Foreign/Export.hs b/plug/src/Montis/Core/Internal/Foreign/Export.hs
deleted file mode 100644
index faa1964..0000000
--- a/plug/src/Montis/Core/Internal/Foreign/Export.hs
+++ /dev/null
@@ -1,226 +0,0 @@
--- | This module has no public functions, but provides the surface interface
--- between the Montis runtime and the plugin.
-module Montis.Core.Internal.Foreign.Export () where
-
-import Control.Monad (forM_)
-import Control.Monad.State (MonadIO (liftIO), gets)
-import Data.ByteString qualified as BS
-import Data.ByteString.Char8 qualified as CH
-import Data.Singletons.Decide (Void)
-import Foreign
- ( Ptr,
- Storable (poke, pokeByteOff),
- Word32,
- Word8,
- deRefStablePtr,
- freeStablePtr,
- mallocBytes,
- newStablePtr,
- )
-import Foreign.C (CChar, CDouble (..), CInt (..))
-import Foreign.Ptr (castPtr)
-import Montis.Base.Foreign.WlRoots.Types
- ( ForeignSurface (toSurface),
- ForeignWlrInputDevice,
- ForeignWlrPointer,
- ForeignWlrXWaylandSurface,
- ForeignWlrXdgSurface,
- WlrEventKeyboardKey,
- WlrInputDevice (WlrInputDevice),
- WlrPointer (WlrPointer),
- WlrPointerButtonEvent,
- )
-import Montis.Core
-import Montis.Core.State
-import Montis.Core.State.Marshal (marshalState)
-import Montis.Foreign.Marshal (Demarshal (Demarshal), demarshal, runDemarshal)
-
--- | Helpers to unpack the opaque state, run a Montis action, and re-wrap it.
--- Each call consumes the old stable pointer and returns a fresh one.
-runForeign ::
- Montis () ->
- OpqStT ->
- IO OpqStT
-runForeign fn stableptr = do
- (ctx, st) <- deRefStablePtr stableptr
- freeStablePtr stableptr
- (_, state') <- runMontis ctx st fn
- newStablePtr (ctx, state')
-
-runForeignWithReturn ::
- (Storable a) =>
- Montis a ->
- Ptr a ->
- OpqStT ->
- IO OpqStT
-runForeignWithReturn fn outptr stableptr = do
- (ctx, st) <- deRefStablePtr stableptr
- freeStablePtr stableptr
- (val, state') <- runMontis ctx st fn
- poke outptr val
- newStablePtr (ctx, state')
-
--- ----------------------------------------------------------------------
--- State marshal/export
-
--- | Marshals the opaque state to a C-style byte array and size pointer.
-foreign export ccall "plugin_marshal_state"
- pluginMarshalState :: OpqStT -> Ptr Word32 -> IO (Ptr Word8)
-
-pluginMarshalState :: OpqStT -> Ptr Word32 -> IO (Ptr Word8)
-pluginMarshalState opqStT outlen = do
- (_, st) <- deRefStablePtr opqStT
- let bs = CH.pack (marshalState st)
- ret <- mallocBytes (BS.length bs)
- poke outlen (fromIntegral $ BS.length bs)
- forM_ (zip [0 ..] (BS.unpack bs)) $ \(off, w8) -> do
- pokeByteOff ret off w8
- return ret
-
--- ----------------------------------------------------------------------
--- Input handlers
-
-foreign export ccall "plugin_handle_button"
- pluginHandleButton :: Ptr WlrPointerButtonEvent -> Word32 -> OpqStT -> IO OpqStT
-
-pluginHandleButton :: Ptr WlrPointerButtonEvent -> Word32 -> OpqStT -> IO OpqStT
-pluginHandleButton eventPtr modifiers =
- runForeign $ do
- s <- gets currentHooks
- event <- liftIO $
- runDemarshal eventPtr $ do
- -- Follows struct wlr_pointer_button_event field order.
- pointerPtr <- demarshal :: Demarshal (Ptr ForeignWlrPointer)
- tMs <- demarshal
- button <- demarshal
- state <- demarshal :: Demarshal Word8
- return $
- ButtonEvent
- (WlrPointer pointerPtr)
- tMs
- button
- modifiers
- (if state == (0 :: Word8) then ButtonReleased else ButtonPressed)
-
- buttonHook s event
-
--- ----------------------------------------------------------------------
--- Keybinding handler
-
-foreign export ccall "plugin_handle_keybinding"
- pluginHandleKeybinding ::
- Ptr ForeignWlrInputDevice ->
- Ptr WlrEventKeyboardKey ->
- Word32 ->
- Word32 ->
- Word32 ->
- Ptr CInt ->
- OpqStT ->
- IO OpqStT
-
-pluginHandleKeybinding ::
- Ptr ForeignWlrInputDevice ->
- Ptr WlrEventKeyboardKey ->
- Word32 ->
- Word32 ->
- Word32 ->
- Ptr CInt ->
- OpqStT ->
- IO OpqStT
-pluginHandleKeybinding inputDevicePtr eventPtr mods sym cp =
- runForeignWithReturn $ do
- s <- gets currentHooks
- event <- liftIO $
- runDemarshal eventPtr $ do
- -- Matches struct wlr_keyboard_key_event in wlroots.
- tMs <- demarshal
- kc <- demarshal
- _ <- (demarshal :: Demarshal Word32)
- keyState <- demarshal
- return $
- KeyEvent
- tMs
- kc
- (if keyState == (0 :: Word8) then KeyReleased else KeyPressed)
- mods
- sym
- (toEnum $ fromIntegral cp)
- (WlrInputDevice inputDevicePtr)
-
- keyHook s event
- return 1
-
--- ----------------------------------------------------------------------
--- Motion handler
-
-foreign export ccall "plugin_handle_motion"
- pluginHandleMotion :: Ptr Void -> Word32 -> Word32 -> CDouble -> CDouble -> OpqStT -> IO OpqStT
-
-pluginHandleMotion :: Ptr Void -> Word32 -> Word32 -> CDouble -> CDouble -> OpqStT -> IO OpqStT
-pluginHandleMotion eventPtr modifiers isAbsolute lx ly =
- runForeign $ do
- s <- gets currentHooks
- event <- liftIO $
- if isAbsolute == 0
- then
- runDemarshal (castPtr eventPtr) $ do
- pointerPtr <- demarshal :: Demarshal (Ptr ForeignWlrPointer)
- tMs <- demarshal
- _ <- demarshal :: Demarshal Word32
- _ <- demarshal :: Demarshal Double
- _ <- demarshal :: Demarshal Double
- _ <- demarshal :: Demarshal Double
- _ <- demarshal :: Demarshal Double
- return $
- MotionEvent
- (WlrPointer pointerPtr)
- tMs
- modifiers
- (realToFrac lx, realToFrac ly)
- (0, 0)
- else
- runDemarshal (castPtr eventPtr) $ do
- -- After time_msec, wlroots pads to 8-byte alignment for doubles.
- pointerPtr <- demarshal :: Demarshal (Ptr ForeignWlrPointer)
- tMs <- demarshal
- _ <- demarshal :: Demarshal Word32
- rawX <- demarshal
- rawY <- demarshal
- return $
- MotionEvent
- (WlrPointer pointerPtr)
- tMs
- modifiers
- (realToFrac lx, realToFrac ly)
- (rawX, rawY)
-
- motionHook s event
-
--- ----------------------------------------------------------------------
--- Surface handlers
-
--- | Function exported to the harness to handle the mapping/unmapping/deletion
--- of an XDG surface.
-foreign export ccall "plugin_handle_surface"
- pluginHandleSurface ::
- Ptr ForeignWlrXdgSurface -> CInt -> OpqStT -> IO OpqStT
-
-pluginHandleSurface ::
- Ptr ForeignWlrXdgSurface -> CInt -> OpqStT -> IO OpqStT
-pluginHandleSurface p t =
- runForeign $ do
- s <- gets currentHooks
- surfaceHook s (SurfaceEvent (toEnum $ fromIntegral t) (toSurface p))
-
--- | Function exported to the harness to handle the mapping/unmapping/deletion
--- of an XWayland surface.
-foreign export ccall "plugin_handle_xwayland_surface"
- pluginHandleXWaylandSurface ::
- Ptr ForeignWlrXWaylandSurface -> CInt -> OpqStT -> IO OpqStT
-
-pluginHandleXWaylandSurface ::
- Ptr ForeignWlrXWaylandSurface -> CInt -> OpqStT -> IO OpqStT
-pluginHandleXWaylandSurface p t =
- runForeign $ do
- s <- gets currentHooks
- surfaceHook s (SurfaceEvent (toEnum $ fromIntegral t) (toSurface p))
diff --git a/plug/src/Montis/Core/Monad.hs b/plug/src/Montis/Core/Monad.hs
deleted file mode 100644
index b7d1633..0000000
--- a/plug/src/Montis/Core/Monad.hs
+++ /dev/null
@@ -1,125 +0,0 @@
-{-# LANGUAGE RankNTypes #-}
-{-# LANGUAGE ScopedTypeVariables #-}
-
-module Montis.Core.Monad where
-
-import Control.Monad.Identity (Identity (Identity))
-import Control.Monad.Reader
-import Control.Monad.State (MonadState, StateT (runStateT), gets, modify')
-import Data.Default.Class (Default (def))
-import Data.Map qualified as Map
-import Data.Maybe (fromMaybe)
-import Data.Typeable
-import Foreign (StablePtr)
-import Montis.Core.Extensions (Extension (Extension), typeRepr)
-import Montis.Core.State
-
--- | A Config type for the Montis monad.
-type MontisConfig = Config Montis
-
--- | A Context type specific for the Montis monad.
-type MontisContext = Context Montis
-
--- | A State type for the Montis monad.
-type MontisState = State Montis
-
--- | The Opaque State Type passed between the plugin and the runtime. The
--- OpqStT *is* the opq_st_t from the runtime code.
-type OpqStT = StablePtr (MontisContext, MontisState)
-
--- | The Montis monad is a Reader over an immutable context plus a State over
--- mutable runtime state, all ultimately running in IO for host effects.
-newtype Montis a where
- Montis :: (ReaderT MontisContext (StateT MontisState IO) a) -> Montis a
- deriving (Functor, Applicative, Monad, MonadState MontisState, MonadIO)
-
--- | Reader access is scoped to the config portion of the full context; this
--- keeps plugin code from mutating the context while still allowing read-only
--- access to configuration.
-instance MonadReader MontisConfig Montis where
- ask :: Montis MontisConfig
- ask = Montis $ asks ctxConfig
-
- reader :: (MontisConfig -> a) -> Montis a
- reader fn = Montis $ asks (fn . ctxConfig)
-
- local :: (MontisConfig -> MontisConfig) -> Montis a -> Montis a
- local cfn (Montis fn) =
- Montis $ local (\ctx -> ctx {ctxConfig = cfn (ctxConfig ctx)}) fn
-
--- | Access the plugin self pointer stored in the context.
-getSelfPtr :: Montis SelfPtr
-getSelfPtr = Montis $ asks ctxSelfPtr
-
--- | Run a Montis action with a fixed context and initial state, returning the
--- result value and the updated state.
-runMontis :: MontisContext -> MontisState -> Montis a -> IO (a, MontisState)
-runMontis ctx initState (Montis m) = runStateT (runReaderT m ctx) initState
-
--- | The standard default config.
-defaultConfig :: MontisConfig
-defaultConfig =
- Config
- { startingHooks =
- Hooks
- { keyHook = const (return ()),
- surfaceHook = const (return ()),
- buttonHook = const (return ()),
- motionHook = const (return ())
- },
- -- Default hooks are no-ops except for basic printing, which makes the
- -- system usable without extra wiring during development.
- startupHook = return (),
- resetHook = return (),
- -- Extensions start empty; callers can register config extensions as needed.
- configExtensions = mempty
- }
-
--- | Store a typed extension in the extensible state map under its TypeRep.
--- The value is wrapped so the map remains heterogeneously typed.
-xStatePut :: forall a. (StateExtension a) => a -> Montis ()
-xStatePut xst = do
- modify'
- ( \st ->
- st
- { extensibleState =
- Map.insert
- (typeRepr (Identity xst))
- (Right (Extension xst))
- (extensibleState st)
- }
- )
-
--- | Retrieve a typed extension, demarshalling it if needed and caching it back.
--- When the extension is stored in marshalled form, it is decoded and then
--- reinserted so future lookups are fast.
-xStateGet :: forall a. (StateExtension a) => Montis a
-xStateGet = do
- mp <- gets extensibleState
- case lookupByType (Proxy :: Proxy a) mp of
- Nothing -> return initialValue
- Just (Right (Extension v)) -> return $ fromMaybe initialValue (cast v)
- Just (Left s) -> do
- let x = (demarshalExtension s :: Maybe a)
- in forM_ x xStatePut >> return (fromMaybe initialValue x)
-
--- | Modifies the typed extension bi the given function.
-xStateModify :: forall a. (StateExtension a) => (a -> a) -> Montis ()
-xStateModify fn = do
- s <- xStateGet
- (xStatePut . fn) s
-
-xStateModifyM :: forall a. (StateExtension a) => (a -> Montis a) -> Montis ()
-xStateModifyM fn = do
- s <- xStateGet
- xStatePut =<< fn s
-
--- | Retrieve a typed configuration extension or return the default
--- instance if the extension had not been configured.
-xConfigGet :: forall a. (Typeable a, Default a) => Montis a
-xConfigGet = do
- exts <- asks configExtensions
- return $
- fromMaybe def $
- Map.lookup (typeRepr (Proxy :: Proxy a)) exts
- >>= (\(Extension a) -> cast a)
diff --git a/plug/src/Montis/Core/Plugin/Interface.hs b/plug/src/Montis/Core/Plugin/Interface.hs
deleted file mode 100644
index 73c0371..0000000
--- a/plug/src/Montis/Core/Plugin/Interface.hs
+++ /dev/null
@@ -1,20 +0,0 @@
--- | Provides the plugin interface through foreign exports.
-module Montis.Core.Plugin.Interface where
-
-import Data.ByteString (ByteString)
-import Data.Data (Typeable)
-import Data.Singletons.Decide (Void)
-import Foreign (Ptr, StablePtr, Word32)
-import Foreign.C (CChar)
-import Montis.Core.State (SelfPtr)
-
--- type OpqStT l w = StablePtr (Context l w, State l w)
-
-class OpaqueState s where
- hotStart :: SelfPtr -> ByteString -> IO s
-
- coldStart :: SelfPtr -> IO s
-
- marshalState :: s -> ByteString
-
- teardown :: s -> IO ()
diff --git a/plug/src/Montis/Core/Runtime.hs b/plug/src/Montis/Core/Runtime.hs
deleted file mode 100644
index 0d4c905..0000000
--- a/plug/src/Montis/Core/Runtime.hs
+++ /dev/null
@@ -1,82 +0,0 @@
-module Montis.Core.Runtime
- ( ToplevelHandle,
- focusToplevel,
- getSeat,
- getToplevelGeometry,
- setToplevelGeometry,
- setToplevelPosition,
- toplevelAt,
- warpCursor,
- )
-where
-
-import Control.Monad.IO.Class (liftIO)
-import Data.Void (Void)
-import Foreign (Ptr)
-import Foreign.C (CDouble (..))
-import Foreign.Marshal.Alloc (alloca)
-import Foreign.Ptr (castPtr, nullPtr)
-import Foreign.Storable (peek)
-import Montis.Base.Foreign.Runtime
-import Montis.Base.Foreign.WlRoots.Types (ForeignWlrSeat, WlrSeat (WlrSeat))
-import Montis.Core.Monad (Montis, getSelfPtr)
-import Montis.Core.State (SelfPtr (..))
-
-type ToplevelHandle = Ptr ForeignMontisToplevel
-
-unwrapSelf :: SelfPtr -> Ptr Void
-unwrapSelf (SelfPtr p) = p
-
-getSeat :: Montis (Maybe WlrSeat)
-getSeat = do
- self <- getSelfPtr
- seatPtr <- liftIO $ foreign_getSeat (unwrapSelf self)
- if seatPtr == nullPtr
- then return Nothing
- else return $ Just (WlrSeat (castPtr seatPtr :: Ptr ForeignWlrSeat))
-
-toplevelAt :: Double -> Double -> Montis (Maybe ToplevelHandle)
-toplevelAt lx ly = do
- self <- getSelfPtr
- tl <- liftIO $ foreign_toplevelAt (unwrapSelf self) (realToFrac lx) (realToFrac ly)
- if tl == nullPtr
- then return Nothing
- else return (Just tl)
-
-getToplevelGeometry :: ToplevelHandle -> Montis (Double, Double, Double, Double)
-getToplevelGeometry tl =
- liftIO $
- alloca $ \xPtr -> alloca $ \yPtr -> alloca $ \wPtr -> alloca $ \hPtr -> do
- foreign_getToplevelGeometry tl xPtr yPtr wPtr hPtr
- x <- peek xPtr
- y <- peek yPtr
- w <- peek wPtr
- h <- peek hPtr
- return
- ( realToFrac (x :: CDouble),
- realToFrac (y :: CDouble),
- realToFrac (w :: CDouble),
- realToFrac (h :: CDouble)
- )
-
-setToplevelGeometry :: ToplevelHandle -> Double -> Double -> Double -> Double -> Montis ()
-setToplevelGeometry tl x y w h =
- liftIO $
- foreign_setToplevelGeometry
- tl
- (realToFrac x)
- (realToFrac y)
- (realToFrac w)
- (realToFrac h)
-
-setToplevelPosition :: ToplevelHandle -> Double -> Double -> Montis ()
-setToplevelPosition tl x y =
- liftIO $ foreign_setToplevelPosition tl (realToFrac x) (realToFrac y)
-
-focusToplevel :: ToplevelHandle -> Montis ()
-focusToplevel tl = liftIO $ foreign_focusToplevel tl
-
-warpCursor :: Double -> Double -> Montis ()
-warpCursor lx ly = do
- self <- getSelfPtr
- liftIO $ foreign_warpCursor (unwrapSelf self) (realToFrac lx) (realToFrac ly)
diff --git a/plug/src/Montis/Core/Start.hs b/plug/src/Montis/Core/Start.hs
deleted file mode 100644
index 54ec8c5..0000000
--- a/plug/src/Montis/Core/Start.hs
+++ /dev/null
@@ -1,38 +0,0 @@
-module Montis.Core.Start where
-
-import Data.ByteString qualified as BS
-import Data.ByteString.Char8 qualified as CH
-import Data.Void
-import Foreign (Word32, newStablePtr)
-import Foreign.C (CChar)
-import Foreign.Ptr
-import Montis.Core.Monad
-import Montis.Core.State
-import Montis.Core.State.Marshal (demarshalState)
-
-type MontisColdStart = Ptr Void -> IO OpqStT
-
-type MontisHotStart = Ptr Void -> Ptr CChar -> Word32 -> IO OpqStT
-
-hotStartMontis :: MontisConfig -> MontisHotStart
-hotStartMontis config self chars len = do
- bs <- BS.packCStringLen (chars, fromIntegral len)
-
- let ctx = Context config (SelfPtr self)
- st = demarshalState config (CH.unpack bs)
-
- ((), st') <- runMontis ctx st (resetHook config)
- newStablePtr (ctx, st')
-
--- Used to start montis given the provided config.
-coldStartMontis :: MontisConfig -> MontisColdStart
-coldStartMontis conf selfPtr =
- let ctx = Context conf (SelfPtr selfPtr)
- st =
- State
- { currentHooks = startingHooks conf,
- extensibleState = mempty
- }
- in do
- ((), st') <- runMontis ctx st (startupHook conf)
- newStablePtr (ctx, st')
diff --git a/plug/src/Montis/Core/State.hs b/plug/src/Montis/Core/State.hs
deleted file mode 100644
index ce8f903..0000000
--- a/plug/src/Montis/Core/State.hs
+++ /dev/null
@@ -1,116 +0,0 @@
--- | Definitions of montis core state.
-module Montis.Core.State where
-
-import Data.Data (Proxy (Proxy), Typeable)
-import Data.Default.Class (Default, def)
-import Data.Map qualified as M
-import Data.Void (Void)
-import Foreign (Ptr)
-import Montis.Core.Events
-import Montis.Core.Extensions
-import Text.Read (readMaybe)
-
--- | An opaque type used for the plugin's self-reference.
-newtype SelfPtr where
- SelfPtr :: Ptr Void -> SelfPtr
-
--- | This is the context the plugin operates under. The context contains data
--- which must be provided by the runtime or the configuration. This data may not
--- be cold-created.
---
--- Parameters:
--- `m` the monad for this Context. This is typically W.
-data Context m where
- Context ::
- { ctxConfig :: Config m,
- ctxSelfPtr :: SelfPtr
- } ->
- Context m
-
--- | Montis configuration. This is the structure that defines the user-written
--- configuration, which is linked in.
-data Config m where
- Config ::
- { startingHooks :: Hooks m,
- startupHook :: m (),
- resetHook :: m (),
- configExtensions :: M.Map ExtensionKey (Extension Nil)
- } ->
- Config m
-
--- | Hooks the runtime can call.
-data Hooks m where
- Hooks ::
- { keyHook :: KeyEvent -> m (),
- surfaceHook :: SurfaceEvent -> m (),
- buttonHook :: ButtonEvent -> m (),
- motionHook :: MotionEvent -> m ()
- } ->
- Hooks m
-
--- | Class for a configurable model.
-class (Typeable a) => ConfigModule m a where
- alterConfig :: a -> Config m -> Config m
-
--- | Configures a typed configuration extension.
-install :: forall a m. (ConfigModule m a) => a -> Config m -> Config m
-install a c =
- alterConfig a $
- c
- { configExtensions =
- M.insert
- (typeRepr (Proxy :: Proxy a))
- (Extension a)
- (configExtensions c)
- }
-
--- | Typeclass defining the set of types which can be used as state extensions
--- to the W monad. These state extensions may be persistent or not.
---
--- There are default implementations for all methods if the type implements
--- Read, Show and Default,
-class (Typeable a) => StateExtension a where
- -- | The initial value used for the first time an extension is 'gotten' or
- -- demarshalling fails.
- initialValue :: a
-
- -- | Transforms a type into a string. If the type cannot be marshalled, this
- -- function should return Nothing.
- --
- -- If a type cannot be marshalled, it cannot persist across hot reloads.
- marshalExtension :: a -> Maybe String
-
- -- | Reads an extension from a string. If this type is not marshallable or
- -- reading fails, this function should return Nothing.
- demarshalExtension :: String -> Maybe a
-
- -- | If the type implements Default, use the default implementation.
- default initialValue :: (Default a) => a
- initialValue = def
-
- -- | If the type implements Show, use show for the marshalling.
- default marshalExtension :: (Show a) => a -> Maybe String
- marshalExtension = Just . show
-
- -- | If the type implements Read, use read for the demarshalling.
- default demarshalExtension :: (Read a) => String -> Maybe a
- demarshalExtension = readMaybe
-
--- | State type. This type contains changeable data.
-data State m where
- State ::
- { -- The datastructure containing the state of the windows.
-
- -- | Current set of hooks. The initial hooks are provided by the
- -- configuration, but the hooks can change during operation. This is how
- -- key sequences can be mapped.
- currentHooks :: Hooks m,
- -- | Map from the typerep string to the state extension.
- extensibleState ::
- M.Map ExtensionKey (Either String (Extension StateExtension))
- } ->
- State m
-
--- | Lookup from an extension map by type.
-lookupByType :: (Typeable a) => proxy a -> M.Map ExtensionKey b -> Maybe b
-lookupByType pxy = M.lookup (typeRepr pxy)
diff --git a/plug/src/Montis/Core/State/Marshal.hs b/plug/src/Montis/Core/State/Marshal.hs
deleted file mode 100644
index 04a2a57..0000000
--- a/plug/src/Montis/Core/State/Marshal.hs
+++ /dev/null
@@ -1,44 +0,0 @@
-module Montis.Core.State.Marshal (marshalState, demarshalState) where
-
-import Data.Map qualified as M
-import Data.Maybe (mapMaybe)
-import Montis.Core.Extensions
-import Montis.Core.State
-
-data MarshalledState where
- MarshalledState ::
- [(String, String)] ->
- MarshalledState
- deriving (Show, Read)
-
--- | Marshals the serializable parts of the state to a string. This happens
--- during a hot-reload where some state must be saved to persist across hot
--- reloads.
--- Only the extensible state is persisted; hooks and other runtime data are
--- reconstructed from the config on restart.
-marshalState :: State m -> String
-marshalState
- ( State
- { extensibleState = xs
- }
- ) =
- show $
- MarshalledState
- (mapMaybe (\(k, v) -> (extensionKeyValue k,) <$> doMarshalEx v) (M.toList xs))
- where
- -- Left values are already marshalled; Right values are re-encoded here.
- doMarshalEx :: Either String (Extension StateExtension) -> Maybe String
- doMarshalEx (Left s) = Just s
- doMarshalEx (Right (Extension a)) = marshalExtension a
-
--- | Demarshals the string from "marshalState" into a state. Uses the provided
--- config to fill out non-persistent parts of the state.
--- The extensible map is rehydrated as marshalled strings so decoding can be
--- deferred until a specific extension is requested.
-demarshalState :: Config m -> String -> State m
-demarshalState Config {startingHooks = hooks} str =
- State hooks xs
- where
- ( MarshalledState
- (M.mapKeys ExtensionKey . fmap Left . M.fromList -> xs)
- ) = read str
diff --git a/plug/src/Montis/Foreign/Marshal.hs b/plug/src/Montis/Foreign/Marshal.hs
deleted file mode 100644
index 157d928..0000000
--- a/plug/src/Montis/Foreign/Marshal.hs
+++ /dev/null
@@ -1,20 +0,0 @@
-module Montis.Foreign.Marshal where
-
-import Control.Monad.State
-import Data.Word
-import Foreign (Ptr, Storable (peek, sizeOf), castPtr, plusPtr)
-
-type Offset = Word32
-
-newtype Demarshal a = Demarshal (StateT (Ptr ()) IO a)
- deriving (Functor, Monad, Applicative, MonadState (Ptr ()))
-
-runDemarshal :: Ptr b -> Demarshal a -> IO a
-runDemarshal p (Demarshal dm) = evalStateT dm (castPtr p)
-
-demarshal :: (Storable a) => Demarshal a
-demarshal = do
- ptr <- get
- val <- Demarshal $ lift $ peek $ castPtr ptr
- put (plusPtr ptr (sizeOf val))
- return val
diff --git a/plug/src/Montis/Standard/Drag.hs b/plug/src/Montis/Standard/Drag.hs
deleted file mode 100644
index a6ee878..0000000
--- a/plug/src/Montis/Standard/Drag.hs
+++ /dev/null
@@ -1,123 +0,0 @@
-module Montis.Standard.Drag where
-
-import Data.Bits ((.&.))
-import Data.Data (Typeable)
-import Data.Word (Word32)
-import Montis.Core
-import Montis.Core.Runtime
-import Montis.Core.State
- ( Config (startingHooks),
- ConfigModule (..),
- Hooks (buttonHook, motionHook),
- StateExtension (..),
- )
-import Montis.Standard.Mouse (CursorPosition (CursorPosition))
-
-data DragConfig where
- DragConfig ::
- { dragModifierMask :: Word32
- } ->
- DragConfig
- deriving (Typeable)
-
-instance ConfigModule Montis DragConfig where
- alterConfig cfg c =
- let ohb = buttonHook (startingHooks c)
- ohm = motionHook (startingHooks c)
- in c
- { startingHooks =
- (startingHooks c)
- { buttonHook = \ev -> onButton (dragModifierMask cfg) ev >> ohb ev,
- motionHook = \ev -> onMotion ev >> ohm ev
- }
- }
-
-data DragState = DragState
- { dragToplevel :: ToplevelHandle,
- dragOffsetX :: Double,
- dragOffsetY :: Double
- }
- deriving (Typeable)
-
-data ResizeState = ResizeState
- { resizeToplevel :: ToplevelHandle,
- resizeStartX :: Double,
- resizeStartY :: Double,
- resizeStartW :: Double,
- resizeStartH :: Double,
- resizeStartCursorX :: Double,
- resizeStartCursorY :: Double
- }
- deriving (Typeable)
-
-data DragAction
- = DragMove DragState
- | DragResize ResizeState
- deriving (Typeable)
-
-newtype Dragging = Dragging (Maybe DragAction)
- deriving (Typeable)
-
-instance StateExtension Dragging where
- initialValue = Dragging Nothing
- marshalExtension _ = Nothing
- demarshalExtension _ = Nothing
-
-leftButton :: Word32
-leftButton = 272 -- BTN_LEFT
-
-rightButton :: Word32
-rightButton = 273 -- BTN_RIGHT
-
-onButton :: Word32 -> ButtonEvent -> Montis ()
-onButton modMask ev
- | buttonEvent_button ev /= leftButton && buttonEvent_button ev /= rightButton = return ()
- | buttonEvent_state ev == ButtonPressed = do
- if buttonEvent_modifiers ev .&. modMask == 0
- then return ()
- else do
- CursorPosition (x, y) <- xStateGet
- mtl <- toplevelAt x y
- case mtl of
- Nothing -> xStatePut (Dragging Nothing)
- Just tl -> do
- (tx, ty, tw, th) <- getToplevelGeometry tl
- if buttonEvent_button ev == rightButton
- then do
- let warpX = tx + tw
- warpY = ty + th
- warpCursor warpX warpY
- xStatePut (CursorPosition (warpX, warpY))
- xStatePut $
- Dragging
- ( Just
- ( DragResize
- (ResizeState tl tx ty tw th warpX warpY)
- )
- )
- else
- xStatePut $
- Dragging
- (Just (DragMove (DragState tl (x - tx) (y - ty))))
- | buttonEvent_state ev == ButtonReleased =
- xStatePut (Dragging Nothing)
- | otherwise = return ()
-
-onMotion :: MotionEvent -> Montis ()
-onMotion ev = do
- let (x, y) = motionEvent_absolute ev
- xStatePut (CursorPosition (x, y))
- Dragging mdrag <- xStateGet
- case mdrag of
- Nothing -> return ()
- Just (DragMove (DragState tl dx dy)) ->
- setToplevelPosition tl (x - dx) (y - dy)
- Just (DragResize rs) -> do
- let newW = max 1 (resizeStartW rs + (x - resizeStartCursorX rs))
- newH = max 1 (resizeStartH rs + (y - resizeStartCursorY rs))
- setToplevelGeometry
- (resizeToplevel rs)
- (resizeStartX rs)
- (resizeStartY rs)
- newW
- newH
diff --git a/plug/src/Montis/Standard/Keys.hs b/plug/src/Montis/Standard/Keys.hs
deleted file mode 100644
index 0b670eb..0000000
--- a/plug/src/Montis/Standard/Keys.hs
+++ /dev/null
@@ -1,110 +0,0 @@
-module Montis.Standard.Keys where
-
-import Control.Monad (when)
-import Control.Monad.IO.Class (liftIO)
-import Data.Data (Typeable)
-import Data.Default.Class (Default (..))
-import Data.Set qualified as Set
-import Data.Word (Word32)
-import Montis.Base.Foreign.WlRoots (seatKeyboardNotifyKey)
-import Montis.Core.Events (KeyEvent (..), KeyState (..))
-import Montis.Core.Monad (Montis, xConfigGet, xStateGet, xStateModify)
-import Montis.Core.Runtime (getSeat)
-import Montis.Core.State
- ( Config (startingHooks),
- ConfigModule (..),
- Hooks (keyHook),
- StateExtension (..),
- )
-
--- | Configuration for the keybindings.
-data KeysConfig where
- KeysConfig ::
- { startCont :: KeyEvent -> Montis Bool
- } ->
- KeysConfig
- deriving (Typeable)
-
-instance Default KeysConfig where
- def = KeysConfig $ \_ -> return False
-
-subkeys :: (KeyEvent -> Montis Bool) -> Montis Bool
-subkeys fn = do
- xStateModify $ \keyState ->
- keyState
- { awaiting = Just fn
- }
- return True
-
--- | State of the keys right now.
-data KeysState where
- KeysState ::
- { awaiting :: Maybe (KeyEvent -> Montis Bool),
- ignoredKeys :: Set.Set Word32
- } ->
- KeysState
-
-instance StateExtension KeysState where
- initialValue = KeysState Nothing Set.empty
- marshalExtension = const Nothing
- demarshalExtension = const Nothing
-
--- | Configurable module for keys.
-instance ConfigModule Montis KeysConfig where
- alterConfig _ c =
- let oh = keyHook (startingHooks c)
- in c
- { startingHooks =
- (startingHooks c)
- { keyHook = \ev -> runEv ev >> oh ev
- }
- }
- where
- isKeyPress ev = keyEvent_state ev == KeyPressed
- isKeyRelease ev = keyEvent_state ev == KeyReleased
- shouldIgnoreEvent ev = do
- KeysState {ignoredKeys} <- xStateGet
- return $ Set.member (keyEvent_keycode ev) ignoredKeys
- runEv ev = do
- shouldIgnore <- shouldIgnoreEvent ev
- if isKeyRelease ev && shouldIgnore
- then xStateModify $ \ks ->
- ks {ignoredKeys = Set.delete (keyEvent_keycode ev) (ignoredKeys ks)}
- else do
- handled <-
- if isKeyPress ev
- then do
- handler' <- awaiting <$> xStateGet
- handler <- maybe (startCont <$> xConfigGet) return handler'
- -- Reset the hadler.
- xStateModify $ \st ->
- st {awaiting = Nothing}
- handler ev
- else return False
-
- if not handled
- then forwardKeyToSeat ev
- else when (isKeyPress ev) $
- xStateModify $
- \ks ->
- ks
- { ignoredKeys =
- Set.insert (keyEvent_keycode ev) (ignoredKeys ks)
- }
-
-forwardKeyToSeat :: KeyEvent -> Montis ()
-forwardKeyToSeat ev = do
- mseat <- getSeat
- case mseat of
- Nothing -> return ()
- Just seat ->
- liftIO $
- seatKeyboardNotifyKey
- seat
- (keyEvent_timeMs ev)
- (keyEvent_keycode ev)
- (keyStateToWord32 (keyEvent_state ev))
-
-keyStateToWord32 :: KeyState -> Word32
-keyStateToWord32 KeyReleased = 0
-keyStateToWord32 KeyPressed = 1
diff --git a/plug/src/Montis/Standard/Mouse.hs b/plug/src/Montis/Standard/Mouse.hs
deleted file mode 100644
index 933a2f4..0000000
--- a/plug/src/Montis/Standard/Mouse.hs
+++ /dev/null
@@ -1,50 +0,0 @@
-module Montis.Standard.Mouse where
-
-import Data.Data (Typeable)
-import Montis.Core
-import Montis.Core.Runtime (focusToplevel, toplevelAt)
-import Montis.Core.State
- ( Config (startingHooks),
- ConfigModule (..),
- Hooks (buttonHook, motionHook),
- StateExtension (..),
- )
-
-data MouseConfig where
- MouseConfig :: MouseConfig
- deriving (Typeable)
-
-instance ConfigModule Montis MouseConfig where
- alterConfig _ c =
- let ohb = buttonHook (startingHooks c)
- ohm = motionHook (startingHooks c)
- in c
- { startingHooks =
- (startingHooks c)
- { buttonHook = \ev -> onButton ev >> ohb ev,
- motionHook = \ev -> onMotion ev >> ohm ev
- }
- }
-
-newtype CursorPosition = CursorPosition (Double, Double)
- deriving (Typeable)
-
-instance StateExtension CursorPosition where
- initialValue = CursorPosition (0, 0)
- marshalExtension _ = Nothing
- demarshalExtension _ = Nothing
-
-onMotion :: MotionEvent -> Montis ()
-onMotion ev = do
- let (x, y) = motionEvent_absolute ev
- xStatePut (CursorPosition (x, y))
-
-onButton :: ButtonEvent -> Montis ()
-onButton ev
- | buttonEvent_state ev /= ButtonPressed = return ()
- | otherwise = do
- CursorPosition (x, y) <- xStateGet
- mtl <- toplevelAt x y
- case mtl of
- Nothing -> return ()
- Just tl -> focusToplevel tl
diff --git a/plug/src/harness_adapter.c b/plug/src/harness_adapter.c
deleted file mode 100644
index db5e7ce..0000000
--- a/plug/src/harness_adapter.c
+++ /dev/null
@@ -1,73 +0,0 @@
-// This file provides functions for the wetterhorn harness that are not
-// expressible directly in haskell.
-//
-// Currently these functions exclusively enable/disable the Haskell runtime.
-
-#include "HsFFI.h"
-#include "plugin_interface.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-const char *plugin_name = "Montis";
-
-extern void performMajorGC();
-
-void plugin_metaload(int argc, char** argv)
-{
- // hs_init(&argc, &argv);
-}
-
-void plugin_load(int argc, char **argv) {
- hs_init(&argc, &argv);
-}
-
-void plugin_teardown(opqst_t st) {
- hs_exit();
-}
-
-void shell_exec(const char* cmd) {
- if (fork() == 0) {
- execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
- exit(1);
- }
-}
-
-static const char msg[] =
- "Montis Plugin v 0.01\n\n"
- "Welcome, and thank you for your interest.\n\n"
- "This is merely a plugin to the Montis Compositor and not meant to be\n"
- "executed as a standalone binary. This plugin requires a harness to run\n"
- "To use this file, please use './wtr_harness [full-path-to-wtr.so]'\n"
- "That will allow you to see how this compositor works in all its glory!\n";
-static const int msg_sz = sizeof(msg);
-
-/*
- * Implemens a basic _start that prints inforamtion and exits for users on an
- * x86_64 system.
- */
-__attribute__((naked)) void _start()
-{
-
- // Make system call to print the message
- asm(
- // Load the address of the string into rsi
- "mov %0, %%rsi\n"
- // Load the string length into edx
- "mov %1, %%edx\n"
- // Load the file descriptor for stdout into edi
- "mov $1, %%edi\n"
- // Load the syscall number for sys_write into eax
- "mov $1, %%eax\n"
- // Make the syscall
- "syscall\n"
-
- // Exit the program.
- "mov $0, %%rdi\n"
- "mov $60, %%rax\n"
- "syscall\n"
- :
- : "r"(msg), "r"(msg_sz) // Input: address of msg
- : "%rsi", "%edx", "%edi" // Clobbered registers
- );
-}
diff --git a/plug/stack.yaml b/plug/stack.yaml
deleted file mode 100644
index 0faf47c..0000000
--- a/plug/stack.yaml
+++ /dev/null
@@ -1,67 +0,0 @@
-# This file was automatically generated by 'stack init'
-#
-# Some commonly used options have been documented as comments in this file.
-# For advanced use and comprehensive documentation of the format, please see:
-# https://docs.haskellstack.org/en/stable/yaml_configuration/
-
-# Resolver to choose a 'specific' stackage snapshot or a compiler version.
-# A snapshot resolver dictates the compiler version and the set of packages
-# to be used for project dependencies. For example:
-#
-resolver: lts-21.21
-# ghc-9.6.4
-# lts-21.21
-# resolver: nightly-2023-09-24
-# resolver: ghc-9.6.2
-#
-# The location of a snapshot can be provided as a file or url. Stack assumes
-# a snapshot provided as a file might change, whereas a url resource does not.
-#
-# resolver: ./custom-snapshot.yaml
-# resolver: https://example.com/snapshots/2023-01-01.yaml
-
-# User packages to be built.
-# Various formats can be used as shown in the example below.
-#
-# packages:
-# - some-directory
-# - https://example.com/foo/bar/baz-0.0.2.tar.gz
-# subdirs:
-# - auto-update
-# - wai
-packages:
-- .
-# Dependency packages to be pulled from upstream that are not in the resolver.
-# These entries can reference officially published versions as well as
-# forks / in-progress versions pinned to a git hash. For example:
-#
-# extra-deps:
-# - acme-missiles-0.3
-# - git: https://github.com/commercialhaskell/stack.git
-# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
-#
-# extra-deps: []
-
-# Override default flag values for local packages and extra-deps
-# flags: {}
-
-# Extra package databases containing global packages
-# extra-package-dbs: []
-
-# Control whether we use the GHC we find on the path
-# system-ghc: true
-#
-# Require a specific version of Stack, using version ranges
-# require-stack-version: -any # Default
-# require-stack-version: ">=2.13"
-#
-# Override the architecture used by Stack, especially useful on Windows
-# arch: i386
-# arch: x86_64
-#
-# Extra directories used by Stack for building
-# extra-include-dirs: [/path/to/dir]
-# extra-lib-dirs: [/path/to/dir]
-#
-# Allow a newer minor version of GHC than the snapshot specifies
-# compiler-check: newer-minor
diff --git a/plug/test/Spec.hs b/plug/test/Spec.hs
deleted file mode 100644
index cd4753f..0000000
--- a/plug/test/Spec.hs
+++ /dev/null
@@ -1,2 +0,0 @@
-main :: IO ()
-main = putStrLn "Test suite not yet implemented"