Title: [113165] trunk/Source/WebKit2
Revision
113165
Author
kenn...@webkit.org
Date
2012-04-04 04:00:21 -0700 (Wed, 04 Apr 2012)

Log Message

[Qt] Improve the tap gesture recognizer
https://bugs.webkit.org/show_bug.cgi?id=83135

Reviewed by Simon Hausmann.

Clean up the code and make sure that the first single tap
event, as part of a double tap gesture, is ignored.

* UIProcess/qt/QtTapGestureRecognizer.cpp:
(WebKit::QtTapGestureRecognizer::withinDistance):
(WebKit):
(WebKit::QtTapGestureRecognizer::recognize):
(WebKit::QtTapGestureRecognizer::singleTapTimeout):
(WebKit::QtTapGestureRecognizer::tapAndHoldTimeout):
(WebKit::QtTapGestureRecognizer::reset):
* UIProcess/qt/QtTapGestureRecognizer.h:
(QtTapGestureRecognizer):

Modified Paths

Diff

Modified: trunk/Source/WebKit2/ChangeLog (113164 => 113165)


--- trunk/Source/WebKit2/ChangeLog	2012-04-04 10:56:25 UTC (rev 113164)
+++ trunk/Source/WebKit2/ChangeLog	2012-04-04 11:00:21 UTC (rev 113165)
@@ -1,3 +1,23 @@
+2012-04-04  Kenneth Rohde Christiansen  <kenn...@webkit.org>
+
+        [Qt] Improve the tap gesture recognizer
+        https://bugs.webkit.org/show_bug.cgi?id=83135
+
+        Reviewed by Simon Hausmann.
+
+        Clean up the code and make sure that the first single tap
+        event, as part of a double tap gesture, is ignored.
+
+        * UIProcess/qt/QtTapGestureRecognizer.cpp:
+        (WebKit::QtTapGestureRecognizer::withinDistance):
+        (WebKit):
+        (WebKit::QtTapGestureRecognizer::recognize):
+        (WebKit::QtTapGestureRecognizer::singleTapTimeout):
+        (WebKit::QtTapGestureRecognizer::tapAndHoldTimeout):
+        (WebKit::QtTapGestureRecognizer::reset):
+        * UIProcess/qt/QtTapGestureRecognizer.h:
+        (QtTapGestureRecognizer):
+
 2012-04-03  Geoffrey Garen  <gga...@apple.com>
 
         Fixed some WebKit2 crashes seen on the buildbot after my last patch.

Modified: trunk/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp (113164 => 113165)


--- trunk/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp	2012-04-04 10:56:25 UTC (rev 113164)
+++ trunk/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.cpp	2012-04-04 11:00:21 UTC (rev 113165)
@@ -37,83 +37,59 @@
 {
 }
 
+bool QtTapGestureRecognizer::withinDistance(const QTouchEvent::TouchPoint& touchPoint, int distance)
+{
+    return QLineF(touchPoint.screenPos(), m_lastTouchEvent->touchPoints().first().screenPos()).length() < distance;
+}
+
 bool QtTapGestureRecognizer::recognize(const QTouchEvent* event, qint64 eventTimestampMillis)
 {
+    ASSERT(m_eventHandler);
+
     if (event->touchPoints().size() != 1) {
         reset();
         return false;
     }
 
+    const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
+
     switch (event->type()) {
     case QEvent::TouchBegin:
         ASSERT(m_tapState == NoTap);
-        ASSERT(!m_tapAndHoldTimer.isActive());
+        m_doubleTapTimer.stop(); // Cancel other pending single tap event.
 
+        ASSERT(!m_tapAndHoldTimer.isActive());
         m_tapAndHoldTimer.start(tapAndHoldTime, this);
 
-        if (m_doubleTapTimer.isActive()) {
-            // Might be double tap.
-            ASSERT(m_touchBeginEventForTap);
-            m_doubleTapTimer.stop();
-            QPointF lastPosition = m_touchBeginEventForTap->touchPoints().first().screenPos();
-            QPointF newPosition = event->touchPoints().first().screenPos();
-            if (QLineF(lastPosition, newPosition).length() < maxDoubleTapDistance)
-                m_tapState = DoubleTapCandidate;
-            else {
-                // Received a new tap, that is unrelated to the previous one.
-                tapTimeout();
-                m_tapState = SingleTapStarted;
-            }
-        } else
+        if (m_lastTouchEvent && withinDistance(touchPoint, maxDoubleTapDistance))
+            m_tapState = DoubleTapCandidate;
+        else {
             m_tapState = SingleTapStarted;
-        m_touchBeginEventForTap = adoptPtr(new QTouchEvent(*event));
-
-        if (m_tapState == SingleTapStarted) {
-            const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
+            // The below in facts resets any previous single tap event.
             m_eventHandler->handlePotentialSingleTapEvent(touchPoint);
+            m_lastTouchEvent = adoptPtr(new QTouchEvent(*event));
+            m_doubleTapTimer.start(maxDoubleTapInterval, this);
         }
         break;
+
     case QEvent::TouchUpdate:
         // If the touch point moves further than the threshold, we cancel the tap gesture.
-        if (m_tapState == SingleTapStarted) {
-            const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
-            QPointF offset(touchPoint.scenePos() - m_touchBeginEventForTap->touchPoints().first().scenePos());
-            const qreal distX = qAbs(offset.x());
-            const qreal distY = qAbs(offset.y());
-            if (distX > initialTriggerDistanceThreshold || distY > initialTriggerDistanceThreshold)
-                reset();
-        }
+        if (m_tapState == SingleTapStarted && !withinDistance(touchPoint, maxPanDistance))
+            reset();
         break;
+
     case QEvent::TouchEnd:
         m_tapAndHoldTimer.stop();
+
+        if (m_tapState == DoubleTapCandidate && withinDistance(touchPoint, maxDoubleTapDistance))
+            m_eventHandler->handleDoubleTapEvent(touchPoint);
+
         if (m_tapState != NoTap)
             m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint());
 
-        switch (m_tapState) {
-        case DoubleTapCandidate:
-            {
-                ASSERT(!m_doubleTapTimer.isActive());
-                m_tapState = NoTap;
-
-                const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
-                QPointF startPosition = touchPoint.startScreenPos();
-                QPointF endPosition = touchPoint.screenPos();
-                if (QLineF(endPosition, startPosition).length() < maxDoubleTapDistance && m_eventHandler)
-                    m_eventHandler->handleDoubleTapEvent(touchPoint);
-                break;
-            }
-        case SingleTapStarted:
-            ASSERT(!m_doubleTapTimer.isActive());
-            m_doubleTapTimer.start(doubleClickInterval, this);
-            m_tapState = NoTap;
-            break;
-        case TapAndHold:
-            m_tapState = NoTap;
-            break;
-        default:
-            break;
-        }
+        m_tapState = NoTap;
         break;
+
     default:
         break;
     }
@@ -121,41 +97,38 @@
     return false;
 }
 
-void QtTapGestureRecognizer::tapTimeout()
+void QtTapGestureRecognizer::singleTapTimeout()
 {
-    m_doubleTapTimer.stop();
-    m_eventHandler->handleSingleTapEvent(m_touchBeginEventForTap->touchPoints().at(0));
-    m_touchBeginEventForTap.clear();
+    ASSERT(m_lastTouchEvent);
+
+    m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint());
+    m_eventHandler->handleSingleTapEvent(m_lastTouchEvent->touchPoints().first());
+    reset();
 }
 
 void QtTapGestureRecognizer::tapAndHoldTimeout()
 {
-    ASSERT(m_touchBeginEventForTap);
-    m_tapAndHoldTimer.stop();
+    ASSERT(m_lastTouchEvent);
+
     m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint());
+    reset();
+
 #if 0 // No support for synthetic context menus in WK2 yet.
-    QTouchEvent::TouchPoint tapPoint = m_touchBeginEventForTap->touchPoints().at(0);
-    WebGestureEvent gesture(WebEvent::GestureTapAndHold, tapPoint.pos().toPoint(), tapPoint.screenPos().toPoint(), WebEvent::Modifiers(0), 0);
-    if (m_webPageProxy)
-        m_webPageProxy->handleGestureEvent(gesture);
+    const QTouchEvent::TouchPoint& touchPoint = m_lastTouchEvent->touchPoints().first();
+    WebGestureEvent event(WebEvent::GestureTapAndHold, touchPoint.pos().toPoint(), touchPoint.screenPos().toPoint(), WebEvent::Modifiers(0), 0);
+    m_eventHandler->handleGestureEvent(event);
 #endif
-    m_touchBeginEventForTap.clear();
-    m_tapState = TapAndHold;
-
-    ASSERT(!m_doubleTapTimer.isActive());
-    m_doubleTapTimer.stop();
 }
 
 void QtTapGestureRecognizer::reset()
 {
-    if (m_tapState == NoTap)
-        return;
+    if (m_tapState != NoTap)
+        m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint());
 
-    m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint());
-
     m_tapState = NoTap;
-    m_touchBeginEventForTap.clear();
     m_tapAndHoldTimer.stop();
+    m_doubleTapTimer.stop();
+    m_lastTouchEvent.clear();
 
     QtGestureRecognizer::reset();
 }
@@ -164,7 +137,7 @@
 {
     int timerId = ev->timerId();
     if (timerId == m_doubleTapTimer.timerId())
-        tapTimeout();
+        singleTapTimeout();
     else if (timerId == m_tapAndHoldTimer.timerId())
         tapAndHoldTimeout();
     else

Modified: trunk/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.h (113164 => 113165)


--- trunk/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.h	2012-04-04 10:56:25 UTC (rev 113164)
+++ trunk/Source/WebKit2/UIProcess/qt/QtTapGestureRecognizer.h	2012-04-04 11:00:21 UTC (rev 113165)
@@ -28,20 +28,17 @@
 
 #include "QtGestureRecognizer.h"
 
+#include <QTouchEvent>
 #include <QtCore/QBasicTimer>
 #include <QtCore/QObject>
 #include <QtCore/QtGlobal>
 #include <wtf/OwnPtr.h>
 
-QT_BEGIN_NAMESPACE
-class QTouchEvent;
-QT_END_NAMESPACE
-
 // FIXME: These constants should possibly depend on DPI.
-const qreal initialTriggerDistanceThreshold = 5;
-const qreal maxDoubleTapDistance = 120;
+const int maxPanDistance = 5;
+const int maxDoubleTapDistance = 120;
 const int tapAndHoldTime = 800;
-const int doubleClickInterval = 400;
+const int maxDoubleTapInterval = 400;
 
 class QtWebPageEventHandler;
 
@@ -55,13 +52,15 @@
 
 protected:
     void timerEvent(QTimerEvent*);
-    void tapTimeout();
+    void singleTapTimeout();
     void tapAndHoldTimeout();
 
 private:
+    bool withinDistance(const QTouchEvent::TouchPoint&, int distance);
+
     QBasicTimer m_doubleTapTimer;
     QBasicTimer m_tapAndHoldTimer;
-    OwnPtr<QTouchEvent> m_touchBeginEventForTap;
+    OwnPtr<QTouchEvent> m_lastTouchEvent;
 
     enum {
         NoTap,
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to