|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef InputData_h__ |
|
7 #define InputData_h__ |
|
8 |
|
9 #include "nsDebug.h" |
|
10 #include "nsPoint.h" |
|
11 #include "nsTArray.h" |
|
12 #include "Units.h" |
|
13 #include "mozilla/EventForwards.h" |
|
14 |
|
15 namespace mozilla { |
|
16 |
|
17 |
|
18 enum InputType |
|
19 { |
|
20 MULTITOUCH_INPUT, |
|
21 PINCHGESTURE_INPUT, |
|
22 TAPGESTURE_INPUT |
|
23 }; |
|
24 |
|
25 class MultiTouchInput; |
|
26 class PinchGestureInput; |
|
27 class TapGestureInput; |
|
28 |
|
29 // This looks unnecessary now, but as we add more and more classes that derive |
|
30 // from InputType (eventually probably almost as many as *Events.h has), it |
|
31 // will be more and more clear what's going on with a macro that shortens the |
|
32 // definition of the RTTI functions. |
|
33 #define INPUTDATA_AS_CHILD_TYPE(type, enumID) \ |
|
34 const type& As##type() const \ |
|
35 { \ |
|
36 NS_ABORT_IF_FALSE(mInputType == enumID, "Invalid cast of InputData."); \ |
|
37 return (const type&) *this; \ |
|
38 } |
|
39 |
|
40 /** Base input data class. Should never be instantiated. */ |
|
41 class InputData |
|
42 { |
|
43 public: |
|
44 InputType mInputType; |
|
45 // Time in milliseconds that this data is relevant to. This only really |
|
46 // matters when this data is used as an event. We use uint32_t instead of |
|
47 // TimeStamp because it is easier to convert from WidgetInputEvent. The time |
|
48 // is platform-specific but it in the case of B2G and Fennec it is since |
|
49 // startup. |
|
50 uint32_t mTime; |
|
51 |
|
52 Modifiers modifiers; |
|
53 |
|
54 INPUTDATA_AS_CHILD_TYPE(MultiTouchInput, MULTITOUCH_INPUT) |
|
55 INPUTDATA_AS_CHILD_TYPE(PinchGestureInput, PINCHGESTURE_INPUT) |
|
56 INPUTDATA_AS_CHILD_TYPE(TapGestureInput, TAPGESTURE_INPUT) |
|
57 |
|
58 InputData() |
|
59 { |
|
60 } |
|
61 |
|
62 protected: |
|
63 InputData(InputType aInputType, uint32_t aTime, Modifiers aModifiers) |
|
64 : mInputType(aInputType), |
|
65 mTime(aTime), |
|
66 modifiers(aModifiers) |
|
67 { |
|
68 |
|
69 |
|
70 } |
|
71 }; |
|
72 |
|
73 /** |
|
74 * Data container for a single touch input. Similar to dom::Touch, but used in |
|
75 * off-main-thread situations. This is more for just storing touch data, whereas |
|
76 * dom::Touch is more useful for dispatching through the DOM (which can only |
|
77 * happen on the main thread). dom::Touch also bears the problem of storing |
|
78 * pointers to nsIWidget instances which can only be used on the main thread, |
|
79 * so if instead we used dom::Touch and ever set these pointers |
|
80 * off-main-thread, Bad Things Can Happen(tm). |
|
81 * |
|
82 * Note that this doesn't inherit from InputData because this itself is not an |
|
83 * event. It is only a container/struct that should have any number of instances |
|
84 * within a MultiTouchInput. |
|
85 * |
|
86 * fixme/bug 775746: Make dom::Touch inherit from this class. |
|
87 */ |
|
88 class SingleTouchData |
|
89 { |
|
90 public: |
|
91 SingleTouchData(int32_t aIdentifier, |
|
92 ScreenIntPoint aScreenPoint, |
|
93 ScreenSize aRadius, |
|
94 float aRotationAngle, |
|
95 float aForce) |
|
96 : mIdentifier(aIdentifier), |
|
97 mScreenPoint(aScreenPoint), |
|
98 mRadius(aRadius), |
|
99 mRotationAngle(aRotationAngle), |
|
100 mForce(aForce) |
|
101 { |
|
102 |
|
103 |
|
104 } |
|
105 |
|
106 SingleTouchData() |
|
107 { |
|
108 } |
|
109 |
|
110 // A unique number assigned to each SingleTouchData within a MultiTouchInput so |
|
111 // that they can be easily distinguished when handling a touch start/move/end. |
|
112 int32_t mIdentifier; |
|
113 |
|
114 // Point on the screen that the touch hit, in device pixels. They are |
|
115 // coordinates on the screen. |
|
116 ScreenIntPoint mScreenPoint; |
|
117 |
|
118 // Radius that the touch covers, i.e. if you're using your thumb it will |
|
119 // probably be larger than using your pinky, even with the same force. |
|
120 // Radius can be different along x and y. For example, if you press down with |
|
121 // your entire finger vertically, the y radius will be much larger than the x |
|
122 // radius. |
|
123 ScreenSize mRadius; |
|
124 |
|
125 float mRotationAngle; |
|
126 |
|
127 // How hard the screen is being pressed. |
|
128 float mForce; |
|
129 }; |
|
130 |
|
131 /** |
|
132 * Similar to WidgetTouchEvent, but for use off-main-thread. Also only stores a |
|
133 * screen touch point instead of the many different coordinate spaces |
|
134 * WidgetTouchEvent stores its touch point in. This includes a way to initialize |
|
135 * itself from a WidgetTouchEvent by copying all relevant data over. Note that |
|
136 * this copying from WidgetTouchEvent functionality can only be used on the main |
|
137 * thread. |
|
138 * |
|
139 * Stores an array of SingleTouchData. |
|
140 */ |
|
141 class MultiTouchInput : public InputData |
|
142 { |
|
143 public: |
|
144 enum MultiTouchType |
|
145 { |
|
146 MULTITOUCH_START, |
|
147 MULTITOUCH_MOVE, |
|
148 MULTITOUCH_END, |
|
149 MULTITOUCH_ENTER, |
|
150 MULTITOUCH_LEAVE, |
|
151 MULTITOUCH_CANCEL |
|
152 }; |
|
153 |
|
154 MultiTouchInput(MultiTouchType aType, uint32_t aTime, Modifiers aModifiers) |
|
155 : InputData(MULTITOUCH_INPUT, aTime, aModifiers), |
|
156 mType(aType) |
|
157 { |
|
158 |
|
159 |
|
160 } |
|
161 |
|
162 MultiTouchInput() |
|
163 { |
|
164 } |
|
165 |
|
166 MultiTouchInput(const WidgetTouchEvent& aTouchEvent); |
|
167 |
|
168 // This conversion from WidgetMouseEvent to MultiTouchInput is needed because |
|
169 // on the B2G emulator we can only receive mouse events, but we need to be |
|
170 // able to pan correctly. To do this, we convert the events into a format that |
|
171 // the panning code can handle. This code is very limited and only supports |
|
172 // SingleTouchData. It also sends garbage for the identifier, radius, force |
|
173 // and rotation angle. |
|
174 MultiTouchInput(const WidgetMouseEvent& aMouseEvent); |
|
175 |
|
176 MultiTouchType mType; |
|
177 nsTArray<SingleTouchData> mTouches; |
|
178 }; |
|
179 |
|
180 /** |
|
181 * Encapsulation class for pinch events. In general, these will be generated by |
|
182 * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and |
|
183 * determining whether or not the user was trying to do a gesture. |
|
184 */ |
|
185 class PinchGestureInput : public InputData |
|
186 { |
|
187 public: |
|
188 enum PinchGestureType |
|
189 { |
|
190 PINCHGESTURE_START, |
|
191 PINCHGESTURE_SCALE, |
|
192 PINCHGESTURE_END |
|
193 }; |
|
194 |
|
195 PinchGestureInput(PinchGestureType aType, |
|
196 uint32_t aTime, |
|
197 const ScreenPoint& aFocusPoint, |
|
198 float aCurrentSpan, |
|
199 float aPreviousSpan, |
|
200 Modifiers aModifiers) |
|
201 : InputData(PINCHGESTURE_INPUT, aTime, aModifiers), |
|
202 mType(aType), |
|
203 mFocusPoint(aFocusPoint), |
|
204 mCurrentSpan(aCurrentSpan), |
|
205 mPreviousSpan(aPreviousSpan) |
|
206 { |
|
207 |
|
208 |
|
209 } |
|
210 |
|
211 PinchGestureType mType; |
|
212 |
|
213 // Center point of the pinch gesture. That is, if there are two fingers on the |
|
214 // screen, it is their midpoint. In the case of more than two fingers, the |
|
215 // point is implementation-specific, but can for example be the midpoint |
|
216 // between the very first and very last touch. This is in device pixels and |
|
217 // are the coordinates on the screen of this midpoint. |
|
218 ScreenPoint mFocusPoint; |
|
219 |
|
220 // The distance in device pixels (though as a float for increased precision |
|
221 // and because it is the distance along both the x and y axis) between the |
|
222 // touches responsible for the pinch gesture. |
|
223 float mCurrentSpan; |
|
224 |
|
225 // The previous |mCurrentSpan| in the PinchGestureInput preceding this one. |
|
226 // This is only really relevant during a PINCHGESTURE_SCALE because when it is |
|
227 // of this type then there must have been a history of spans. |
|
228 float mPreviousSpan; |
|
229 }; |
|
230 |
|
231 /** |
|
232 * Encapsulation class for tap events. In general, these will be generated by |
|
233 * a gesture listener by looking at SingleTouchData/MultiTouchInput instances and |
|
234 * determining whether or not the user was trying to do a gesture. |
|
235 */ |
|
236 class TapGestureInput : public InputData |
|
237 { |
|
238 public: |
|
239 enum TapGestureType |
|
240 { |
|
241 TAPGESTURE_LONG, |
|
242 TAPGESTURE_LONG_UP, |
|
243 TAPGESTURE_UP, |
|
244 TAPGESTURE_CONFIRMED, |
|
245 TAPGESTURE_DOUBLE, |
|
246 TAPGESTURE_CANCEL |
|
247 }; |
|
248 |
|
249 TapGestureInput(TapGestureType aType, |
|
250 uint32_t aTime, |
|
251 const ScreenIntPoint& aPoint, |
|
252 Modifiers aModifiers) |
|
253 : InputData(TAPGESTURE_INPUT, aTime, aModifiers), |
|
254 mType(aType), |
|
255 mPoint(aPoint) |
|
256 { |
|
257 |
|
258 |
|
259 } |
|
260 |
|
261 TapGestureType mType; |
|
262 ScreenIntPoint mPoint; |
|
263 }; |
|
264 |
|
265 } |
|
266 |
|
267 #endif // InputData_h__ |