1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
4 /* This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "mozSwipeGesture.h"
9 #include <QGraphicsWidget>
10 #include <nsIDOMSimpleGestureEvent.h>
13 // Percent of screen size
14 static const float TRIGGER_DISTANCE
= 0.3;
16 // It would be nice to get platform defines for these values
17 // Maximum finger distance in pixels
18 const int MAX_FINGER_DISTANCE
= 250;
19 // We could define it as 2*QT_GUI_DOUBLE_CLICK_RADIUS, but it's not available
21 const int FINGER_DISTANCE_MISTAKE
= 50;
24 MozSwipeGestureRecognizer::create(QObject
* target
)
26 return new MozSwipeGesture();
29 QGestureRecognizer::Result
30 MozSwipeGestureRecognizer::recognize(QGesture
* aState
,
34 const QTouchEvent
* ev
= static_cast<const QTouchEvent
*>(aEvent
);
35 MozSwipeGesture
* swipe
= static_cast<MozSwipeGesture
*>(aState
);
37 QGestureRecognizer::Result result
= QGestureRecognizer::Ignore
;
39 QGraphicsWidget
* widget
= qobject_cast
<QGraphicsWidget
*>(aWatched
);
44 switch (aEvent
->type()) {
45 case QEvent::TouchBegin
:
46 swipe
->mSwipeState
= MozSwipeGesture::NOT_STARTED
;
47 result
= QGestureRecognizer::MayBeGesture
;
50 case QEvent::TouchEnd
:
51 if (swipe
->state() != Qt::NoGesture
&&
52 swipe
->mSwipeState
== MozSwipeGesture::TRIGGERED
) {
53 result
= QGestureRecognizer::FinishGesture
;
56 result
= QGestureRecognizer::CancelGesture
;
60 case QEvent::TouchUpdate
:
61 // We have already handled this swipe
62 if (swipe
->mSwipeState
> MozSwipeGesture::STARTED
) {
66 if (ev
->touchPoints().count() > 2) {
67 swipe
->mSwipeState
= MozSwipeGesture::CANCELLED
;
68 result
= QGestureRecognizer::CancelGesture
;
73 if (ev
->touchPoints().count() == 2) {
74 swipe
->mSwipeState
= MozSwipeGesture::STARTED
;
75 QList
<QTouchEvent::TouchPoint
> touchPoints
= ev
->touchPoints();
76 if (!swipe
->Update(touchPoints
[0], touchPoints
[1], widget
->size())) {
77 result
= QGestureRecognizer::CancelGesture
;
78 swipe
->mSwipeState
= MozSwipeGesture::CANCELLED
;
80 if (swipe
->mSwipeState
== MozSwipeGesture::TRIGGERED
) {
81 result
= QGestureRecognizer::TriggerGesture
;
84 result
= QGestureRecognizer::MayBeGesture
;
90 result
= QGestureRecognizer::Ignore
;
97 MozSwipeGestureRecognizer::reset(QGesture
* aState
)
99 MozSwipeGesture
* swipe
= static_cast<MozSwipeGesture
*>(aState
);
100 swipe
->mHorizontalDirection
= 0;
101 swipe
->mVerticalDirection
= 0;
102 QGestureRecognizer::reset(aState
);
105 MozSwipeGesture::MozSwipeGesture()
106 : mHorizontalDirection(0)
107 , mVerticalDirection(0)
108 , mSwipeState(MozSwipeGesture::NOT_STARTED
)
112 int MozSwipeGesture::Direction()
114 return mHorizontalDirection
| mVerticalDirection
;
118 MozSwipeGesture::Update(const QTouchEvent::TouchPoint
& aFirstPoint
,
119 const QTouchEvent::TouchPoint
& aSecondPoint
,
122 // Check that fingers are not too far away
123 QPointF fingerDistance
= aFirstPoint
.pos() - aSecondPoint
.pos();
124 if (fingerDistance
.manhattanLength() > MAX_FINGER_DISTANCE
) {
128 // Check that fingers doesn't move too much from the original distance
129 QPointF startFingerDistance
= aFirstPoint
.startPos() - aSecondPoint
.startPos();
130 if ((startFingerDistance
- fingerDistance
).manhattanLength()
131 > FINGER_DISTANCE_MISTAKE
) {
135 QPointF startPosition
= aFirstPoint
.startNormalizedPos();
136 QPointF currentPosition
= aFirstPoint
.normalizedPos();
138 float xDistance
= fabs(currentPosition
.x() - startPosition
.x());
139 float yDistance
= fabs(currentPosition
.y() - startPosition
.y());
141 startPosition
= aFirstPoint
.startPos();
142 currentPosition
= aFirstPoint
.pos();
144 if (!aSize
.isEmpty()) {
145 xDistance
= fabs(currentPosition
.x() - startPosition
.x())
147 yDistance
= fabs(currentPosition
.y() - startPosition
.y())
151 mVerticalDirection
= nsIDOMSimpleGestureEvent::DIRECTION_UP
;
152 if (currentPosition
.y() > startPosition
.y()) {
153 mVerticalDirection
= nsIDOMSimpleGestureEvent::DIRECTION_DOWN
;
156 mHorizontalDirection
= nsIDOMSimpleGestureEvent::DIRECTION_LEFT
;
157 if (currentPosition
.x() > startPosition
.x()) {
158 mHorizontalDirection
= nsIDOMSimpleGestureEvent::DIRECTION_RIGHT
;
161 if (xDistance
> TRIGGER_DISTANCE
) {
162 if (yDistance
< TRIGGER_DISTANCE
/2) {
163 mVerticalDirection
= 0;
165 mSwipeState
= TRIGGERED
;
168 if (yDistance
> TRIGGER_DISTANCE
) {
169 if (xDistance
< TRIGGER_DISTANCE
/2) {
170 mHorizontalDirection
= 0;
172 mSwipeState
= TRIGGERED
;
175 // Use center of touchpoints as hotspot
176 QPointF hotspot
= aFirstPoint
.pos() + aSecondPoint
.pos();