Wrap internal events in a new InternalEvent type to improve how signal handling is done

This change modifies the Input type's event channel API to produce
InternalEvents, not Events. The new InternalEvent either wraps Event
with the InputEvent constructor (the previous behavior) or indicates
that Vty resumed after handling a signal using the ResumeAfterSignal
constructor. This change avoids the previous use of EvResize with lazy
exception arguments as a sentinel value for ResumeAfterSignal.
This commit is contained in:
Jonathan Daugherty 2022-03-14 12:56:27 -07:00
parent 4969735ce4
commit 2cd98a862c
4 changed files with 24 additions and 12 deletions

View File

@ -48,6 +48,7 @@ where
import Graphics.Vty.Config import Graphics.Vty.Config
import Graphics.Vty.Input import Graphics.Vty.Input
import Graphics.Vty.Input.Events
import Graphics.Vty.Output import Graphics.Vty.Output
import Graphics.Vty.Output.Interface import Graphics.Vty.Output.Interface
import Graphics.Vty.Picture import Graphics.Vty.Picture
@ -209,16 +210,18 @@ internalMkVty input out = do
maybe (return ()) innerUpdate mPic maybe (return ()) innerUpdate mPic
let mkResize = uncurry EvResize <$> displayBounds out let mkResize = uncurry EvResize <$> displayBounds out
handleInternalEvent ResumeAfterSignal = mkResize
handleInternalEvent (InputEvent e) = return e
gkey = do gkey = do
k <- atomically $ readTChan $ _eventChannel input e <- atomically $ readTChan $ _eventChannel input
case k of handleInternalEvent e
(EvResize _ _) -> mkResize
_ -> return k
gkey' = do gkey' = do
k <- atomically $ tryReadTChan $ _eventChannel input mEv <- atomically $ tryReadTChan $ _eventChannel input
case k of case mEv of
(Just (EvResize _ _)) -> Just <$> mkResize Just e -> Just <$> handleInternalEvent e
_ -> return k Nothing -> return Nothing
return $ Vty { update = innerUpdate return $ Vty { update = innerUpdate
, nextEvent = gkey , nextEvent = gkey

View File

@ -158,9 +158,8 @@ inputForConfig config@Config{ termName = Just termName
setAttrs setAttrs
input <- initInput config activeInputMap input <- initInput config activeInputMap
let pokeIO = Catch $ do let pokeIO = Catch $ do
let e = error "vty internal failure: this value should not propagate to users"
setAttrs setAttrs
atomically $ writeTChan (input^.eventChannel) (EvResize e e) atomically $ writeTChan (input^.eventChannel) ResumeAfterSignal
_ <- installHandler windowChange pokeIO Nothing _ <- installHandler windowChange pokeIO Nothing
_ <- installHandler continueProcess pokeIO Nothing _ <- installHandler continueProcess pokeIO Nothing

View File

@ -76,3 +76,13 @@ data Event
instance NFData Event instance NFData Event
type ClassifyMap = [(String,Event)] type ClassifyMap = [(String,Event)]
-- | The type of internal events that drive the internal Vty event
-- dispatching to the application.
data InternalEvent =
ResumeAfterSignal
-- ^ Vty resumed operation after the process was interrupted with a
-- signal. In practice this translates into a screen redraw in the
-- input event loop.
| InputEvent Event
-- ^ An input event was received.

View File

@ -55,7 +55,7 @@ data Input = Input
{ -- | Channel of events direct from input processing. Unlike { -- | Channel of events direct from input processing. Unlike
-- 'nextEvent' this will not refresh the display if the next event -- 'nextEvent' this will not refresh the display if the next event
-- is an 'EvResize'. -- is an 'EvResize'.
_eventChannel :: TChan Event _eventChannel :: TChan InternalEvent
-- | Shuts down the input processing. As part of shutting down the -- | Shuts down the input processing. As part of shutting down the
-- input, this should also restore the input state. -- input, this should also restore the input state.
, shutdownInput :: IO () , shutdownInput :: IO ()
@ -115,7 +115,7 @@ addBytesToProcess block = unprocessedBytes <>= block
emit :: Event -> InputM () emit :: Event -> InputM ()
emit event = do emit event = do
logMsg $ "parsed event: " ++ show event logMsg $ "parsed event: " ++ show event
view eventChannel >>= liftIO . atomically . flip writeTChan event view eventChannel >>= liftIO . atomically . flip writeTChan (InputEvent event)
-- The timing requirements are assured by the VMIN and VTIME set for the -- The timing requirements are assured by the VMIN and VTIME set for the
-- device. -- device.