From 9b8e6ec95668dc1cd76dd0b40f8b6d6b74ebaee0 Mon Sep 17 00:00:00 2001 From: Jens Nolte <git@queezle.net> Date: Wed, 3 Aug 2022 12:55:43 +0200 Subject: [PATCH] Send wl_display.delete_id --- src/Quasar/Wayland/Client.hs | 2 +- src/Quasar/Wayland/Protocol/Core.hs | 51 ++++++++++++++++++++--------- src/Quasar/Wayland/Protocol/TH.hs | 4 +-- src/Quasar/Wayland/Server.hs | 2 +- 4 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/Quasar/Wayland/Client.hs b/src/Quasar/Wayland/Client.hs index ce64551..3c4aa1b 100644 --- a/src/Quasar/Wayland/Client.hs +++ b/src/Quasar/Wayland/Client.hs @@ -48,7 +48,7 @@ newWaylandClient socket = do } where newClientDisplay :: STM ((Object 'Client Interface_wl_display, Registry), ProtocolHandle 'Client) - newClientDisplay = initializeProtocol wlDisplayEventHandler initalize + newClientDisplay = initializeProtocol wlDisplayEventHandler (\_ _ -> unreachableCodePathM) initalize initalize :: Object 'Client Interface_wl_display -> STM (Object 'Client Interface_wl_display, Registry) initalize wlDisplay = do diff --git a/src/Quasar/Wayland/Protocol/Core.hs b/src/Quasar/Wayland/Protocol/Core.hs index bc56fa3..c4644a1 100644 --- a/src/Quasar/Wayland/Protocol/Core.hs +++ b/src/Quasar/Wayland/Protocol/Core.hs @@ -42,7 +42,6 @@ module Quasar.Wayland.Protocol.Core ( -- * Low-level protocol interaction objectWireArgument, nullableObjectWireArgument, - handleDestructor, checkObject, sendMessage, newObject, @@ -71,7 +70,7 @@ module Quasar.Wayland.Protocol.Core ( ) where import Control.Monad.Catch -import Control.Monad.Reader (ReaderT, runReaderT, ask, lift) +import Control.Monad.Reader (ReaderT, runReaderT, ask, asks, lift) import Data.Binary import Data.Binary.Get import Data.Binary.Put @@ -104,6 +103,9 @@ newtype GenericObjectId = GenericObjectId Word32 toGenericObjectId :: ObjectId j -> GenericObjectId toGenericObjectId (ObjectId oId) = GenericObjectId oId +objectIdValue :: ObjectId j -> Word32 +objectIdValue (ObjectId value) = value + type Opcode = Word16 type Version = Word32 @@ -243,6 +245,8 @@ class Typeable s => IsSide (s :: Side) where type WireDown s i initialId :: Word32 maximumId :: Word32 + -- | Should be called by generated code _after_ calling a destructor. + handleDestructor :: IsInterfaceSide s i => Object s i -> ProtocolM s () -> ProtocolM s () instance IsSide 'Client where type MessageHandler 'Client i = EventHandler i @@ -251,6 +255,7 @@ instance IsSide 'Client where -- Id #1 is reserved for wl_display initialId = 2 maximumId = 0xfeffffff + handleDestructor object msgFn = handleDestructorPre object >> msgFn instance IsSide 'Server where type MessageHandler 'Server i = RequestHandler i @@ -258,6 +263,21 @@ instance IsSide 'Server where type WireDown 'Server i = WireRequest i initialId = 0xff000000 maximumId = 0xffffffff + handleDestructor object msgFn = do + handleDestructorPre object + msgFn + when (oid <= maximumId @'Client) do + sendWlDisplayDeleteId :: Word32 -> STM () <- asks (.sendWlDisplayDeleteId) + liftSTM $ sendWlDisplayDeleteId oid + where + oid :: Word32 + oid = objectIdValue object.objectId + +-- Shared destructor code for client and server +handleDestructorPre :: IsInterfaceSide s i => Object s i -> ProtocolM s () +handleDestructorPre object = do + traceM $ "Destroying " <> showObject object + lift $ writeTVar object.destroyed True class ( @@ -416,13 +436,14 @@ data ProtocolState (s :: Side) = ProtocolState { outboxVar :: TVar (Maybe Put), outboxFdsVar :: TVar (Seq Fd), objectsVar :: TVar (HashMap GenericObjectId (SomeObject s)), - nextIdVar :: TVar Word32 + nextIdVar :: TVar Word32, + sendWlDisplayDeleteId :: Word32 -> STM () } type ProtocolM s a = ReaderT (ProtocolState s) STM a askProtocol :: ProtocolM s (ProtocolHandle s) -askProtocol = (.protocolHandle) <$> ask +askProtocol = asks (.protocolHandle) readProtocolVar :: (ProtocolState s -> TVar a) -> ProtocolM s a readProtocolVar fn = do @@ -457,9 +478,13 @@ swapProtocolVar fn x = do initializeProtocol :: forall s wl_display a. (IsInterfaceSide s wl_display) => (ProtocolHandle s -> MessageHandler s wl_display) + -- FIXME only required for server code + -> (Object s wl_display -> Word32 -> STM ()) + -- ^ Send a wl_display.delete_id message. Because this is part of the core protocol but generated from the xml it has + -- to be provided by the main server module. -> (Object s wl_display -> STM a) -> STM (a, ProtocolHandle s) -initializeProtocol wlDisplayMessageHandler initializationAction = do +initializeProtocol wlDisplayMessageHandler sendWlDisplayDeleteId initializationAction = do bytesReceivedVar <- newTVar 0 bytesSentVar <- newTVar 0 inboxDecoderVar <- newTVar $ runGetIncremental getRawMessage @@ -477,6 +502,10 @@ initializeProtocol wlDisplayMessageHandler initializationAction = do stateVar } + messageHandlerVar <- newTVar (Just (wlDisplayMessageHandler protocol)) + destroyed <- newTVar False + let wlDisplay = Object protocol wlDisplayId messageHandlerVar destroyed + let state = ProtocolState { protocolHandle = protocol, protocolKey, @@ -487,13 +516,11 @@ initializeProtocol wlDisplayMessageHandler initializationAction = do outboxVar, outboxFdsVar, objectsVar, - nextIdVar + nextIdVar, + sendWlDisplayDeleteId = (sendWlDisplayDeleteId wlDisplay) } writeTVar stateVar (Right state) - messageHandlerVar <- newTVar (Just (wlDisplayMessageHandler protocol)) - destroyed <- newTVar False - let wlDisplay = Object protocol wlDisplayId messageHandlerVar destroyed modifyTVar' objectsVar (HM.insert (toGenericObjectId wlDisplayId) (SomeObject wlDisplay)) result <- initializationAction wlDisplay @@ -675,12 +702,6 @@ handleWlDisplayDeleteId protocol oId = runProtocolM protocol do modifyProtocolVar (.objectsVar) $ HM.delete (GenericObjectId oId) -handleDestructor :: IsInterfaceSide s i => Object s i -> ProtocolM s () -handleDestructor object = do - traceM $ "Handling destructor for " <> showObject object - lift $ writeTVar object.destroyed True - - checkObject :: IsInterface i => Object s i -> ProtocolM s (Either String ()) checkObject object = do -- TODO check if object belongs to current connection diff --git a/src/Quasar/Wayland/Protocol/TH.hs b/src/Quasar/Wayland/Protocol/TH.hs index 10f6410..1fbb56f 100644 --- a/src/Quasar/Wayland/Protocol/TH.hs +++ b/src/Quasar/Wayland/Protocol/TH.hs @@ -258,7 +258,7 @@ interfaceDecs interface = do msgHandlerE = [|$(appTypeE [|getField|] fieldNameLitT) $handlerE|] bodyE :: Q Exp bodyE - | msg.msgSpec.isDestructor = [|handleDestructor $objectE >> $msgE|] + | msg.msgSpec.isDestructor = [|handleDestructor $objectE $msgE|] | otherwise = msgE msgE :: Q Exp msgE = [|$(applyMsgArgs msgHandlerE) >>= lift|] @@ -312,7 +312,7 @@ messageProxyInstanceDecs side messageContexts = mapM messageProxyInstanceD messa msgE idArgE = mkWireMsgE (idArgE : (wireArgE <$> args)) dtorE :: Q Exp - dtorE = [|handleDestructor object >> $normalE|] + dtorE = [|handleDestructor object $normalE|] -- Body for a normal (i.e. non-constructor) proxy normalE :: Q Exp diff --git a/src/Quasar/Wayland/Server.hs b/src/Quasar/Wayland/Server.hs index a3f1c4c..1d8ba76 100644 --- a/src/Quasar/Wayland/Server.hs +++ b/src/Quasar/Wayland/Server.hs @@ -41,7 +41,7 @@ newWaylandServerConnection server socket = do } where newServerDisplay :: STM (Object 'Server Interface_wl_display, ProtocolHandle 'Server) - newServerDisplay = initializeProtocol wlDisplayRequestHandler pure + newServerDisplay = initializeProtocol wlDisplayRequestHandler (.delete_id) pure wlDisplayRequestHandler :: ProtocolHandle 'Server -> RequestHandler_wl_display wlDisplayRequestHandler _protocol = -- GitLab