Web Inspector: detailed heap snapshot: Replace (Native objects) root element
[WebKit-https.git] / Source / WebKit2 / UIProcess / qt / QtTapGestureRecognizer.cpp
1 /*
2  * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies)
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #include "config.h"
26 #include "QtTapGestureRecognizer.h"
27
28 #include "QtWebPageEventHandler.h"
29 #include <QLineF>
30 #include <QTouchEvent>
31
32 namespace WebKit {
33
34 QtTapGestureRecognizer::QtTapGestureRecognizer(QtWebPageEventHandler* eventHandler)
35     : QtGestureRecognizer(eventHandler)
36     , m_tapState(NoTap)
37 {
38     reset();
39 }
40
41 bool QtTapGestureRecognizer::recognize(const QTouchEvent* event, qint64 eventTimestampMillis)
42 {
43     if (event->touchPoints().size() != 1) {
44         reset();
45         return false;
46     }
47
48     switch (event->type()) {
49     case QEvent::TouchBegin:
50         ASSERT(m_tapState == NoTap);
51         ASSERT(!m_tapAndHoldTimer.isActive());
52
53         m_tapAndHoldTimer.start(tapAndHoldTime, this);
54
55         if (m_doubleTapTimer.isActive()) {
56             // Might be double tap.
57             ASSERT(m_touchBeginEventForTap);
58             m_doubleTapTimer.stop();
59             QPointF lastPosition = m_touchBeginEventForTap->touchPoints().first().screenPos();
60             QPointF newPosition = event->touchPoints().first().screenPos();
61             if (QLineF(lastPosition, newPosition).length() < maxDoubleTapDistance)
62                 m_tapState = DoubleTapCandidate;
63             else {
64                 // Received a new tap, that is unrelated to the previous one.
65                 tapTimeout();
66                 m_tapState = SingleTapStarted;
67             }
68         } else
69             m_tapState = SingleTapStarted;
70         m_touchBeginEventForTap = adoptPtr(new QTouchEvent(*event));
71
72         if (m_tapState == SingleTapStarted) {
73             const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
74             m_eventHandler->handlePotentialSingleTapEvent(touchPoint);
75         }
76         break;
77     case QEvent::TouchUpdate:
78         // If the touch point moves further than the threshold, we cancel the tap gesture.
79         if (m_tapState == SingleTapStarted) {
80             const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
81             QPointF offset(touchPoint.scenePos() - m_touchBeginEventForTap->touchPoints().first().scenePos());
82             const qreal distX = qAbs(offset.x());
83             const qreal distY = qAbs(offset.y());
84             if (distX > initialTriggerDistanceThreshold || distY > initialTriggerDistanceThreshold)
85                 reset();
86         }
87         break;
88     case QEvent::TouchEnd:
89         m_tapAndHoldTimer.stop();
90
91         switch (m_tapState) {
92         case DoubleTapCandidate:
93             {
94                 ASSERT(!m_doubleTapTimer.isActive());
95                 m_tapState = NoTap;
96
97                 const QTouchEvent::TouchPoint& touchPoint = event->touchPoints().first();
98                 QPointF startPosition = touchPoint.startScreenPos();
99                 QPointF endPosition = touchPoint.screenPos();
100                 if (QLineF(endPosition, startPosition).length() < maxDoubleTapDistance && m_eventHandler)
101                     m_eventHandler->handleDoubleTapEvent(touchPoint);
102                 break;
103             }
104         case SingleTapStarted:
105             ASSERT(!m_doubleTapTimer.isActive());
106             m_doubleTapTimer.start(doubleClickInterval, this);
107             m_tapState = NoTap;
108             break;
109         case TapAndHold:
110             m_tapState = NoTap;
111             break;
112         default:
113             break;
114         }
115         break;
116     default:
117         break;
118     }
119
120     if (m_tapState == NoTap)
121         m_eventHandler->handlePotentialSingleTapEvent(QTouchEvent::TouchPoint());
122
123     return false;
124 }
125
126 void QtTapGestureRecognizer::tapTimeout()
127 {
128     m_doubleTapTimer.stop();
129     m_eventHandler->handleSingleTapEvent(m_touchBeginEventForTap->touchPoints().at(0));
130     m_touchBeginEventForTap.clear();
131 }
132
133 void QtTapGestureRecognizer::tapAndHoldTimeout()
134 {
135     ASSERT(m_touchBeginEventForTap);
136     m_tapAndHoldTimer.stop();
137 #if 0 // No support for synthetic context menus in WK2 yet.
138     QTouchEvent::TouchPoint tapPoint = m_touchBeginEventForTap->touchPoints().at(0);
139     WebGestureEvent gesture(WebEvent::GestureTapAndHold, tapPoint.pos().toPoint(), tapPoint.screenPos().toPoint(), WebEvent::Modifiers(0), 0);
140     if (m_webPageProxy)
141         m_webPageProxy->handleGestureEvent(gesture);
142 #endif
143     m_touchBeginEventForTap.clear();
144     m_tapState = TapAndHold;
145
146     ASSERT(!m_doubleTapTimer.isActive());
147     m_doubleTapTimer.stop();
148 }
149
150 void QtTapGestureRecognizer::reset()
151 {
152     m_tapState = NoTap;
153     m_touchBeginEventForTap.clear();
154     m_tapAndHoldTimer.stop();
155
156     QtGestureRecognizer::reset();
157 }
158
159 void QtTapGestureRecognizer::timerEvent(QTimerEvent* ev)
160 {
161     int timerId = ev->timerId();
162     if (timerId == m_doubleTapTimer.timerId())
163         tapTimeout();
164     else if (timerId == m_tapAndHoldTimer.timerId())
165         tapAndHoldTimeout();
166     else
167         QObject::timerEvent(ev);
168 }
169
170 } // namespace WebKit