diff --git a/Graphics/Vty/LLInput.hs b/Graphics/Vty/LLInput.hs
--- a/Graphics/Vty/LLInput.hs
+++ b/Graphics/Vty/LLInput.hs
@@ -12,6 +12,8 @@
 import System.Posix.Signals
 import System.Posix.Terminal
 
+import System.Posix.IO (stdInput, fdRead, setFdOption, FdOption(..))
+
 -- |Representations of non-modifier keys.
 data Key = KEsc | KFun Int | KPrtScr | KPause | KASCII Char | KBS | KIns
          | KHome | KPageUp | KDel | KEnd | KPageDown | KNP5 | KUp | KMenu
@@ -32,6 +34,7 @@
 threadName _str = return ()
 
 data KClass = Valid Key [Modifier] | Invalid | Prefix | MisPfx Key [Modifier] [Char]
+    deriving(Show)
 
 -- | Set up the terminal for input.  Returns a function which reads key
 -- events, and a function for shutting down the terminal access.
@@ -39,39 +42,47 @@
 initTermInput = do
   threadName "main"
   kchan <- newEmptyMVar
-  kmv <- newEmptyMVar
-  oattr <- getTerminalAttributes 0
+  oattr <- getTerminalAttributes stdInput
   let nattr = foldl withoutMode oattr [StartStopOutput, KeyboardInterrupts,
                                        EnableEcho, ProcessInput]
-  setTerminalAttributes 0 nattr Immediately
-  iothr <- forkIO $ iothread kmv kchan
+  setTerminalAttributes stdInput nattr Immediately
+  iothr <- forkIO $ iothread kchan
   let pokeIO = (Catch $ do threadName "winch|cont"
-                           tryPutMVar kmv '\xFFFD'
                            let e = error "(getsize in input layer)"
-                           setTerminalAttributes 0 nattr Immediately
+                           setTerminalAttributes stdInput nattr Immediately
                            putMVar kchan (EvResize e e))
   installHandler windowChange pokeIO Nothing
   installHandler continueProcess pokeIO Nothing
   let uninit = do killThread iothr
                   installHandler windowChange Ignore Nothing
                   installHandler continueProcess Ignore Nothing
-                  setTerminalAttributes 0 oattr Immediately
+                  setTerminalAttributes stdInput oattr Immediately
   return (takeMVar kchan, uninit)
 
-iothread :: MVar Char -> MVar Event -> IO ()
-iothread kmv chn = threadName "kbd" >> loop [] where
+iothread :: MVar Event -> IO ()
+iothread chn = threadName "kbd" >> loop [] where
     loop kb = case (classify kb) of
-                Prefix       -> do ch <- getInput (kb == "")
+                Prefix       -> do ch <- getInput
                                    loop (kb ++ [ch])
                 Invalid      -> loop ""
                 MisPfx k m s -> putMVar chn (EvKey k m) >> loop s
                 Valid k m    -> putMVar chn (EvKey k m) >> loop ""
-    getInput wf = do t1 <- forkIO $ threadName "getc" >> getChar >>= putMVar kmv
-                     t2 <- forkIO $ threadName "sleep" >> if wf then return () else
-                                        threadDelay 50000 >> putMVar kmv '\xFFFE'
-                     ch <- takeMVar kmv
-                     mapM_ killThread [t1,t2]
-                     return ch
+    getInput = do 
+        catch 
+            (do
+                setFdOption stdInput NonBlockingRead True
+                (bytes, bytes_read) <- fdRead stdInput 1 
+                if (bytes_read > 0)
+                    then do
+                        let out_byte = head bytes
+                        return (head bytes)
+                    else do
+                        threadDelay 50000
+                        return '\xFFFE'
+            )
+            (\_ -> do
+                threadDelay 50000
+                return '\xFFFE')
 
 compile :: [[([Char],(Key,[Modifier]))]] -> [Char] -> KClass
 compile lst = cl' where
@@ -89,16 +100,19 @@
 -- ANSI specific bits
 
 classify :: [Char] -> KClass
-classify = compile $
-           [ let k c s = ("\ESC["++c,(s,[])) in
-             [ k "A" KUp, k "B" KDown, k "C" KRight, k "D" KLeft, k "G" KNP5, k "P" KPause ],
-             let k n s = ("\ESC["++show n++"~",(s,[])) in zipWith k [1::Int ..6] [KHome,KIns,KDel,KEnd,KPageUp,KPageDown],
-             [ (x:[],(KASCII x,[])) | x <- map toEnum [0..255] ],
-             [ ("\ESC[["++[toEnum(64+i)],(KFun i,[])) | i <- [1..5] ],
-             let f ff nrs m = [ ("\ESC["++show n++"~",(KFun (n-(nrs!!0)+ff), m)) | n <- nrs ] in
-             concat [ f 6 [17..21] [], f 11 [23,24] [], f 1 [25,26] [MShift], f 3 [28,29] [MShift], f 5 [31..34] [MShift] ],
-             [ ('\ESC':[x],(KASCII x,[MMeta])) | x <- '\ESC':'\t':[' ' .. '\DEL'] ],
-             [ ([toEnum x],(KASCII y,[MCtrl])) | (x,y) <- zip [0..31] ('@':['a'..'z']++['['..'_']) ],
-             [ ('\ESC':[toEnum x],(KASCII y,[MMeta,MCtrl])) | (x,y) <- zip [0..31] ('@':['a'..'z']++['['..'_']) ],
-             [ ("\ESC",(KEsc,[])) , ("\ESC\ESC",(KEsc,[MMeta])) , ("\DEL",(KBS,[])), ("\ESC\DEL",(KBS,[MMeta])),
-               ("\ESC\^J",(KEnter,[MMeta])), ("\^J",(KEnter,[])) ] ]
+classify = compile ansi_classify_table
+
+ansi_classify_table =
+   [ let k c s = ("\ESC["++c,(s,[])) in
+     [ k "A" KUp, k "B" KDown, k "C" KRight, k "D" KLeft, k "G" KNP5, k "P" KPause ],
+     let k n s = ("\ESC["++show n++"~",(s,[])) in zipWith k [1::Int ..6] [KHome,KIns,KDel,KEnd,KPageUp,KPageDown],
+     [ (x:[],(KASCII x,[])) | x <- map toEnum [0..255] ],
+     [ ("\ESC[["++[toEnum(64+i)],(KFun i,[])) | i <- [1..5] ],
+     let f ff nrs m = [ ("\ESC["++show n++"~",(KFun (n-(nrs!!0)+ff), m)) | n <- nrs ] in
+     concat [ f 6 [17..21] [], f 11 [23,24] [], f 1 [25,26] [MShift], f 3 [28,29] [MShift], f 5 [31..34] [MShift] ],
+     [ ('\ESC':[x],(KASCII x,[MMeta])) | x <- '\ESC':'\t':[' ' .. '\DEL'] ],
+     [ ([toEnum x],(KASCII y,[MCtrl])) | (x,y) <- zip ([0..8] ++ [10..31]) ('@':['a'..'h'] ++ ['j'..'z']++['['..'_']) ],
+     [ ('\ESC':[toEnum x],(KASCII y,[MMeta,MCtrl])) | (x,y) <- zip [0..31] ('@':['a'..'z']++['['..'_']) ],
+     [ ("\ESC",(KEsc,[])) , ("\ESC\ESC",(KEsc,[MMeta])) , ("\DEL",(KBS,[])), ("\ESC\DEL",(KBS,[MMeta])),
+       ("\ESC\^J",(KEnter,[MMeta])), ("\^J",(KEnter,[])) ] ]
+
diff --git a/README b/README
--- a/README
+++ b/README
@@ -46,9 +46,7 @@
 * Uses the TIOCGWINSZ ioctl to find the current window size, which
   appears to be limited to Linux and *BSD.
 
-darcs get --tag=rel-3.0.0 http://members.cox.net/stefanor/vty
-
-http://members.cox.net/stefanor/vty/dist/vty-3.0.0.tar.gz
+darcs get --tag=rel-3.0.0 http://code.haskell.org/vty/
 
 To compile the demonstration program: ghc --make Test.hs gwinsz.c
 
diff --git a/TODO b/TODO
--- a/TODO
+++ b/TODO
@@ -2,6 +2,7 @@
 - xterm keyboard support
 - Termcap/terminfo parser
 - 256 color support (xterm)
+- Improve input handling performance.
 
 Major:
 - Remove size fields in resize constr
diff --git a/vty.cabal b/vty.cabal
--- a/vty.cabal
+++ b/vty.cabal
@@ -1,9 +1,9 @@
 Name:                vty
-Version:             3.0.1
+Version:             3.0.2
 License:             BSD3
 License-file:        LICENSE
 Author:              Stefan O'Rear
-Maintainer:          Stefan O'Rear <stefanor@cox.net>
+Maintainer:          Corey O'Connor (coreyoconnor@gmail.com)
 Category:            User Interfaces
 Synopsis:            A simple terminal access library
 Description:
@@ -16,7 +16,7 @@
   Notable infelicities: requires an ANSI-type terminal, poor efficiency,
                         requires Linux\/xterm style UTF8 support.
   .
-  You can 'darcs get' it from <http://members.cox.net/stefanor/vty>
+  You can 'darcs get' it from <http://code.haskell.org/vty/>
   &#169; 2006-2007 Stefan O'Rear; BSD3 license.
 
 Build-Depends:       base>3, bytestring, containers, unix
