diff --git a/Control/DysFRP/Cairo.hs b/Control/DysFRP/Cairo.hs
new file mode 100644
--- /dev/null
+++ b/Control/DysFRP/Cairo.hs
@@ -0,0 +1,136 @@
+module Control.DysFRP.Cairo(GtkEvent, mkTickerE, 
+    drawContextOnSurface, drawContextOnDrawable,
+    addRefresher, addBufRefresher, addDrawingAreaRefresher,
+    addDrawingAreaRefresherG,
+    addTick,
+    reactiveOn, eventData, 
+    prerenderBG,
+    concatContextB,
+    RenderContext, mkContext,
+    keyValE, keyNameE, modifierE, keyValModifierE, keyLeftE, keyRightE, keyUpE, keyDownE) where
+
+import qualified Control.DysFRP.Internal as R
+import Data.IORef
+import Control.Applicative
+import Control.Monad.Trans
+import Control.Monad.Reader
+import Graphics.UI.Gtk
+import Graphics.UI.Gtk.Gdk.GC
+import qualified Graphics.Rendering.Cairo as C
+import Foreign.Ptr
+import Data.Traversable
+
+data GtkEvent a = GtkEvent { fromGtkEvent :: Ptr a }
+
+type RenderContext = Double -> Double -> IO (C.Render ())
+
+zeroRenderContext = \_ _ -> return (return ())
+appendRenderContext c1 c2 = \a b -> liftM2 (>>) (c1 a b) (c2 a b)
+concatContext = foldr appendRenderContext zeroRenderContext
+mkContext c = \_ _ -> return c
+
+drawContextOnSurface :: C.Surface -> RenderContext -> IO ()
+drawContextOnSurface srf fig = do
+    w <- C.imageSurfaceGetWidth srf
+    h <- C.imageSurfaceGetHeight srf
+    rnd <- fig (fromIntegral w) (fromIntegral h)
+    C.renderWith srf rnd
+
+drawContextOnDrawable :: DrawableClass d => d -> RenderContext -> IO ()
+drawContextOnDrawable srf fig = do
+    (w, h) <- drawableGetSize srf
+    rnd <- fig (fromIntegral w) (fromIntegral h)
+    renderWithDrawable srf rnd
+
+mkTickerE :: Int -> IO (HandlerId, R.Event ())
+mkTickerE k = do
+    (f, e) <- R.mkE
+    c <- timeoutAdd (f () >> return True) k
+    return (c, e)
+
+addRefresher :: DrawableClass d => Int -> d -> R.Behavior RenderContext -> IO HandlerId
+addRefresher k srf fig = flip timeoutAdd k $ R.runBehavior fig >>= drawContextOnDrawable srf >> return True
+
+addBufRefresher :: DrawableClass d => Int -> d -> R.Behavior RenderContext -> IO HandlerId
+addBufRefresher k srf2 fig = do
+    (mx, my) <- drawableGetSize srf2
+    srf1 <- pixmapNew (Just srf2) mx my Nothing
+    gc <- gcNew srf2
+    flip timeoutAdd k $ R.runBehavior fig >>= drawContextOnDrawable srf1 >> do
+        drawDrawable srf2 gc srf1 0 0 0 0 (-1) (-1) >> return True
+
+addDrawingAreaRefresher k drawingarea fig = do
+    canvas <- widgetGetDrawWindow drawingarea
+    (mx, my) <- {-fmap fixSize $-} drawableGetSize canvas
+    srfp <- newIORef =<< pixmapNew (Just canvas) mx my Nothing
+    gc <- gcNew canvas
+{-    on drawingarea configureEvent $ do
+        (x, y) <- fmap fixSize $ eventSize
+        liftIO $ print (x,y)
+        liftIO $ writeIORef srfp =<< pixmapNew (Just canvas) x y Nothing
+        return True-}
+    flip timeoutAdd k $ do
+        srf <- readIORef srfp
+        drawContextOnDrawable srf =<< R.runBehavior fig
+        drawDrawable canvas gc srf 0 0 0 0 (-1) (-1) >> return True
+{-    where
+    fixSize (a, b) | fromIntegral a/(px :: Double)*py > fromIntegral b = 
+                                   (round $ fromIntegral b/py*px, b)
+                   | otherwise   = (a, round $ fromIntegral a/px*py)-}
+
+addDrawingAreaRefresherG k drawingarea fig = addDrawingAreaRefresher k drawingarea =<< R.runBehavior fig
+
+addTick :: Int -> IO (R.Event ())
+addTick k = do
+    (f, e) <- R.mkE
+    flip timeoutAdd k $ f () >> return True
+    return e
+
+reactiveOn :: a -> Signal a (EventM b Bool) -> IO (ConnectId a, R.Event (GtkEvent b))
+reactiveOn obj sig = do
+    (f, e) <- R.mkE 
+    c <- on obj sig $ ask >>= liftIO . f . GtkEvent >> return True
+    return (c, e)
+
+prerenderBG :: (Int,Int) -> RenderContext -> R.Event RenderContext -> R.BehaviorGen RenderContext
+prerenderBG (w,h) fig e = R.mkBG $ liftIO $ do
+    pixmap <- C.createImageSurface C.FormatARGB32 w h
+    drawContextOnSurface pixmap fig
+    let io = do
+        C.setSourceSurface pixmap 0 0
+        C.rectangle 0 0 (fromIntegral w) (fromIntegral h)
+        C.fill 
+    hn <- io `seq` R.mkH io $ liftIO . drawContextOnSurface pixmap
+    R.addHandler e hn
+    return $ return $ mkContext io
+
+eventData :: EventM a b -> R.Event (GtkEvent a) -> R.Event b
+eventData e = R.ioMapE $ runReaderT e . fromGtkEvent
+
+concatContextB :: [R.Behavior RenderContext] -> R.Behavior RenderContext
+concatContextB = fmap concatContext . sequenceA
+
+keyValE :: R.Event (GtkEvent EKey) -> R.Event KeyVal
+keyValE = eventData eventKeyVal
+
+keyNameE :: R.Event (GtkEvent EKey) -> R.Event String
+keyNameE = eventData eventKeyName
+
+modifierE :: R.Event (GtkEvent EKey) -> R.Event [Modifier]
+modifierE = eventData eventModifier
+
+keyValModifierE :: R.Event (GtkEvent EKey) -> R.Event (KeyVal, [Modifier])
+keyValModifierE = eventData (liftM2 (,) eventKeyVal eventModifier)
+
+keyLeftE :: R.Event (GtkEvent EKey) -> R.Event ()
+keyLeftE = fmap (const ()) . R.filterE (== 0xff51) . keyValE
+
+keyRightE :: R.Event (GtkEvent EKey) -> R.Event ()
+keyRightE = fmap (const ()) . R.filterE (== 0xff53) . keyValE
+
+keyUpE :: R.Event (GtkEvent EKey) -> R.Event ()
+keyUpE = fmap (const ()) . R.filterE (== 0xff52) . keyValE
+
+keyDownE :: R.Event (GtkEvent EKey) -> R.Event ()
+keyDownE = fmap (const ()) . R.filterE (== 0xff54) . keyValE
+
diff --git a/DysFRP-Cairo.cabal b/DysFRP-Cairo.cabal
new file mode 100644
--- /dev/null
+++ b/DysFRP-Cairo.cabal
@@ -0,0 +1,18 @@
+Name: DysFRP-Cairo
+Version: 0.1
+License: BSD3
+License-File: LICENSE
+Author: Marek Materzok
+Maintainer: Marek Materzok
+Build-Type: Simple
+Stability: experimental
+Cabal-Version: >= 1.2
+Homepage: https://github.com/tilk/DysFRP
+Category: FRP
+Synopsis: dysFunctional Reactive Programming on Cairo
+Description: Simple Cairo bindings for DysFRP.
+
+Library
+    Build-Depends: base >= 4 && <5, cairo, gtk, mtl, DysFRP
+    Exposed-modules: Control.DysFRP.Cairo
+
diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2012, Marek Materzok
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+    * Redistributions in binary form must reproduce the above copyright
+      notice, this list of conditions and the following disclaimer in the
+      documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+import Distribution.Simple
+main = defaultMain
+
