[reactive] Fun with existentials

Achim Schneider barsoap at web.de
Thu Jan 29 09:00:20 EST 2009


XHB uses existentials to enable X extensions to define their own events
and still have them delivered to the user by the main library, so I had
the chance to mess around with them and reactive. If you comment out
the keyPressH, things are perfectly fine, but there's no dispatch on
event types. With the forkIO, the program stumbles over an indefinite
block on the next event. The adaptE without fromEventE is the only
thing keeping the program alive: It seems that if there is only a
single event that is possibly not handled, things go haywire... even if
every event is guaranteed to be handled (in some other adaptE).

Without any adaptE things work fine, too.

I don't know if multiple adaptE's are supposed to work, but it'd be
certainly nice if they would. I'm going to try to join the
Nothings sorted out by joinMaybes back into the stream, hopefully
that'll convince the RTS.




{-# LANGUAGE ExistentialQuantification #-}
module Main where

-- current darcs XHB
-- hack it to export Graphics.XHB.Connection.Types
-- port of http://en.wikibooks.org/wiki/X_Window_Programming/XCB
-- run your X server on :0 or change getScreen

import Graphics.XHB as X
import FRP.Reactive as R
import FRP.Reactive.LegacyAdapters
import Control.Concurrent
import Control.Monad
import System.Exit
import Control.Applicative


printErrors c = (forkIO . forever) $ waitForError c >>= print
getScreen = head . roots_Setup . conf_setup . conn_conf
castXid = fromXid . toXid

main = do
    (Just c) <- connect
    printErrors c
    print $ displayInfo c
    let s     = getScreen c
        black = black_pixel_SCREEN s
        white = white_pixel_SCREEN s
        root  = root_SCREEN s
        depth = root_depth_SCREEN s
        visual = root_visual_SCREEN s


    g <- newResource c
    createGC c (MkCreateGC 
        g 
        (castXid root) 
        (toValueParam 
            [(GCForeground,white)
            ,(GCGraphicsExposures,0)
            ]
        ))

    w <- newResource c
    createWindow c (MkCreateWindow 
        depth w root     
        0 0 640 480
        0 0 visual
        (toValueParam
            [(CWBackPixel,black)
            ,(CWEventMask,toMask
                [ EventMaskExposure
                , EventMaskKeyPress 
                ]
             )
            ]
         ))

    lock <- newEmptyMVar
    sync <- makeSync
    evs <- eventsE sync c
    mapWindow c w
    forkIO $ adaptE $ keyPressH lock c $ fromEventE evs 
--    forkIO $ adaptE $ exposeH c $ fromEventE evs 
    adaptE $ (fmap.const) (putStrLn "some event" ) evs

    --readMVar lock

keyPressH :: MVar () -> Connection -> R.Event KeyPress -> R.Event Action
keyPressH lock _ = (fmap.const) $ putStrLn "key" >> putMVar lock ()

exposeH :: Connection -> R.Event KeyPress -> R.Event Action
exposeH _ = fmap print

fromEventE :: X.Event a => R.Event SomeEvent -> R.Event a
fromEventE = joinMaybes <$> fmap fromEvent

type Sync = Clock TimeT
makeSync = makeClock

eventsE :: Sync -> Connection -> IO (R.Event SomeEvent)
eventsE cl c = do
    (sink, res) <- makeEvent cl
    (forkIO . forever) $
        putStrLn "tick " >> waitForEvent c >>= sink
    return res



-- 
(c) this sig last receiving data processing entity. Inspect headers
for copyright history. All rights reserved. Copying, hiring, renting,
performance and/or quoting of this signature prohibited.




More information about the Reactive mailing list