Bug 944300 - Disable browser_tabview_privatebrowsing_perwindowpb.js on Linux for...
[gecko.git] / widget / qt / mozSwipeGesture.cpp
blobf5f41596a9ad0eb9992d67ba502061439ddfe80c
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* vim:expandtab:shiftwidth=4:tabstop=4:
3 */
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"
8 #include <QTouchEvent>
9 #include <QGraphicsWidget>
10 #include <nsIDOMSimpleGestureEvent.h>
11 #include <math.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
20 // due to QTBUG-9630
21 const int FINGER_DISTANCE_MISTAKE = 50;
23 QGesture*
24 MozSwipeGestureRecognizer::create(QObject* target)
26 return new MozSwipeGesture();
29 QGestureRecognizer::Result
30 MozSwipeGestureRecognizer::recognize(QGesture* aState,
31 QObject* aWatched,
32 QEvent* aEvent)
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);
40 if (!widget) {
41 return result;
44 switch (aEvent->type()) {
45 case QEvent::TouchBegin:
46 swipe->mSwipeState = MozSwipeGesture::NOT_STARTED;
47 result = QGestureRecognizer::MayBeGesture;
48 break;
50 case QEvent::TouchEnd:
51 if (swipe->state() != Qt::NoGesture &&
52 swipe->mSwipeState == MozSwipeGesture::TRIGGERED) {
53 result = QGestureRecognizer::FinishGesture;
55 else {
56 result = QGestureRecognizer::CancelGesture;
58 break;
60 case QEvent::TouchUpdate:
61 // We have already handled this swipe
62 if (swipe->mSwipeState > MozSwipeGesture::STARTED) {
63 break;
66 if (ev->touchPoints().count() > 2) {
67 swipe->mSwipeState = MozSwipeGesture::CANCELLED;
68 result = QGestureRecognizer::CancelGesture;
69 break;
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;
83 else {
84 result = QGestureRecognizer::MayBeGesture;
87 break;
89 default:
90 result = QGestureRecognizer::Ignore;
93 return result;
96 void
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;
117 bool
118 MozSwipeGesture::Update(const QTouchEvent::TouchPoint& aFirstPoint,
119 const QTouchEvent::TouchPoint& aSecondPoint,
120 const QSizeF& aSize)
122 // Check that fingers are not too far away
123 QPointF fingerDistance = aFirstPoint.pos() - aSecondPoint.pos();
124 if (fingerDistance.manhattanLength() > MAX_FINGER_DISTANCE) {
125 return false;
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) {
132 return false;
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())
146 / aSize.width();
147 yDistance = fabs(currentPosition.y() - startPosition.y())
148 / aSize.height();
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();
177 hotspot /= 2;
178 setHotSpot(hotspot);
179 return true;