diff --git a/lib/blinqpage.cpp b/lib/blinqpage.cpp
index 94a20447a2b094629dde5ae3e5995791a08b2fde..b56558078810bbc4503b5d1b428e0e3dc93f637d 100644
--- a/lib/blinqpage.cpp
+++ b/lib/blinqpage.cpp
@@ -39,7 +39,6 @@
 #include "content/browser/renderer_host/backing_store_gtk.h"
 #include "webkit/user_agent/user_agent_util.h"
 #include "skia/ext/platform_canvas.h"
-#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
 
 #include "backing_store_qt.h"
 #include "raster_window.h"
@@ -51,12 +50,9 @@
 #include <QGuiApplication>
 #include <qpa/qplatformwindow.h>
 #include <QLabel>
-#include <QMouseEvent>
 #include <QPainter>
 #include <qpa/qplatformnativeinterface.h>
 
-#include <X11/Xutil.h>
-
 namespace {
 
 class Context;
@@ -165,6 +161,7 @@ inline net::URLRequestContext* ResourceContext::GetRequestContext()
     return context->GetRequestContext()->GetURLRequestContext();
 }
 
+
 class RenderViewHost : public content::RenderViewHostImpl
 {
 public:
diff --git a/lib/lib.pro b/lib/lib.pro
index 36b80884112feda949e36302d8866b8f9e779e81..31c03d72083629bdb615f82901d5facd2d4ebc81 100644
--- a/lib/lib.pro
+++ b/lib/lib.pro
@@ -23,12 +23,14 @@ SOURCES = \
         render_widget_host_view_qt.cpp \
         shell_qt.cpp \
         signal_connector.cpp \
-        moc_signal_connector.cpp 
+        web_event_factory.cpp \
+        moc_signal_connector.cpp
 
 HEADERS = \
         backing_store_qt.h \
         blinqpage.h \
         raster_window.h \
         render_widget_host_view_qt.h \
+        web_event_factory.h \
         signal_connector.h
 
diff --git a/lib/raster_window.cpp b/lib/raster_window.cpp
index 3c4b12fd289ab70504c1c6ecab58d3ba945e60af..4613f8081c8c5ececf1b7394ba16ba83f766c335 100644
--- a/lib/raster_window.cpp
+++ b/lib/raster_window.cpp
@@ -46,12 +46,8 @@ bool RasterWindow::event(QEvent *event)
     case QEvent::UpdateRequest:
         renderNow();
         return true;
-    case QEvent::MouseButtonDblClick:
-    case QEvent::MouseButtonPress:
-    case QEvent::MouseButtonRelease:
-//    case QEvent::KeyPress:
-        if (m_view)
-            return m_view->handleEvent(event);
     }
-    return QWindow::event(event);
+    if (!m_view || !m_view->handleEvent(event))
+        return QWindow::event(event);
+    return true;
 }
diff --git a/lib/render_widget_host_view_qt.cpp b/lib/render_widget_host_view_qt.cpp
index 83e5026af9b1c4c6fbd34363096739fccfcf38a9..edb5df21ac198201010cf5739d2f51efc26ff6c3 100644
--- a/lib/render_widget_host_view_qt.cpp
+++ b/lib/render_widget_host_view_qt.cpp
@@ -1,6 +1,8 @@
 #include "render_widget_host_view_qt.h"
 
 #include "backing_store_qt.h"
+#include "web_event_factory.h"
+
 #include "content/browser/renderer_host/render_view_host_impl.h"
 #include "content/common/gpu/gpu_messages.h"
 #include "raster_window.h"
@@ -8,6 +10,7 @@
 
 #include <QEvent>
 #include <QMouseEvent>
+#include <QKeyEvent>
 #include <QScreen>
 
 #include <QDebug>
@@ -54,13 +57,15 @@ bool RenderWidgetHostView::handleEvent(QEvent* event) {
     case QEvent::MouseButtonDblClick:
     case QEvent::MouseButtonPress:
     case QEvent::MouseButtonRelease:
+    case QEvent::MouseMove:
         handleMouseEvent(static_cast<QMouseEvent*>(event));
         break;
-//        case QEvent::KeyPress:
-//            handleKeyEvent(event);
-//            break;
+    case QEvent::KeyPress:
+    case QEvent::KeyRelease:
+        handleKeyEvent(static_cast<QKeyEvent*>(event));
+        break;
     default:
-        Q_ASSERT(false); // not reached
+        return false;
     }
     return true;
 }
@@ -419,17 +424,12 @@ bool RenderWidgetHostView::IsPopup() const
 
 void RenderWidgetHostView::handleMouseEvent(QMouseEvent* ev)
 {
-    qDebug() << ev << ev->pos();
-    WebKit::WebMouseEvent webKitEvent;
-    webKitEvent.x = ev->x();
-    webKitEvent.y = ev->y();
-    webKitEvent.globalX = ev->globalX();
-    webKitEvent.globalY = ev->globalY();
-    webKitEvent.clickCount = (ev->type() == QEvent::MouseButtonDblClick)? 2 : 1;
-    webKitEvent.button = mouseButtonForEvent(ev);
-    //FIXME: and window coordinates ?
-
-    m_host->ForwardMouseEvent(webKitEvent);
+    m_host->ForwardMouseEvent(WebEventFactory::toWebMouseEvent(ev));
+}
+
+void RenderWidgetHostView::handleKeyEvent(QKeyEvent *ev)
+{
+    m_host->ForwardKeyboardEvent(WebEventFactory::toWebKeyboardEvent(ev));
 }
 
 
diff --git a/lib/render_widget_host_view_qt.h b/lib/render_widget_host_view_qt.h
index 30a471ee4eb88e999eb4f2a91b51ad30575741e1..84bcfdf8184ff398298494e990991fa82a888af7 100644
--- a/lib/render_widget_host_view_qt.h
+++ b/lib/render_widget_host_view_qt.h
@@ -5,6 +5,7 @@
 
 class QEvent;
 class QMouseEvent;
+class QKeyEvent;
 class RasterWindow;
 
 class RenderWidgetHostView
@@ -78,11 +79,12 @@ private:
     void Paint(const gfx::Rect& scroll_rect);
 
     bool IsPopup() const;
-    void handleMouseEvent(QMouseEvent* ev);
+    void handleMouseEvent(QMouseEvent*);
+    void handleKeyEvent(QKeyEvent*);
 
     content::RenderWidgetHostImpl *m_host;
     RasterWindow *m_view;
     gfx::Size m_requestedSize;
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/lib/web_event_factory.cpp b/lib/web_event_factory.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6d1d6386f7f784764d6fbd3612c1acabbf0bdd14
--- /dev/null
+++ b/lib/web_event_factory.cpp
@@ -0,0 +1,85 @@
+#include "web_event_factory.h"
+
+#include <QMouseEvent>
+#include <QKeyEvent>
+
+using namespace WebKit;
+
+static WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event)
+{
+    if (event->button() == Qt::LeftButton || (event->buttons() & Qt::LeftButton))
+        return WebMouseEvent::ButtonLeft;
+    else if (event->button() == Qt::RightButton || (event->buttons() & Qt::RightButton))
+        return WebMouseEvent::ButtonRight;
+    else if (event->button() == Qt::MidButton || (event->buttons() & Qt::MidButton))
+        return WebMouseEvent::ButtonMiddle;
+    return WebMouseEvent::ButtonNone;
+}
+
+static inline WebInputEvent::Modifiers modifiersForEvent(Qt::KeyboardModifiers modifiers)
+{
+    unsigned result = 0;
+    if (modifiers & Qt::ShiftModifier)
+        result |= WebInputEvent::ShiftKey;
+    if (modifiers & Qt::ControlModifier)
+        result |= WebInputEvent::ControlKey;
+    if (modifiers & Qt::AltModifier)
+        result |= WebInputEvent::AltKey;
+    if (modifiers & Qt::MetaModifier)
+        result |= WebInputEvent::MetaKey;
+    return (WebInputEvent::Modifiers)result;
+}
+
+
+WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev)
+{
+    WebMouseEvent webKitEvent;
+    webKitEvent.timeStampSeconds = ev->timestamp() / 1000.0;
+    webKitEvent.button = mouseButtonForEvent(ev);
+    webKitEvent.modifiers = modifiersForEvent(ev->modifiers());
+
+    webKitEvent.x = webKitEvent.windowX = ev->x();
+    webKitEvent.y = webKitEvent.windowY = ev->y();
+    webKitEvent.globalX = ev->globalX();
+    webKitEvent.globalY = ev->globalY();
+
+    webKitEvent.clickCount = 0;
+    switch (ev->type()) {
+    case QEvent::MouseButtonPress:
+        webKitEvent.clickCount = 1;
+        webKitEvent.type = WebInputEvent::MouseDown;
+        break;
+    case QEvent::MouseMove:
+        webKitEvent.type = WebInputEvent::MouseMove;
+        break;
+    case QEvent::MouseButtonRelease:
+        webKitEvent.type = WebInputEvent::MouseUp;
+        break;
+    case QEvent::MouseButtonDblClick:
+        webKitEvent.clickCount = 2;
+    default:
+        Q_ASSERT(false);
+    };
+
+    return webKitEvent;
+}
+
+content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev)
+{
+    content::NativeWebKeyboardEvent webKitEvent;
+    webKitEvent.timeStampSeconds = ev->timestamp() / 1000.0;
+    webKitEvent.modifiers = modifiersForEvent(ev->modifiers());
+    switch (ev->type()) {
+    case QEvent::KeyPress:
+        webKitEvent.type = WebInputEvent::KeyDown;
+        break;
+    case QEvent::KeyRelease:
+        webKitEvent.type = WebInputEvent::KeyUp;
+        break;
+    }
+
+    webKitEvent.nativeKeyCode = ev->nativeVirtualKey();
+    // FIXME: need Windows keycode mapping from WebCore...
+    memcpy(&webKitEvent.text, ev->text().utf16(), qMin(sizeof(webKitEvent.text), sizeof(ev->text().utf16())));
+    return webKitEvent;
+}
diff --git a/lib/web_event_factory.h b/lib/web_event_factory.h
new file mode 100644
index 0000000000000000000000000000000000000000..366da641749e0b52664e4b9aa63e7172cc6ba9cb
--- /dev/null
+++ b/lib/web_event_factory.h
@@ -0,0 +1,19 @@
+#ifndef WEB_EVENT_FACTORY_H
+#define WEB_EVENT_FACTORY_H
+
+#include "content/public/browser/native_web_keyboard_event.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
+
+class QMouseEvent;
+class QKeyEvent;
+
+class WebEventFactory {
+
+public:
+    static WebKit::WebMouseEvent toWebMouseEvent(QMouseEvent*);
+    static content::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*);
+
+};
+
+
+#endif