|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (developer.feedback@nokia.com) |
|
6 ** |
|
7 ** This file is part of the HbFeedback module of the UI Extensions for Mobile. |
|
8 ** |
|
9 ** GNU Lesser General Public License Usage |
|
10 ** This file may be used under the terms of the GNU Lesser General Public |
|
11 ** License version 2.1 as published by the Free Software Foundation and |
|
12 ** appearing in the file LICENSE.LGPL included in the packaging of this file. |
|
13 ** Please review the following information to ensure the GNU Lesser General |
|
14 ** Public License version 2.1 requirements will be met: |
|
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. |
|
16 ** |
|
17 ** In addition, as a special exception, Nokia gives you certain additional |
|
18 ** rights. These rights are described in the Nokia Qt LGPL Exception |
|
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. |
|
20 ** |
|
21 ** If you have questions regarding the use of this file, please contact |
|
22 ** Nokia at developer.feedback@nokia.com. |
|
23 ** |
|
24 ****************************************************************************/ |
|
25 |
|
26 #include "hbfeedbackplayer_symbian_p.h" |
|
27 |
|
28 #include <tacticon.h> |
|
29 #include <touchfeedback.h> |
|
30 |
|
31 #include <coecntrl.h> |
|
32 |
|
33 #include <QList> |
|
34 #include <QMap> |
|
35 #include <QMapIterator> |
|
36 #include <QDebug> |
|
37 |
|
38 #include "hbinstantfeedback.h" |
|
39 #include "hbcontinuousfeedback.h" |
|
40 #include "hbtacticonfeedback.h" |
|
41 #include "hbhitareafeedback.h" |
|
42 |
|
43 /*! |
|
44 Symbian-specific feedback class that wraps Symbian feedback APIs. |
|
45 */ |
|
46 |
|
47 class HbFeedbackBasePlayerPrivate |
|
48 { |
|
49 |
|
50 public: |
|
51 HbFeedbackBasePlayerPrivate(); |
|
52 ~HbFeedbackBasePlayerPrivate(); |
|
53 |
|
54 public: |
|
55 void init(); |
|
56 inline int getNewIdentifier(); |
|
57 inline TRect convertToSymbian(const QRect& rect); |
|
58 inline CCoeControl* convertToSymbian(QWidget* window); |
|
59 inline TTouchLogicalFeedback convertToSymbian(HbFeedback::InstantEffect effect); |
|
60 inline TTacticonType convertTacticonToSymbian(HbFeedback::InstantEffect effect); |
|
61 inline TTacticonType convertTacticonToSymbian(HbFeedback::TacticonEffect effect); |
|
62 inline TTouchContinuousFeedback convertToSymbian(HbFeedback::ContinuousEffect effect); |
|
63 inline TTouchEventType convertToSymbian(HbFeedback::HitAreaType hitAreaType); |
|
64 |
|
65 public: |
|
66 MTouchFeedback *iFeedback; |
|
67 RTacticon iTacticon; |
|
68 TBool iTacticonReady; |
|
69 QMap <int, QWidget*> registeredHitAreas; |
|
70 QMap <int, QWidget*> ongoingContinuousFeedbacks; |
|
71 int slidingValue; |
|
72 }; |
|
73 |
|
74 HbFeedbackBasePlayerPrivate::HbFeedbackBasePlayerPrivate() : slidingValue(0) |
|
75 { |
|
76 } |
|
77 |
|
78 HbFeedbackBasePlayerPrivate::~HbFeedbackBasePlayerPrivate() { |
|
79 |
|
80 MTouchFeedback::DestroyInstance(); |
|
81 registeredHitAreas.clear(); |
|
82 iTacticon.Close(); |
|
83 iTacticonReady = EFalse; |
|
84 } |
|
85 |
|
86 void HbFeedbackBasePlayerPrivate::init() { |
|
87 |
|
88 iFeedback = MTouchFeedback::Instance(); |
|
89 if (!iFeedback) { |
|
90 TRAPD(err, iFeedback = MTouchFeedback::CreateInstanceL()); |
|
91 if (err != KErrNone) { |
|
92 iFeedback = 0; |
|
93 } |
|
94 } |
|
95 TInt err = iTacticon.Connect(); |
|
96 if(err) { |
|
97 iTacticonReady = EFalse; |
|
98 } |
|
99 else { |
|
100 iTacticonReady = ETrue; |
|
101 } |
|
102 } |
|
103 |
|
104 int HbFeedbackBasePlayerPrivate::getNewIdentifier() { |
|
105 |
|
106 slidingValue++; |
|
107 return slidingValue; |
|
108 } |
|
109 |
|
110 |
|
111 TRect HbFeedbackBasePlayerPrivate::convertToSymbian(const QRect& rect) { |
|
112 |
|
113 return TRect(rect.left(), rect.top(), rect.right(), rect.bottom()); |
|
114 } |
|
115 |
|
116 TTouchLogicalFeedback HbFeedbackBasePlayerPrivate::convertToSymbian(HbFeedback::InstantEffect effect) { |
|
117 |
|
118 TTouchLogicalFeedback instantFeedbackSymbian = ETouchFeedbackBasic; |
|
119 |
|
120 switch (effect) { |
|
121 |
|
122 case HbFeedback::None: |
|
123 instantFeedbackSymbian = ETouchFeedbackNone; |
|
124 break; |
|
125 case HbFeedback::Basic: |
|
126 instantFeedbackSymbian = ETouchFeedbackBasic; |
|
127 break; |
|
128 case HbFeedback::Sensitive: |
|
129 instantFeedbackSymbian = ETouchFeedbackSensitive; |
|
130 break; |
|
131 case HbFeedback::BasicButton: |
|
132 instantFeedbackSymbian = ETouchFeedbackBasicButton; |
|
133 break; |
|
134 case HbFeedback::SensitiveButton: |
|
135 instantFeedbackSymbian = ETouchFeedbackSensitiveButton; |
|
136 break; |
|
137 case HbFeedback::BasicItem: |
|
138 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
139 break; |
|
140 case HbFeedback::SensitiveItem: |
|
141 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
142 break; |
|
143 case HbFeedback::BounceEffect: |
|
144 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
145 break; |
|
146 case HbFeedback::PopupOpen: |
|
147 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
148 break; |
|
149 case HbFeedback::PopupClose: |
|
150 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
151 break; |
|
152 case HbFeedback::BasicSlider: |
|
153 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
154 break; |
|
155 case HbFeedback::SensitiveSlider: |
|
156 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
157 break; |
|
158 case HbFeedback::StopFlick: |
|
159 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
160 break; |
|
161 case HbFeedback::Flick: |
|
162 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
163 break; |
|
164 case HbFeedback::Editor: |
|
165 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
166 break; |
|
167 case HbFeedback::TextSelection: |
|
168 instantFeedbackSymbian = ETouchFeedbackTextSelection; |
|
169 break; |
|
170 case HbFeedback::BlankSelection: |
|
171 instantFeedbackSymbian = ETouchFeedbackBlankSelection; |
|
172 break; |
|
173 case HbFeedback::LineSelection: |
|
174 instantFeedbackSymbian = ETouchFeedbackLineSelection; |
|
175 break; |
|
176 case HbFeedback::EmptyLineSelection: |
|
177 instantFeedbackSymbian = ETouchFeedbackEmptyLineSelection; |
|
178 break; |
|
179 case HbFeedback::Checkbox: |
|
180 instantFeedbackSymbian = ETouchFeedbackCheckbox; |
|
181 break; |
|
182 case HbFeedback::MultipleCheckbox: |
|
183 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
184 break; |
|
185 case HbFeedback::SensitiveKeypad: |
|
186 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
187 break; |
|
188 case HbFeedback::BasicKeypad: |
|
189 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
190 break; |
|
191 case HbFeedback::MultitouchActivate: |
|
192 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
193 break; |
|
194 case HbFeedback::RotateStep: |
|
195 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
196 break; |
|
197 case HbFeedback::ItemDrop: |
|
198 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
199 break; |
|
200 case HbFeedback::ItemMoveOver: |
|
201 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
202 break; |
|
203 case HbFeedback::ItemPick: |
|
204 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
205 break; |
|
206 case HbFeedback::ItemScroll: |
|
207 instantFeedbackSymbian = ETouchFeedbackBasic; // Effects changing in 10.1 are mapped to basic. |
|
208 break; |
|
209 case HbFeedback::PopUp: |
|
210 instantFeedbackSymbian = ETouchFeedbackPopUp; |
|
211 break; |
|
212 default: |
|
213 break; |
|
214 } |
|
215 return instantFeedbackSymbian; |
|
216 } |
|
217 |
|
218 TTacticonType HbFeedbackBasePlayerPrivate::convertTacticonToSymbian(HbFeedback::InstantEffect effect) { |
|
219 |
|
220 TTacticonType type = ENoTacticon; |
|
221 |
|
222 switch (effect) { |
|
223 |
|
224 case HbFeedback::PositiveTacticon: |
|
225 type = EPositiveTacticon; |
|
226 break; |
|
227 case HbFeedback::NeutralTacticon: |
|
228 type = ENeutralTacticon; |
|
229 break; |
|
230 case HbFeedback::NegativeTacticon: |
|
231 type = ENegativeTacticon; |
|
232 break; |
|
233 default: |
|
234 break; |
|
235 } |
|
236 return type; |
|
237 } |
|
238 |
|
239 TTacticonType HbFeedbackBasePlayerPrivate::convertTacticonToSymbian(HbFeedback::TacticonEffect effect) { |
|
240 |
|
241 TTacticonType type = ENoTacticon; |
|
242 |
|
243 switch (effect) { |
|
244 |
|
245 case HbFeedback::TacticonPositive: |
|
246 type = EPositiveTacticon; |
|
247 break; |
|
248 case HbFeedback::TacticonNeutral: |
|
249 type = ENeutralTacticon; |
|
250 break; |
|
251 case HbFeedback::TacticonNegative: |
|
252 type = ENegativeTacticon; |
|
253 break; |
|
254 default: |
|
255 break; |
|
256 } |
|
257 return type; |
|
258 } |
|
259 |
|
260 TTouchContinuousFeedback HbFeedbackBasePlayerPrivate::convertToSymbian(HbFeedback::ContinuousEffect effect) { |
|
261 |
|
262 TTouchContinuousFeedback continuousFeedbackSymbian = ETouchContinuousSmooth; |
|
263 |
|
264 switch (effect) { |
|
265 |
|
266 case HbFeedback::ContinuousSmooth: |
|
267 continuousFeedbackSymbian = ETouchContinuousSmooth; |
|
268 break; |
|
269 case HbFeedback::ContinuousSlider: |
|
270 continuousFeedbackSymbian = ETouchContinuousSlider; |
|
271 break; |
|
272 case HbFeedback::ContinuousInput: |
|
273 continuousFeedbackSymbian = ETouchContinuousInput; |
|
274 break; |
|
275 // Effects coming in 10.1 are mapped to smooth temporarily. |
|
276 case HbFeedback::ContinuousPopup: |
|
277 continuousFeedbackSymbian = ETouchContinuousSmooth; |
|
278 break; |
|
279 case HbFeedback::ContinuousPinch: |
|
280 continuousFeedbackSymbian = ETouchContinuousSmooth; |
|
281 break; |
|
282 default: |
|
283 break; |
|
284 } |
|
285 return continuousFeedbackSymbian; |
|
286 } |
|
287 |
|
288 TTouchEventType HbFeedbackBasePlayerPrivate::convertToSymbian(HbFeedback::HitAreaType hitAreaType) { |
|
289 |
|
290 TTouchEventType touchEventType = ETouchEventStylusDown; |
|
291 |
|
292 if ( hitAreaType == HbFeedback::MouseButtonPress ) { |
|
293 touchEventType = ETouchEventStylusDown; |
|
294 } else if (hitAreaType == HbFeedback::MouseButtonRelease ) { |
|
295 // ETouchEventStylusUp not yet supported |
|
296 touchEventType = ETouchEventStylusDown; |
|
297 } |
|
298 return touchEventType; |
|
299 } |
|
300 |
|
301 |
|
302 CCoeControl* HbFeedbackBasePlayerPrivate::convertToSymbian(QWidget* window) { |
|
303 |
|
304 CCoeControl* control = 0; |
|
305 |
|
306 if ( window && window->winId()) { |
|
307 control = reinterpret_cast<CCoeControl*>(window->winId()); |
|
308 } |
|
309 return control; |
|
310 } |
|
311 |
|
312 HbFeedbackBasePlayer::HbFeedbackBasePlayer() : d(new HbFeedbackBasePlayerPrivate) { |
|
313 |
|
314 d->init(); |
|
315 } |
|
316 |
|
317 HbFeedbackBasePlayer::~HbFeedbackBasePlayer() { |
|
318 |
|
319 removeHitAreas(); |
|
320 cancelContinuousFeedbacks(); |
|
321 delete d; |
|
322 } |
|
323 |
|
324 void HbFeedbackBasePlayer::removeHitAreas() { |
|
325 |
|
326 // remove hit areas |
|
327 QMapIterator<int, QWidget*> i(d->registeredHitAreas); |
|
328 |
|
329 while (i.hasNext()) { |
|
330 i.next(); |
|
331 removeHitArea( i.key()); |
|
332 } |
|
333 |
|
334 d->registeredHitAreas.clear(); |
|
335 } |
|
336 |
|
337 void HbFeedbackBasePlayer::cancelContinuousFeedbacks() { |
|
338 |
|
339 // stop ongoing continuous feedbacks |
|
340 QMapIterator<int, QWidget*> i(d->ongoingContinuousFeedbacks); |
|
341 |
|
342 while (i.hasNext()) { |
|
343 i.next(); |
|
344 cancelContinuousFeedback(i.key()); |
|
345 } |
|
346 |
|
347 d->ongoingContinuousFeedbacks.clear(); |
|
348 } |
|
349 |
|
350 void HbFeedbackBasePlayer::playInstantFeedback(const HbInstantFeedback& feedback) { |
|
351 |
|
352 if (d->iFeedback) { |
|
353 // If the effect is a tacticon, use the tacticon playing mechanism of the feedback player |
|
354 if (feedback.instantEffect() == HbFeedback::PositiveTacticon || |
|
355 feedback.instantEffect() == HbFeedback::NeutralTacticon || |
|
356 feedback.instantEffect() == HbFeedback::NegativeTacticon) { |
|
357 if (d->iTacticonReady) { |
|
358 d->iTacticon.PlayTacticon(d->convertTacticonToSymbian(feedback.instantEffect())); |
|
359 } |
|
360 } else { |
|
361 CCoeControl* control = d->convertToSymbian(feedback.window()); |
|
362 if (control) { |
|
363 d->iFeedback->InstantFeedback(control, d->convertToSymbian(feedback.instantEffect())); |
|
364 } |
|
365 else { |
|
366 d->iFeedback->InstantFeedback(d->convertToSymbian(feedback.instantEffect())); |
|
367 } |
|
368 } |
|
369 } |
|
370 } |
|
371 |
|
372 void HbFeedbackBasePlayer::playTacticonFeedback(const HbTacticonFeedback& feedback) { |
|
373 |
|
374 if (d->iTacticonReady) { |
|
375 d->iTacticon.PlayTacticon(d->convertTacticonToSymbian(feedback.tacticonEffect())); |
|
376 } |
|
377 } |
|
378 |
|
379 int HbFeedbackBasePlayer::startContinuousFeedback(const HbContinuousFeedback& feedback) { |
|
380 |
|
381 int identifier = -1; |
|
382 CCoeControl* control = d->convertToSymbian(feedback.window()); |
|
383 |
|
384 if (d->iFeedback && control) { |
|
385 identifier = d->getNewIdentifier(); |
|
386 if (feedback.continuousEffect() != HbFeedback::ContinuousNone) { |
|
387 d->iFeedback->StartFeedback(control, d->convertToSymbian(feedback.continuousEffect()), |
|
388 0, feedback.intensity(), |
|
389 1000*feedback.timeout()); |
|
390 } |
|
391 d->ongoingContinuousFeedbacks.insert(identifier, feedback.window()); |
|
392 } |
|
393 return identifier; |
|
394 } |
|
395 |
|
396 void HbFeedbackBasePlayer::updateContinuousFeedback(int identifier, const HbContinuousFeedback& feedback) { |
|
397 |
|
398 CCoeControl* control = d->convertToSymbian(feedback.window()); |
|
399 |
|
400 if (d->iFeedback && control) { |
|
401 if (d->ongoingContinuousFeedbacks.contains(identifier)) { |
|
402 CCoeControl* storedControl = d->convertToSymbian(d->ongoingContinuousFeedbacks[identifier]); |
|
403 if (storedControl == control) { |
|
404 if (feedback.continuousEffect() != HbFeedback::ContinuousNone) { |
|
405 d->iFeedback->StartFeedback( storedControl, |
|
406 d->convertToSymbian(feedback.continuousEffect()), |
|
407 0, feedback.intensity(), |
|
408 1000*feedback.timeout()); |
|
409 } else { |
|
410 d->iFeedback->StopFeedback(storedControl); |
|
411 } |
|
412 } |
|
413 } |
|
414 } |
|
415 } |
|
416 |
|
417 void HbFeedbackBasePlayer::cancelContinuousFeedback(int identifier) { |
|
418 |
|
419 if (d->iFeedback) { |
|
420 if (d->ongoingContinuousFeedbacks.contains(identifier)) { |
|
421 d->iFeedback->StopFeedback(d->convertToSymbian(d->ongoingContinuousFeedbacks[identifier])); |
|
422 d->ongoingContinuousFeedbacks.remove(identifier); |
|
423 } |
|
424 } |
|
425 } |
|
426 |
|
427 bool HbFeedbackBasePlayer::continuousFeedbackOngoing(int identifier) { |
|
428 |
|
429 bool feedbackOngoing(false); |
|
430 if (d->ongoingContinuousFeedbacks.contains(identifier)) { |
|
431 feedbackOngoing = true; |
|
432 } |
|
433 return feedbackOngoing; |
|
434 } |
|
435 |
|
436 int HbFeedbackBasePlayer::insertHitArea(const HbHitAreaFeedback& feedback) { |
|
437 |
|
438 int identifier = -1; |
|
439 CCoeControl* control = d->convertToSymbian(feedback.window()); |
|
440 if (d->iFeedback && control) { |
|
441 identifier = d->getNewIdentifier(); |
|
442 TTouchLogicalFeedback logicalFeedback = d->convertToSymbian(feedback.instantEffect()); |
|
443 // current hit area implementation below does not yet support new logical feedbacks |
|
444 if (logicalFeedback > ETouchFeedbackSensitive) { |
|
445 logicalFeedback = ETouchFeedbackSensitive; |
|
446 } |
|
447 |
|
448 int errorValue = d->iFeedback->SetFeedbackArea(control, identifier, |
|
449 d->convertToSymbian(feedback.rect()), |
|
450 logicalFeedback, |
|
451 d->convertToSymbian(feedback.hitAreaType())); |
|
452 if (errorValue >= 0) { |
|
453 // no error |
|
454 d->registeredHitAreas.insert(identifier, feedback.window()); |
|
455 } |
|
456 } |
|
457 return identifier; |
|
458 } |
|
459 |
|
460 void HbFeedbackBasePlayer::updateHitArea(int identifier, const HbHitAreaFeedback& feedback) { |
|
461 |
|
462 CCoeControl* control = d->convertToSymbian(feedback.window()); |
|
463 |
|
464 if (d->iFeedback && control && d->registeredHitAreas.contains(identifier)) { |
|
465 CCoeControl* storedControl = d->convertToSymbian(d->registeredHitAreas[identifier]); |
|
466 if (storedControl == control) { |
|
467 d->iFeedback->ChangeFeedbackArea(storedControl, identifier, d->convertToSymbian(feedback.rect())); |
|
468 } |
|
469 } |
|
470 } |
|
471 |
|
472 void HbFeedbackBasePlayer::removeHitArea(int identifier) { |
|
473 |
|
474 if (d->iFeedback && d->registeredHitAreas.contains(identifier)) { |
|
475 CCoeControl* storedControl = d->convertToSymbian(d->registeredHitAreas[identifier]); |
|
476 d->iFeedback->RemoveFeedbackArea(storedControl, identifier); |
|
477 d->registeredHitAreas.remove(identifier); |
|
478 } |
|
479 } |
|
480 |
|
481 bool HbFeedbackBasePlayer::hitAreaExists(int identifier) { |
|
482 |
|
483 return d->registeredHitAreas.contains(identifier); |
|
484 } |