2 * Copyright (C) 2013 Canonical, Ltd.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; version 3.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17#ifndef DIRECTIONAL_DRAG_AREA_H
18#define DIRECTIONAL_DRAG_AREA_H
20#include <QtQuick/QQuickItem>
21#include "AxisVelocityCalculator.h"
22#include "UbuntuGesturesGlobal.h"
26namespace UbuntuGestures {
27/* Defines an interface for a Timer. */
28class UBUNTUGESTURES_EXPORT AbstractTimer : public QObject {
31 AbstractTimer(QObject *parent) : QObject(parent), m_isRunning(false) {}
32 virtual int interval() const = 0;
33 virtual void setInterval(int msecs) = 0;
34 virtual void start() { m_isRunning = true; };
35 virtual void stop() { m_isRunning = false; }
36 bool isRunning() const { return m_isRunning; }
45 An area that detects axis-aligned single-finger drag gestures
47 If a drag deviates too much from the components' direction recognition will
48 fail. It will also fail if the drag or flick is too short. E.g. a noisy or
51 See doc/DirectionalDragArea.svg
53class UBUNTUGESTURES_EXPORT DirectionalDragArea : public QQuickItem {
56 // The direction in which the gesture should move in order to be recognized.
57 Q_PROPERTY(Direction::Type direction READ direction WRITE setDirection NOTIFY directionChanged)
59 // The distance travelled by the finger along the axis specified by
60 // DirectionalDragArea's direction.
61 Q_PROPERTY(qreal distance READ distance NOTIFY distanceChanged)
63 // The distance travelled by the finger along the axis specified by
64 // DirectionalDragArea's direction in scene coordinates
65 Q_PROPERTY(qreal sceneDistance READ sceneDistance NOTIFY sceneDistanceChanged)
67 // Position of the touch point performing the drag relative to this item.
68 Q_PROPERTY(qreal touchX READ touchX NOTIFY touchXChanged)
69 Q_PROPERTY(qreal touchY READ touchY NOTIFY touchYChanged)
71 // Position of the touch point performing the drag, in scene's coordinate system
72 Q_PROPERTY(qreal touchSceneX READ touchSceneX NOTIFY touchSceneXChanged)
73 Q_PROPERTY(qreal touchSceneY READ touchSceneY NOTIFY touchSceneYChanged)
75 // The current status of the directional drag gesture area.
76 Q_PROPERTY(Status status READ status NOTIFY statusChanged)
78 // Whether a drag gesture is taking place
79 // This will be true as long as status is Undecided or Recognized
80 // When a gesture gets rejected, dragging turns to false.
81 Q_PROPERTY(bool dragging READ dragging NOTIFY draggingChanged)
84 // stuff that will be set in stone at some point
86 // How far the touch point can move away from its expected position before
87 // it causes a rejection in the gesture recognition. This is to compensate
88 // for both noise in the touch input signal and for the natural irregularities
89 // in the finger movement.
90 // Proper value is likely device-specific.
91 Q_PROPERTY(qreal maxDeviation READ maxDeviation WRITE setMaxDeviation NOTIFY maxDeviationChanged)
93 // Widening angle, in degrees
94 // It's roughly the maximum angle a touch point can make relative to the
95 // axis defined by the compoment's direction for it to be recognized as a
97 Q_PROPERTY(qreal wideningAngle READ wideningAngle WRITE setWideningAngle
98 NOTIFY wideningAngleChanged)
100 // How far a touch point has to move from its initial position in order for
101 // it to be recognized as a directional drag.
102 Q_PROPERTY(qreal distanceThreshold READ distanceThreshold WRITE setDistanceThreshold
103 NOTIFY distanceThresholdChanged)
105 // Minimum speed a gesture needs to have in order to be recognized as a
107 // In pixels per second
108 Q_PROPERTY(qreal minSpeed READ minSpeed WRITE setMinSpeed NOTIFY minSpeedChanged)
110 // A gesture will be rejected if more than maxSilenceTime milliseconds has
111 // passed since we last got an input event from it (during Undecided state).
113 // Silence (i.e., lack of new input events) doesn't necessarily mean that the user's
114 // finger is still (zero drag speed). In some cases the finger might be moving but
115 // the driver's high noise filtering might cause those silence periods, specially
116 // in the moments succeeding a press (talking about Galaxy Nexus here).
117 Q_PROPERTY(int maxSilenceTime READ maxSilenceTime
118 WRITE setMaxSilenceTime
119 NOTIFY maxSilenceTimeChanged)
124 // Maximum time (in milliseconds) after the start of a given touch point where
125 // subsequent touch starts are grouped with the first one into an N-touches gesture
126 // (e.g. a two-fingers tap or drag).
127 Q_PROPERTY(int compositionTime READ compositionTime
128 WRITE setCompositionTime
129 NOTIFY compositionTimeChanged)
134 DirectionalDragArea(QQuickItem *parent = 0);
136 Direction::Type direction() const;
137 void setDirection(Direction::Type);
139 // Describes the state of the directional drag gesture.
141 // Waiting for a new touch point to land on this area. No gesture is being processed
145 // A touch point has landed on this area but it's not know yet whether it is
146 // performing a drag in the correct direction.
147 // If it's decided that the touch point is not performing a directional drag gesture,
148 // it will be rejected/ignored and status will return to WaitingForTouch.
149 Undecided, //Recognizing,
151 // There's a touch point in this area and it performed a drag in the correct
154 // Once recognized, the gesture state will move back to WaitingForTouch only once
155 // that touch point ends. The gesture will remain in the Recognized state even if
156 // the touch point starts moving in other directions or halts.
159 Status status() const { return m_status; }
161 qreal distance() const;
162 qreal sceneDistance() const;
163 void updateSceneDistance();
165 qreal touchX() const;
166 qreal touchY() const;
168 qreal touchSceneX() const;
169 qreal touchSceneY() const;
171 bool dragging() const { return (m_status == Undecided) || (m_status == Recognized); }
173 qreal maxDeviation() const { return m_dampedScenePos.maxDelta(); }
174 void setMaxDeviation(qreal value);
176 qreal wideningAngle() const;
177 void setWideningAngle(qreal value);
179 qreal distanceThreshold() const { return m_distanceThreshold; }
180 void setDistanceThreshold(qreal value);
182 qreal minSpeed() const { return m_minSpeed; }
183 void setMinSpeed(qreal value);
185 int maxSilenceTime() const { return m_maxSilenceTime; }
186 void setMaxSilenceTime(int value);
188 int compositionTime() const { return m_compositionTime; }
189 void setCompositionTime(int value);
191 // Replaces the existing Timer with the given one.
193 // Useful for providing a fake timer when testing.
194 void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
196 // Useful for testing, where a fake time source can be supplied
197 void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
200 void directionChanged(Direction::Type direction);
201 void statusChanged(Status value);
202 void draggingChanged(bool value);
203 void distanceChanged(qreal value);
204 void sceneDistanceChanged(qreal value);
205 void maxDeviationChanged(qreal value);
206 void wideningAngleChanged(qreal value);
207 void distanceThresholdChanged(qreal value);
208 void minSpeedChanged(qreal value);
209 void maxSilenceTimeChanged(int value);
210 void compositionTimeChanged(int value);
211 void touchXChanged(qreal value);
212 void touchYChanged(qreal value);
213 void touchSceneXChanged(qreal value);
214 void touchSceneYChanged(qreal value);
217 virtual void touchEvent(QTouchEvent *event);
221 void onEnabledChanged();
224 void touchEvent_absent(QTouchEvent *event);
225 void touchEvent_undecided(QTouchEvent *event);
226 void touchEvent_recognized(QTouchEvent *event);
227 bool pointInsideAllowedArea() const;
228 bool movingInRightDirection() const;
229 bool movedFarEnough(const QPointF &point) const;
230 const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
231 void setStatus(Status newStatus);
232 void setPreviousPos(const QPointF &point);
233 void setPreviousScenePos(const QPointF &point);
234 void updateVelocityCalculator(const QPointF &point);
235 bool isWithinTouchCompositionWindow();
236 void updateSceneDirectionVector();
237 // returns the scalar projection between the given vector (in scene coordinates)
238 // and m_sceneDirectionVector
239 qreal projectOntoDirectionVector(const QPointF &sceneVector) const;
244 QPointF m_startScenePos;
245 QPointF m_previousPos;
246 QPointF m_previousScenePos;
247 qreal m_sceneDistance;
250 // A movement damper is used in some of the gesture recognition calculations
251 // to get rid of noise or small oscillations in the touch position.
252 DampedPointF m_dampedScenePos;
253 QPointF m_previousDampedScenePos;
255 // Unit vector in scene coordinates describing the direction of the gesture recognition
256 QPointF m_sceneDirectionVector;
258 Direction::Type m_direction;
259 qreal m_wideningAngle; // in degrees
260 qreal m_wideningFactor; // it's pow(cosine(m_wideningAngle), 2)
261 qreal m_distanceThreshold;
262 qreal m_distanceThresholdSquared; // it's pow(m_distanceThreshold, 2)
264 int m_maxSilenceTime; // in milliseconds
265 int m_silenceTime; // in milliseconds
266 int m_compositionTime; // in milliseconds
267 int m_numSamplesOnLastSpeedCheck;
268 UbuntuGestures::AbstractTimer *m_recognitionTimer;
269 AxisVelocityCalculator *m_velocityCalculator;
271 UbuntuGestures::SharedTimeSource m_timeSource;
273 // Information about an active touch point
274 struct ActiveTouchInfo {
275 ActiveTouchInfo() : id(-1), startTime(-1) {}
276 bool isValid() const { return id != -1; }
277 void reset() { id = -1; }
281 class ActiveTouchesInfo {
283 ActiveTouchesInfo(const UbuntuGestures::SharedTimeSource &timeSource);
284 void update(QTouchEvent *event);
285 ActiveTouchInfo &touchInfo(int id);
286 qint64 mostRecentStartTime();
287 UbuntuGestures::SharedTimeSource m_timeSource;
288 bool isEmpty() const { return m_lastUsedIndex == -1; }
290 void addTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
291 ActiveTouchInfo &getEmptySlot();
292 void freeSlot(int index);
293 void removeTouchPoint(const QTouchEvent::TouchPoint &touchPoint);
294 QVector<struct ActiveTouchInfo> m_vector;
299#endif // DIRECTIONAL_DRAG_AREA_H
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list