Skip to content
Snippets Groups Projects
Registry.hs 2.63 KiB
Newer Older
Jens Nolte's avatar
Jens Nolte committed
module Quasar.Wayland.Server.Registry (
  Registry,
Jens Nolte's avatar
Jens Nolte committed
  Global,
Jens Nolte's avatar
Jens Nolte committed
  newRegistry,
  addRegistryConnection,
Jens Nolte's avatar
Jens Nolte committed
  createGlobal,
  maxVersion,
Jens Nolte's avatar
Jens Nolte committed
) where

Jens Nolte's avatar
Jens Nolte committed
import Data.Foldable (toList)
Jens Nolte's avatar
Jens Nolte committed
import Data.HashMap.Strict qualified as HM
Jens Nolte's avatar
Jens Nolte committed
import Data.Sequence (Seq)
import Data.Sequence qualified as Seq
Jens Nolte's avatar
Jens Nolte committed
import Quasar.Prelude
import Quasar.Wayland.Protocol
Jens Nolte's avatar
Jens Nolte committed
import Quasar.Wayland.Protocol.Core
Jens Nolte's avatar
Jens Nolte committed
import Quasar.Wayland.Protocol.Generated

-- TODO: send registry messages
Jens Nolte's avatar
Jens Nolte committed
-- TODO: remove RegistryConnection when registry protocol connection is destroyed
Jens Nolte's avatar
Jens Nolte committed

data Registry = Registry {
  connections :: TVar [RegistryConnection],
Jens Nolte's avatar
Jens Nolte committed
  singletons :: Seq Global,
Jens Nolte's avatar
Jens Nolte committed
  globalsVar :: TVar (HM.HashMap Word32 Global)
}

Jens Nolte's avatar
Jens Nolte committed
newRegistry :: MonadIO m => [Global] -> m Registry
newRegistry singletons = do
Jens Nolte's avatar
Jens Nolte committed
  connections <- newTVarIO mempty
  globalsVar <- newTVarIO mempty
Jens Nolte's avatar
Jens Nolte committed
  pure Registry { connections, singletons = Seq.fromList singletons, globalsVar }
Jens Nolte's avatar
Jens Nolte committed

data RegistryConnection = RegistryConnection {
  registry :: Registry,
  wlRegistry :: Object 'Server Interface_wl_registry
}

Jens Nolte's avatar
Jens Nolte committed
createGlobal :: forall i. IsInterfaceSide 'Server i => Version -> (Object 'Server i -> STM ()) -> Global
createGlobal supportedVersion bindFn =
  Global {
    interface = interfaceName @i,
    version = min supportedVersion (interfaceVersion @i),
    bindObject
  }
  where
    bindObject :: GenericNewId -> ProtocolM 'Server ()
    bindObject newId = do
      object <- bindObjectFromId Nothing newId
      liftSTM $ bindFn object

Jens Nolte's avatar
Jens Nolte committed
addRegistryConnection :: Registry -> Object 'Server Interface_wl_registry -> STM ()
addRegistryConnection registry wlRegistry = do
  setMessageHandler wlRegistry messageHandler
  modifyTVar registry.connections (connection:)
Jens Nolte's avatar
Jens Nolte committed
  forM_ (zip [0..] (toList registry.singletons)) (sendGlobal wlRegistry)
Jens Nolte's avatar
Jens Nolte committed
  where
    connection = RegistryConnection { registry, wlRegistry }
    messageHandler :: RequestHandler_wl_registry
    messageHandler = RequestHandler_wl_registry {
Jens Nolte's avatar
Jens Nolte committed
      bind = bindHandler registry (objectProtocol wlRegistry)
Jens Nolte's avatar
Jens Nolte committed
sendGlobal :: Object 'Server Interface_wl_registry -> (Word32, Global) -> STM ()
sendGlobal wlRegistry (name, global) = wlRegistry.global name global.interface global.version

bindHandler :: Registry -> ProtocolHandle 'Server -> Word32 -> GenericNewId -> STM ()
bindHandler registry protocolHandle name newId = do
  case Seq.lookup (fromIntegral name) registry.singletons of
    Just global -> runProtocolM protocolHandle (global.bindObject newId)
    Nothing -> traceM $ "Invalid global " <> show name
  -- TODO dynamic globals

Jens Nolte's avatar
Jens Nolte committed
data Global = Global {
  interface :: WlString,
Jens Nolte's avatar
Jens Nolte committed
  version :: Word32,
  bindObject :: GenericNewId -> ProtocolM 'Server ()
Jens Nolte's avatar
Jens Nolte committed
}
Jens Nolte's avatar
Jens Nolte committed

maxVersion :: Version
maxVersion = maxBound