From 49b6875074d194f38b50f385a242cc3a7d175008 Mon Sep 17 00:00:00 2001
From: Pierre Rossi <pierre.rossi@digia.com>
Date: Thu, 16 May 2013 11:49:30 +0200
Subject: [PATCH] Wheel events

---
 lib/render_widget_host_view_qt.cpp |  19 +++---
 lib/render_widget_host_view_qt.h   |   2 +
 lib/web_event_factory.cpp          | 105 +++++++++++++++++++++++------
 lib/web_event_factory.h            |   2 +
 4 files changed, 98 insertions(+), 30 deletions(-)

diff --git a/lib/render_widget_host_view_qt.cpp b/lib/render_widget_host_view_qt.cpp
index edb5df21a..3d4e3fc54 100644
--- a/lib/render_widget_host_view_qt.cpp
+++ b/lib/render_widget_host_view_qt.cpp
@@ -11,23 +11,13 @@
 #include <QEvent>
 #include <QMouseEvent>
 #include <QKeyEvent>
+#include <QWheelEvent>
 #include <QScreen>
 
 #include <QDebug>
 
 #define QT_NOT_YET_IMPLEMENTED fprintf(stderr, "function %s not implemented! - %s:%d\n", __func__, __FILE__, __LINE__);
 
-static WebKit::WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event)
-{
-    if (event->button() == Qt::LeftButton || (event->buttons() & Qt::LeftButton))
-        return WebKit::WebMouseEvent::ButtonLeft;
-    else if (event->button() == Qt::RightButton || (event->buttons() & Qt::RightButton))
-        return WebKit::WebMouseEvent::ButtonRight;
-    else if (event->button() == Qt::MidButton || (event->buttons() & Qt::MidButton))
-        return WebKit::WebMouseEvent::ButtonMiddle;
-    return WebKit::WebMouseEvent::ButtonNone;
-}
-
 static void GetScreenInfoFromNativeWindow(QWindow* window, WebKit::WebScreenInfo* results)
 {
     QScreen* screen = window->screen();
@@ -64,6 +54,8 @@ bool RenderWidgetHostView::handleEvent(QEvent* event) {
     case QEvent::KeyRelease:
         handleKeyEvent(static_cast<QKeyEvent*>(event));
         break;
+    case QEvent::Wheel:
+        handleWheelEvent(static_cast<QWheelEvent*>(event));
     default:
         return false;
     }
@@ -432,4 +424,9 @@ void RenderWidgetHostView::handleKeyEvent(QKeyEvent *ev)
     m_host->ForwardKeyboardEvent(WebEventFactory::toWebKeyboardEvent(ev));
 }
 
+void RenderWidgetHostView::handleWheelEvent(QWheelEvent *ev)
+{
+    m_host->ForwardWheelEvent(WebEventFactory::toWebWheelEvent(ev));
+}
+
 
diff --git a/lib/render_widget_host_view_qt.h b/lib/render_widget_host_view_qt.h
index 84bcfdf81..227dc820e 100644
--- a/lib/render_widget_host_view_qt.h
+++ b/lib/render_widget_host_view_qt.h
@@ -6,6 +6,7 @@
 class QEvent;
 class QMouseEvent;
 class QKeyEvent;
+class QWheelEvent;
 class RasterWindow;
 
 class RenderWidgetHostView
@@ -81,6 +82,7 @@ private:
     bool IsPopup() const;
     void handleMouseEvent(QMouseEvent*);
     void handleKeyEvent(QKeyEvent*);
+    void handleWheelEvent(QWheelEvent*);
 
     content::RenderWidgetHostImpl *m_host;
     RasterWindow *m_view;
diff --git a/lib/web_event_factory.cpp b/lib/web_event_factory.cpp
index 6d1d6386f..65d8638b5 100644
--- a/lib/web_event_factory.cpp
+++ b/lib/web_event_factory.cpp
@@ -2,9 +2,24 @@
 
 #include <QMouseEvent>
 #include <QKeyEvent>
+#include <QElapsedTimer>
+#include <QWheelEvent>
 
 using namespace WebKit;
 
+static inline double currentTimeForEvent(const QInputEvent* event)
+{
+    Q_ASSERT(event);
+
+    if (event->timestamp())
+        return static_cast<double>(event->timestamp()) / 1000;
+
+    static QElapsedTimer timer;
+    if (!timer.isValid())
+        timer.start();
+    return static_cast<double>(timer.elapsed()) / 1000;
+}
+
 static WebMouseEvent::Button mouseButtonForEvent(QMouseEvent *event)
 {
     if (event->button() == Qt::LeftButton || (event->buttons() & Qt::LeftButton))
@@ -30,11 +45,42 @@ static inline WebInputEvent::Modifiers modifiersForEvent(Qt::KeyboardModifiers m
     return (WebInputEvent::Modifiers)result;
 }
 
+static WebInputEvent::Type webEventTypeForEvent(const QEvent* event)
+{
+    switch (event->type()) {
+    case QEvent::MouseButtonPress:
+        return WebInputEvent::MouseDown;
+    case QEvent::MouseButtonRelease:
+        return WebInputEvent::MouseUp;
+    case QEvent::MouseMove:
+        return WebInputEvent::MouseMove;
+    case QEvent::Wheel:
+        return WebInputEvent::MouseWheel;
+    case QEvent::KeyPress:
+        return WebInputEvent::KeyDown;
+    case QEvent::KeyRelease:
+        return WebInputEvent::KeyUp;
+    case QEvent::TouchBegin:
+        return WebInputEvent::TouchStart;
+    case QEvent::TouchUpdate:
+        return WebInputEvent::TouchMove;
+    case QEvent::TouchEnd:
+        return WebInputEvent::TouchEnd;
+    case QEvent::TouchCancel:
+        return WebInputEvent::TouchCancel;
+    case QEvent::MouseButtonDblClick:
+        return WebInputEvent::Undefined;
+    default:
+        Q_ASSERT(false);
+        return WebInputEvent::MouseMove;
+    }
+}
+
 
 WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev)
 {
     WebMouseEvent webKitEvent;
-    webKitEvent.timeStampSeconds = ev->timestamp() / 1000.0;
+    webKitEvent.timeStampSeconds = currentTimeForEvent(ev);
     webKitEvent.button = mouseButtonForEvent(ev);
     webKitEvent.modifiers = modifiersForEvent(ev->modifiers());
 
@@ -43,40 +89,61 @@ WebMouseEvent WebEventFactory::toWebMouseEvent(QMouseEvent *ev)
     webKitEvent.globalX = ev->globalX();
     webKitEvent.globalY = ev->globalY();
 
-    webKitEvent.clickCount = 0;
+    webKitEvent.type = webEventTypeForEvent(ev);
+
     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;
+        break;
     default:
-        Q_ASSERT(false);
+        webKitEvent.clickCount = 0;
+        break;
     };
 
     return webKitEvent;
 }
 
+WebKit::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev)
+{
+    WebMouseWheelEvent webEvent;
+    webEvent.type = webEventTypeForEvent(ev);
+    webEvent.deltaX = 0;
+    webEvent.deltaY = 0;
+    webEvent.wheelTicksX = 0;
+    webEvent.wheelTicksY = 0;
+    webEvent.modifiers = modifiersForEvent(ev->modifiers());
+    webEvent.timeStampSeconds = currentTimeForEvent(ev);
+
+    if (ev->orientation() == Qt::Horizontal)
+        webEvent.wheelTicksX = ev->delta() / 120.0f;
+    else
+        webEvent.wheelTicksY = ev->delta() / 120.0f;
+
+
+    // Since we report the scroll by the pixel, convert the delta to pixel distance using standard scroll step.
+    // Use the same single scroll step as QTextEdit (in QTextEditPrivate::init [h,v]bar->setSingleStep)
+    static const float cDefaultQtScrollStep = 20.f;
+    // ### FIXME: Default from QtGui. Should use Qt platform theme API once configurable.
+    const int wheelScrollLines = 3;
+    webEvent.deltaX = webEvent.wheelTicksX * wheelScrollLines * cDefaultQtScrollStep;
+    webEvent.deltaY = webEvent.wheelTicksY * wheelScrollLines * cDefaultQtScrollStep;
+
+    webEvent.x = webEvent.windowX = ev->x();
+    webEvent.y = webEvent.windowY = ev->y();
+    webEvent.globalX = ev->globalX();
+    webEvent.globalY = ev->globalY();
+    return webEvent;
+}
+
 content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev)
 {
     content::NativeWebKeyboardEvent webKitEvent;
-    webKitEvent.timeStampSeconds = ev->timestamp() / 1000.0;
+    webKitEvent.timeStampSeconds = currentTimeForEvent(ev);
     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.type = webEventTypeForEvent(ev);
 
     webKitEvent.nativeKeyCode = ev->nativeVirtualKey();
     // FIXME: need Windows keycode mapping from WebCore...
diff --git a/lib/web_event_factory.h b/lib/web_event_factory.h
index 366da6417..8557ce936 100644
--- a/lib/web_event_factory.h
+++ b/lib/web_event_factory.h
@@ -6,11 +6,13 @@
 
 class QMouseEvent;
 class QKeyEvent;
+class QWheelEvent;
 
 class WebEventFactory {
 
 public:
     static WebKit::WebMouseEvent toWebMouseEvent(QMouseEvent*);
+    static WebKit::WebMouseWheelEvent toWebWheelEvent(QWheelEvent*);
     static content::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*);
 
 };
-- 
GitLab