Unity 8
DirectionalDragArea_p.h
1 /*
2  * Copyright (C) 2015 Canonical, Ltd.
3  *
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.
7  *
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.
12  *
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/>.
15  */
16 
17 #ifndef DIRECTIONAL_DRAG_AREA_PRIV_H
18 #define DIRECTIONAL_DRAG_AREA_PRIV_H
19 
20 // Information about an active touch point
21 struct UBUNTUGESTURESQML_EXPORT ActiveTouchInfo {
22  ActiveTouchInfo() : id(-1), startTime(-1) {}
23  bool isValid() const { return id != -1; }
24  void reset() { id = -1; }
25  int id;
26  qint64 startTime;
27 };
28 class UBUNTUGESTURESQML_EXPORT ActiveTouchesInfo {
29 public:
30  ActiveTouchesInfo(const UbuntuGestures::SharedTimeSource &timeSource);
31  void update(QTouchEvent *event);
32  qint64 touchStartTime(int id);
33  bool isEmpty() const { return m_touchInfoPool.isEmpty(); }
34  qint64 mostRecentStartTime();
35  UbuntuGestures::SharedTimeSource m_timeSource;
36 private:
37  void addTouchPoint(int touchId);
38  void removeTouchPoint(int touchId);
39  #if ACTIVETOUCHESINFO_DEBUG
40  QString toString();
41  #endif
42 
43  Pool<ActiveTouchInfo> m_touchInfoPool;
44 };
45 
46 class UBUNTUGESTURESQML_EXPORT DirectionalDragAreaPrivate : public QObject {
47  Q_OBJECT
48 
49  Q_ENUMS(Status)
50 public:
51  DirectionalDragAreaPrivate(DirectionalDragArea *q);
52 
53 public Q_SLOTS:
54  void giveUpIfDisabledOrInvisible();
55  void rejectGesture();
56 
57 public:
58  // Describes the state of the directional drag gesture.
59  enum Status {
60  // Waiting for a new touch point to land on this area. No gesture is being processed
61  // or tracked.
62  WaitingForTouch,
63 
64  // A touch point has landed on this area but it's not know yet whether it is
65  // performing a drag in the correct direction.
66  // If it's decided that the touch point is not performing a directional drag gesture,
67  // it will be rejected/ignored and status will return to WaitingForTouch.
68  Undecided, //Recognizing,
69 
70  // There's a touch point in this area and it performed a drag in the correct
71  // direction.
72  //
73  // Once recognized, the gesture state will move back to WaitingForTouch only once
74  // that touch point ends. The gesture will remain in the Recognized state even if
75  // the touch point starts moving in other directions or halts.
76  Recognized,
77  };
78 
79  void touchEvent_absent(QTouchEvent *event);
80  void touchEvent_undecided(QTouchEvent *event);
81  void touchEvent_recognized(QTouchEvent *event);
82  bool movingInRightDirection() const;
83  bool movedFarEnoughAlongGestureAxis() const;
84  bool isPastMaxDistance() const;
85  const QTouchEvent::TouchPoint *fetchTargetTouchPoint(QTouchEvent *event);
86  void setStatus(Status newStatus);
87  void setPublicPos(const QPointF &point);
88  void setPublicScenePos(const QPointF &point);
89  bool isWithinTouchCompositionWindow();
90  void updateSceneDirectionVector();
91  // returns the scalar projection between the given vector (in scene coordinates)
92  // and m_sceneDirectionVector
93  qreal projectOntoDirectionVector(const QPointF &sceneVector) const;
94  void touchOwnershipEvent(TouchOwnershipEvent *event);
95  void unownedTouchEvent(UnownedTouchEvent *event);
96  void unownedTouchEvent_undecided(UnownedTouchEvent *unownedTouchEvent);
97  void watchPressedTouchPoints(const QList<QTouchEvent::TouchPoint> &touchPoints);
98  bool recognitionIsDisabled() const;
99  bool sanityCheckRecognitionProperties();
100  void updateSceneDistance();
101  void setMaxTime(int value);
102  void setDistanceThreshold(qreal value);
103  void setPixelsPerMm(qreal pixelsPerMm);
104  QString objectName() const { return q->objectName(); }
105 
106  // Replaces the existing Timer with the given one.
107  //
108  // Useful for providing a fake timer when testing.
109  void setRecognitionTimer(UbuntuGestures::AbstractTimer *timer);
110 
111  // Useful for testing, where a fake time source can be supplied
112  void setTimeSource(const UbuntuGestures::SharedTimeSource &timeSource);
113 
114  DirectionalDragArea *q;
115 
116  // The current status of the directional drag gesture area.
117  Status status;
118 
119  QPointF startPos;
120  QPointF startScenePos;
121  qreal sceneDistance;
122  int touchId;
123 
124  // The touch position exposed in the public API.
125  // It only starts to move once the gesture gets recognized.
126  QPointF publicPos;
127  QPointF publicScenePos;
128 
129  // A movement damper is used in some of the gesture recognition calculations
130  // to get rid of noise or small oscillations in the touch position.
131  DampedPointF dampedScenePos;
132  QPointF previousDampedScenePos;
133 
134  // Unit vector in scene coordinates describing the direction of the gesture recognition
135  QPointF sceneDirectionVector;
136 
137  Direction::Type direction;
138 
139  // How far a touch point has to move from its initial position along the gesture axis in order
140  // for it to be recognized as a directional drag.
141  qreal distanceThreshold;
142  qreal distanceThresholdSquared; // it's pow(distanceThreshold, 2)
143 
144  // Maximum time (in milliseconds) the gesture can take to go beyond the distance threshold
145  int maxTime;
146 
147  // Maximum distance the gesture can go without crossing the axis-aligned distance threshold
148  qreal maxDistance;
149 
150  // Maximum time (in milliseconds) after the start of a given touch point where
151  // subsequent touch starts are grouped with the first one into an N-touches gesture
152  // (e.g. a two-fingers tap or drag).
153  int compositionTime;
154 
155  bool immediateRecognition;
156 
157  UbuntuGestures::AbstractTimer *recognitionTimer;
158 
159  UbuntuGestures::SharedTimeSource timeSource;
160 
161  ActiveTouchesInfo activeTouches;
162 
163 Q_SIGNALS:
164  void statusChanged(Status value);
165 };
166 
167 #endif // DIRECTIONAL_DRAG_AREA_PRIV_H