|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Tap touch gesture recognizer. |
|
15 * |
|
16 */ |
|
17 |
|
18 #include "akntouchgesturefwdefs.h" |
|
19 #include "akntouchgesturefwevent.h" |
|
20 #include "akntouchgesturefwsettings.h" |
|
21 #include "akntouchgesturefwtaprecognizer.h" |
|
22 |
|
23 using namespace AknTouchGestureFw; |
|
24 |
|
25 // ======== MEMBER FUNCTIONS ======== |
|
26 |
|
27 // --------------------------------------------------------------------------- |
|
28 // Two-phased constructor. |
|
29 // --------------------------------------------------------------------------- |
|
30 // |
|
31 CAknTouchGestureFwTapRecognizer* CAknTouchGestureFwTapRecognizer::NewL( |
|
32 CAknTouchGestureFwRecognitionEngine& aEngine ) |
|
33 { |
|
34 CAknTouchGestureFwTapRecognizer* self = |
|
35 CAknTouchGestureFwTapRecognizer::NewLC( aEngine ); |
|
36 CleanupStack::Pop( self ); |
|
37 return self; |
|
38 } |
|
39 |
|
40 |
|
41 // --------------------------------------------------------------------------- |
|
42 // Two-phased constructor. |
|
43 // --------------------------------------------------------------------------- |
|
44 // |
|
45 CAknTouchGestureFwTapRecognizer* CAknTouchGestureFwTapRecognizer::NewLC( |
|
46 CAknTouchGestureFwRecognitionEngine& aEngine ) |
|
47 { |
|
48 CAknTouchGestureFwTapRecognizer* self |
|
49 = new ( ELeave ) CAknTouchGestureFwTapRecognizer( aEngine ); |
|
50 CleanupStack::PushL( self ); |
|
51 return self; |
|
52 } |
|
53 |
|
54 |
|
55 // --------------------------------------------------------------------------- |
|
56 // Destructor |
|
57 // --------------------------------------------------------------------------- |
|
58 // |
|
59 CAknTouchGestureFwTapRecognizer::~CAknTouchGestureFwTapRecognizer() |
|
60 { |
|
61 if ( iLongTapTimer ) |
|
62 { |
|
63 iLongTapTimer->Cancel(); |
|
64 } |
|
65 delete iLongTapTimer; |
|
66 } |
|
67 |
|
68 |
|
69 // --------------------------------------------------------------------------- |
|
70 // Returns the tap gesture group. |
|
71 // --------------------------------------------------------------------------- |
|
72 // |
|
73 TAknTouchGestureFwGroup CAknTouchGestureFwTapRecognizer::GestureGroup() const |
|
74 { |
|
75 return EAknTouchGestureFwGroupTap; |
|
76 } |
|
77 |
|
78 |
|
79 // --------------------------------------------------------------------------- |
|
80 // Cancels the tap recognition. |
|
81 // --------------------------------------------------------------------------- |
|
82 // |
|
83 void CAknTouchGestureFwTapRecognizer::CancelRecognizing() |
|
84 { |
|
85 DoCancelTapRecognition( ETrue ); |
|
86 } |
|
87 |
|
88 |
|
89 // --------------------------------------------------------------------------- |
|
90 // Handles single-touch pointer events. |
|
91 // --------------------------------------------------------------------------- |
|
92 // |
|
93 void CAknTouchGestureFwTapRecognizer::HandleSinglePointerEventL( |
|
94 const TPointerEventData& aPointerData ) |
|
95 { |
|
96 switch ( aPointerData.iPointerEvent.iType ) |
|
97 { |
|
98 case TPointerEvent::EButton1Down: |
|
99 { |
|
100 // Start recognition on down event |
|
101 StartTapRecognition( |
|
102 aPointerData.iPointerEvent.iPosition, |
|
103 aPointerData.iTimeStamp ); |
|
104 break; |
|
105 } |
|
106 case TPointerEvent::EDrag: |
|
107 { |
|
108 // Continue tap recognizing. |
|
109 TapRecognize( aPointerData.iPointerEvent.iPosition ); |
|
110 break; |
|
111 } |
|
112 case TPointerEvent::EButton1Up: |
|
113 { |
|
114 // Pointer up - complete recognition |
|
115 CompleteTapRecognitionL( aPointerData.iTimeStamp ); |
|
116 break; |
|
117 } |
|
118 default: |
|
119 { |
|
120 break; |
|
121 } |
|
122 } |
|
123 } |
|
124 |
|
125 |
|
126 // --------------------------------------------------------------------------- |
|
127 // Handles multi-touch pointer events. |
|
128 // --------------------------------------------------------------------------- |
|
129 // |
|
130 void CAknTouchGestureFwTapRecognizer::HandleMultiPointerEventL( |
|
131 const TPointerEventData& aPointerData, |
|
132 const TPoint& /*aFirstPointerPosition*/, |
|
133 const TPoint& /*aSecondPointerPosition*/ ) |
|
134 { |
|
135 if ( aPointerData.iPointerEvent.iType == TPointerEvent::EButton1Down ) |
|
136 { |
|
137 // First pointer is already down, second pointer down cancels tap |
|
138 // recognizing because taps are allowed only for the first pointer. |
|
139 CancelRecognizing(); |
|
140 } |
|
141 } |
|
142 |
|
143 |
|
144 // --------------------------------------------------------------------------- |
|
145 // C++ constructor. |
|
146 // --------------------------------------------------------------------------- |
|
147 // |
|
148 CAknTouchGestureFwTapRecognizer::CAknTouchGestureFwTapRecognizer( |
|
149 CAknTouchGestureFwRecognitionEngine& aEngine ) |
|
150 : CAknTouchGestureFwBaseRecognizer( aEngine ), |
|
151 iThresholdArea(), |
|
152 iLongTapTimer( NULL ), |
|
153 iFirstTapDetected( EFalse ), |
|
154 iFirstTapTime(), |
|
155 iFirstTapPos(), |
|
156 iLongTapIntensity( 0 ), |
|
157 iFeedBackStarted( EFalse ) |
|
158 { |
|
159 } |
|
160 |
|
161 |
|
162 // --------------------------------------------------------------------------- |
|
163 // Starts the tap gesture recognition. |
|
164 // --------------------------------------------------------------------------- |
|
165 // |
|
166 void CAknTouchGestureFwTapRecognizer::StartTapRecognition( |
|
167 const TPoint& aStartPoint, |
|
168 const TTime& aTimeStamp ) |
|
169 { |
|
170 iThresholdArea.Start( aStartPoint ); |
|
171 |
|
172 // Start timer to recognize long tap |
|
173 if ( !iLongTapTimer ) |
|
174 { |
|
175 iLongTapTimer = CPeriodic::New( CActive::EPriorityStandard ); |
|
176 } |
|
177 |
|
178 if ( iLongTapTimer ) |
|
179 { |
|
180 iLongTapTimer->Cancel(); |
|
181 // Set timer for initial long tap delay. |
|
182 iLongTapTimer->Start( KDefaultLongTapInitialDelay, |
|
183 KDefaultLongTapInitialDelay, |
|
184 TCallBack( LongTapCallback, this ) ); |
|
185 } |
|
186 |
|
187 if ( iFirstTapDetected ) |
|
188 { |
|
189 // First tap already detected, check if this tap is double tap |
|
190 |
|
191 // Check if position of this tap is too far from |
|
192 // position of first tap. |
|
193 TInt xDistance = Abs( aStartPoint.iX - iFirstTapPos.iX ); |
|
194 TInt yDistance = Abs( aStartPoint.iY - iFirstTapPos.iY ); |
|
195 |
|
196 if ( xDistance > DragThreshold() || yDistance > DragThreshold() ) |
|
197 { |
|
198 // Too far, this tap can't be double tap. |
|
199 iFirstTapDetected = EFalse; |
|
200 return; |
|
201 } |
|
202 |
|
203 // Check if delay between already detected tap and this tap is too long. |
|
204 TInt delay( aTimeStamp.MicroSecondsFrom( iFirstTapTime ).Int64() ); |
|
205 |
|
206 if ( delay > DoubleTapMaximumDuration() ) |
|
207 { |
|
208 // Delay is too long, this tap can't be double tap. |
|
209 iFirstTapDetected = EFalse; |
|
210 } |
|
211 } |
|
212 } |
|
213 |
|
214 |
|
215 // --------------------------------------------------------------------------- |
|
216 // Continues the tap gesture recognition, called on drag pointer events. |
|
217 // --------------------------------------------------------------------------- |
|
218 // |
|
219 void CAknTouchGestureFwTapRecognizer::TapRecognize( const TPoint& aPoint ) |
|
220 { |
|
221 if ( iThresholdArea.Check( aPoint, TapThreshold() ) ) |
|
222 { |
|
223 CancelRecognizing(); |
|
224 } |
|
225 } |
|
226 |
|
227 |
|
228 // --------------------------------------------------------------------------- |
|
229 // Ends the tap gesture recognition. |
|
230 // --------------------------------------------------------------------------- |
|
231 // |
|
232 void CAknTouchGestureFwTapRecognizer::CompleteTapRecognitionL( |
|
233 const TTime& aTimeStamp ) |
|
234 { |
|
235 if ( iThresholdArea.IsActive() ) |
|
236 { |
|
237 // Single pointer has been down and goes up now |
|
238 // and tap recognition hasn't been cancelled |
|
239 const TPoint startPos( iThresholdArea.InitialPosition() ); |
|
240 |
|
241 // Cancel tap recognition of this tap, but don't |
|
242 // remove the possible info that first tap has already been detected |
|
243 DoCancelTapRecognition( EFalse ); |
|
244 |
|
245 if ( iFirstTapDetected ) |
|
246 { |
|
247 iFirstTapDetected = EFalse; |
|
248 // First tap already detected: Send Double Tap gesture event |
|
249 SendTapEventL( EAknTouchGestureFwDoubleTap, iFirstTapPos ); |
|
250 } |
|
251 else |
|
252 { |
|
253 iFirstTapTime = aTimeStamp; |
|
254 iFirstTapDetected = ETrue; |
|
255 iFirstTapPos = startPos; |
|
256 |
|
257 // First tap not detected: Send normal Tap gesture event |
|
258 SendTapEventL( EAknTouchGestureFwTap, startPos ); |
|
259 } |
|
260 } |
|
261 } |
|
262 |
|
263 |
|
264 // --------------------------------------------------------------------------- |
|
265 // Sends a tap gesture event to the observer. |
|
266 // --------------------------------------------------------------------------- |
|
267 // |
|
268 void CAknTouchGestureFwTapRecognizer::SendTapEventL( |
|
269 TAknTouchGestureFwType aGestureType, |
|
270 const TPoint& aPointerPos ) |
|
271 { |
|
272 TTouchFeedbackType feedbackType( FeedbackType( aGestureType ) ); |
|
273 if ( feedbackType ) |
|
274 { |
|
275 switch ( aGestureType ) |
|
276 { |
|
277 case EAknTouchGestureFwTap: |
|
278 { |
|
279 ImmediateFeedback( ETouchFeedbackSensitive, feedbackType ); |
|
280 break; |
|
281 } |
|
282 case EAknTouchGestureFwDoubleTap: |
|
283 { |
|
284 ImmediateFeedback( ETouchFeedbackBasic, feedbackType ); |
|
285 break; |
|
286 } |
|
287 case EAknTouchGestureFwLongTap: |
|
288 { |
|
289 ImmediateFeedback( ETouchFeedbackBasic, feedbackType ); |
|
290 break; |
|
291 } |
|
292 default: |
|
293 { |
|
294 break; |
|
295 } |
|
296 } |
|
297 } |
|
298 |
|
299 TAknTouchGestureFwTapEvent tap; |
|
300 tap.SetType( aGestureType ); |
|
301 tap.SetPosition( aPointerPos ); |
|
302 SendGestureEventL( tap ); |
|
303 } |
|
304 |
|
305 |
|
306 // --------------------------------------------------------------------------- |
|
307 // Called when long tap has been detected. |
|
308 // --------------------------------------------------------------------------- |
|
309 // |
|
310 TInt CAknTouchGestureFwTapRecognizer::LongTapCallback( TAny* aThis ) |
|
311 { |
|
312 CAknTouchGestureFwTapRecognizer* recognizer = |
|
313 static_cast<CAknTouchGestureFwTapRecognizer*>( aThis ); |
|
314 if ( recognizer ) |
|
315 { |
|
316 TRAP_IGNORE( recognizer->HandleLongTapCallbackL() ); |
|
317 } |
|
318 return 0; |
|
319 } |
|
320 |
|
321 |
|
322 // --------------------------------------------------------------------------- |
|
323 // Handles long tap callback related actions. |
|
324 // --------------------------------------------------------------------------- |
|
325 // |
|
326 void CAknTouchGestureFwTapRecognizer::HandleLongTapCallbackL() |
|
327 { |
|
328 if ( iLongTapIntensity == 0 && iLongTapTimer ) |
|
329 { |
|
330 iLongTapTimer->Cancel(); |
|
331 |
|
332 TInt interval = ( LongTapThreshold() - KDefaultLongTapInitialDelay ) |
|
333 / KDefaultMaxLongTapIntensitySteps; |
|
334 |
|
335 TInt timeOut = |
|
336 interval * ( KDefaultMaxLongTapIntensitySteps + 1 ); |
|
337 |
|
338 // Start timer again to increase long tap intensity on |
|
339 // regular interval until max intensity is reached. |
|
340 iLongTapTimer->Start( 0, interval, |
|
341 TCallBack( LongTapCallback, this ) ); |
|
342 |
|
343 TTouchFeedbackType feedbackType( |
|
344 FeedbackType( EAknTouchGestureFwTap ) ); |
|
345 |
|
346 if ( feedbackType & ETouchFeedbackVibra ) |
|
347 { |
|
348 // Start feedback for long tap gesture. |
|
349 StartContinuousFeedback( ETouchContinuousSmooth, 0, timeOut ); |
|
350 iFeedBackStarted = ETrue; |
|
351 } |
|
352 } |
|
353 |
|
354 // Calculate new long tap intensity value. |
|
355 iLongTapIntensity = iLongTapIntensity + |
|
356 KDefaultMaxLongTapIntensity / KDefaultMaxLongTapIntensitySteps; |
|
357 |
|
358 if ( iFeedBackStarted ) |
|
359 { |
|
360 // Modify existing continuous feedback. Intensity will grow |
|
361 // from 0 to 100 and after that long tap is detected. |
|
362 ModifyContinuousFeedback( iLongTapIntensity ); |
|
363 } |
|
364 |
|
365 if ( iLongTapIntensity >= KDefaultMaxLongTapIntensity ) |
|
366 { |
|
367 const TPoint startPos( iThresholdArea.InitialPosition() ); |
|
368 CancelRecognizing(); |
|
369 // Send Long Tap gesture event. |
|
370 SendTapEventL( EAknTouchGestureFwLongTap, startPos ); |
|
371 } |
|
372 } |
|
373 |
|
374 |
|
375 // --------------------------------------------------------------------------- |
|
376 // Cancels the tap gesture recognition. |
|
377 // --------------------------------------------------------------------------- |
|
378 // |
|
379 void CAknTouchGestureFwTapRecognizer::DoCancelTapRecognition( |
|
380 TBool aResetFirstTapDetection ) |
|
381 { |
|
382 iThresholdArea.Reset(); |
|
383 |
|
384 if ( aResetFirstTapDetection ) |
|
385 { |
|
386 iFirstTapDetected = EFalse; |
|
387 } |
|
388 |
|
389 if ( iLongTapTimer ) |
|
390 { |
|
391 iLongTapTimer->Cancel(); |
|
392 |
|
393 if ( iLongTapIntensity > 0 ) |
|
394 { |
|
395 StopContinuousFeedback(); |
|
396 iFeedBackStarted = EFalse; |
|
397 iLongTapIntensity = 0; |
|
398 } |
|
399 } |
|
400 } |
|
401 |
|
402 |
|
403 // --------------------------------------------------------------------------- |
|
404 // Returns the value for the long tap threshold setting. |
|
405 // --------------------------------------------------------------------------- |
|
406 // |
|
407 TInt CAknTouchGestureFwTapRecognizer::LongTapThreshold() const |
|
408 { |
|
409 return Settings().LongTapThreshold() * KMicroSecondsInMilliSecond; |
|
410 } |
|
411 |
|
412 |
|
413 // --------------------------------------------------------------------------- |
|
414 // Returns the value for the single tap threshold setting. |
|
415 // --------------------------------------------------------------------------- |
|
416 // |
|
417 TInt CAknTouchGestureFwTapRecognizer::TapThreshold() const |
|
418 { |
|
419 return Settings().TapThreshold(); |
|
420 } |
|
421 |
|
422 |
|
423 // --------------------------------------------------------------------------- |
|
424 // Returns the value for the double tap maximum duration setting. |
|
425 // --------------------------------------------------------------------------- |
|
426 // |
|
427 TInt CAknTouchGestureFwTapRecognizer::DoubleTapMaximumDuration() const |
|
428 { |
|
429 return Settings().DoubleTapMaximumDuration() * KMicroSecondsInMilliSecond; |
|
430 } |
|
431 |
|
432 // End of File |