|
1 /* |
|
2 * Copyright (c) 2002-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: Avkon keysound animation dll. |
|
15 * |
|
16 */ |
|
17 |
|
18 // INCLUDES |
|
19 #include "AknAnimKeySound.h" |
|
20 #include <eikkeysound.h> |
|
21 #include "aknanimdllstd.h" |
|
22 #include <AknKeyRotator.h> |
|
23 #include <keffactory.h> |
|
24 #include <centralrepository.h> |
|
25 |
|
26 // End key - power key related headers |
|
27 #include <featmgr.h> |
|
28 #include <e32property.h> |
|
29 #include <UikonInternalPSKeys.h> |
|
30 #include "avkoninternalpskeys.h" // KAknIdleAppWindowGroupId |
|
31 #include <avkondomainpskeys.h> // KAknPowerMenuStatus & KAknEndKeyEvent |
|
32 |
|
33 // This is currently nasty set dependencies, API should be moved to middleware layer asap |
|
34 #include <ctsydomainpskeys.h> |
|
35 #include <activeidle2domainpskeys.h> |
|
36 #include <NetworkHandlingDomainPSKeys.h> |
|
37 #include <PSVariables.h> |
|
38 |
|
39 #include <hwrmlight.h> |
|
40 #include <tactilefeedbackserver.h> |
|
41 |
|
42 // CONSTANTS |
|
43 const TInt KShortPress(600000); |
|
44 const TInt KLongPress(1800000); // Extreme long press 2,4s - 0,6s |
|
45 |
|
46 enum TKeyEmulationAction |
|
47 { |
|
48 EDoNothing = 0, |
|
49 EEmulateNow, |
|
50 EEmulateNowPhoneCallActive, |
|
51 EEmulateNowNotificationOnTop, |
|
52 ESetEventPending |
|
53 }; |
|
54 |
|
55 // Scan codes in this table are blocked by the animdll if another key is currently being pressed |
|
56 // This prevents two keys from being pressed, but allows power key, headset and grip to still be |
|
57 // operated. |
|
58 const TInt KBlockedKeyCodes[] = |
|
59 { |
|
60 '1', |
|
61 '2', |
|
62 '3', |
|
63 '4', |
|
64 '5', |
|
65 '6', |
|
66 '7', |
|
67 '8', |
|
68 '9', |
|
69 '0', |
|
70 EStdKeyHash, |
|
71 EStdKeyNkpAsterisk, |
|
72 EStdKeyYes, |
|
73 EStdKeyNo, |
|
74 EStdKeyApplication0, // Apps key |
|
75 EStdKeyDevice6 // Side key |
|
76 }; |
|
77 |
|
78 const TInt KBlockedKeyCodeTableSize = sizeof(KBlockedKeyCodes) / sizeof(TInt); |
|
79 |
|
80 NONSHARABLE_CLASS(CAknPendingKeyEvent): public CTimer |
|
81 { |
|
82 public: |
|
83 static CAknPendingKeyEvent* NewL(MAnimGeneralFunctions* aFucntions, TInt& aEmulatedKey); |
|
84 ~CAknPendingKeyEvent(); |
|
85 TBool HandleKeyReleased(const TRawEvent &aRawEvent); |
|
86 void SetShortTimerForEvent(const TRawEvent &aRawEvent); |
|
87 void SetLongTimerForEvent(const TRawEvent &aRawEvent); |
|
88 void JustEmulateUpEvent(const TRawEvent &aRawEvent); |
|
89 TBool IsMadeUpEvent() |
|
90 { |
|
91 return iIsMadeUpEvent; |
|
92 } |
|
93 |
|
94 private: |
|
95 CAknPendingKeyEvent(MAnimGeneralFunctions* aFucntions, TInt& aEmulatedKey); |
|
96 void RunL(); |
|
97 void DoCancel(); |
|
98 |
|
99 enum |
|
100 { |
|
101 EBreathe, |
|
102 EShort, |
|
103 ELong, |
|
104 EWaitingUpEvent |
|
105 }; |
|
106 |
|
107 TInt iState; |
|
108 TRawEvent iPendingEvent; |
|
109 TInt& iEmulatedKey; |
|
110 MAnimGeneralFunctions* iFunctions; |
|
111 TBool iIsMadeUpEvent; // Indicates whether the event is self generated. |
|
112 }; |
|
113 |
|
114 // REikSrvSoundServerSession implementation: |
|
115 |
|
116 // ----------------------------------------------------------------------------- |
|
117 // REikSrvSoundServerSession::Connect |
|
118 // ----------------------------------------------------------------------------- |
|
119 // |
|
120 TInt REikSrvSoundServerSession::Connect() |
|
121 { |
|
122 // Create a session with zero message slots |
|
123 // (since we have no asycronous calls). |
|
124 TInt ret=CreateSession |
|
125 ( |
|
126 __KEYSOUND_SERVER_NAME, |
|
127 TVersion( |
|
128 KKeySoundServMajorVN, |
|
129 KKeySoundServMinorVN, |
|
130 KKeySoundServBuildVN ), |
|
131 1 |
|
132 ); |
|
133 return ret; |
|
134 } |
|
135 |
|
136 // ----------------------------------------------------------------------------- |
|
137 // REikSrvSoundServerSession::KeyPressed |
|
138 // |
|
139 // NB. as this is asynchronous, the cancel should be provided also, anyway we rely on that |
|
140 // keysound server will complete all requests relatively fast so we never stall on |
|
141 // ~CAknAnimKeySound more than tens of milliseconds. |
|
142 // ----------------------------------------------------------------------------- |
|
143 // |
|
144 void REikSrvSoundServerSession::KeyPressed( TInt aKey, TRequestStatus& aStatus, TBool aRepeat ) |
|
145 { |
|
146 TIpcArgs args( aKey, aRepeat); |
|
147 SendReceive( EKeySoundServerPlayKey, args, aStatus ); |
|
148 } |
|
149 |
|
150 // CAknAnimKeySound implementation: |
|
151 |
|
152 // ----------------------------------------------------------------------------- |
|
153 // CAknAnimKeySound::CAknAnimKeySound |
|
154 // ----------------------------------------------------------------------------- |
|
155 // |
|
156 CAknAnimKeySound::CAknAnimKeySound() |
|
157 :iEnableKeyBlock(ETrue), |
|
158 iBlockedPointerDown(EFalse), |
|
159 iBlockKeyEvents( EFalse ), |
|
160 iBlockPointerEvents( EFalse ) |
|
161 { |
|
162 iFeedback = MTactileFeedbackServer::Instance(); |
|
163 } |
|
164 |
|
165 // ----------------------------------------------------------------------------- |
|
166 // CAknAnimKeySound::~CAknAnimKeySound |
|
167 // ----------------------------------------------------------------------------- |
|
168 // |
|
169 CAknAnimKeySound::~CAknAnimKeySound() |
|
170 { |
|
171 if ( iFunctions ) |
|
172 { |
|
173 iFunctions->GetRawEvents( EFalse ); |
|
174 } |
|
175 delete iKeyRotator; |
|
176 iRotateLibrary.Close(); |
|
177 |
|
178 delete iKeyEventMap; |
|
179 iKefLibrary.Close(); |
|
180 |
|
181 |
|
182 delete iSoundSession; |
|
183 delete iPendingEvent; |
|
184 delete iLight; |
|
185 } |
|
186 |
|
187 // ----------------------------------------------------------------------------- |
|
188 // CAknAnimKeySound::CommandReplyL |
|
189 // ----------------------------------------------------------------------------- |
|
190 // |
|
191 TInt CAknAnimKeySound::CommandReplyL( TInt /*aOpcode*/, TAny* /*aArgs*/ ) |
|
192 { |
|
193 return KErrNone; |
|
194 } |
|
195 |
|
196 // ----------------------------------------------------------------------------- |
|
197 // CAknAnimKeySound::Command |
|
198 // ----------------------------------------------------------------------------- |
|
199 // |
|
200 void CAknAnimKeySound::Command( TInt /*aOpcode*/, TAny* /*aArgs*/ ) |
|
201 { |
|
202 } |
|
203 |
|
204 // ----------------------------------------------------------------------------- |
|
205 // CAknAnimKeySound::Animate |
|
206 // ----------------------------------------------------------------------------- |
|
207 // |
|
208 void CAknAnimKeySound::Animate( TDateTime* /*aDateTime*/ ) |
|
209 { |
|
210 } |
|
211 |
|
212 // ----------------------------------------------------------------------------- |
|
213 // CAknAnimKeySound::ConstructL |
|
214 // ----------------------------------------------------------------------------- |
|
215 // |
|
216 void CAknAnimKeySound::ConstructL( TAny* /*aArgs*/, TBool /*aHasFocus*/ ) |
|
217 { |
|
218 iFunctions->GetRawEvents( ETrue ); |
|
219 |
|
220 iSoundSession = new (ELeave) CAknAsynchTonePlayer(); |
|
221 |
|
222 if ( iKefLibrary.Load( KKefLibraryName ) == KErrNone ) |
|
223 { |
|
224 // The function in the lookup table may leave (CreateKefMapL) |
|
225 TInt res = iKefLibrary.Lookup( KKefMapFactoryFunctionOrdinal )(); |
|
226 iKeyEventMap = (CKefMap*)res; |
|
227 |
|
228 if ( !iKeyEventMap->IsKeyEventMapEnabled() ) |
|
229 { |
|
230 // Key event map is disabled. Use default approach. |
|
231 delete iKeyEventMap; |
|
232 iKeyEventMap = NULL; |
|
233 iKefLibrary.Close(); |
|
234 } |
|
235 else |
|
236 { |
|
237 iKeyEventMap->SetProvider( *this ); |
|
238 } |
|
239 } |
|
240 |
|
241 if ( !iKeyEventMap ) |
|
242 { |
|
243 if ( iRotateLibrary.Load( KAknKeyRotatorLibraryName ) == KErrNone ) |
|
244 { |
|
245 // The function in the lookup table may leave (CreateAknKeyRotatorL) |
|
246 TInt res = iRotateLibrary.Lookup( KAknKeyRotatorFactoryFunctionOrdinal )(); |
|
247 iKeyRotator = (CAknKeyRotator*)res; |
|
248 } |
|
249 iConnected = iSoundSession->iSoundSession.Handle() != 0; |
|
250 } |
|
251 |
|
252 FeatureManager::InitializeLibL(); |
|
253 iFeatureNoPowerKey = |
|
254 FeatureManager::FeatureSupported( KFeatureIdNoPowerkey ); |
|
255 |
|
256 if (iFeatureNoPowerKey) |
|
257 { |
|
258 iPendingEvent = CAknPendingKeyEvent::NewL(iFunctions, iNoPowerKeyScanCode); |
|
259 } |
|
260 |
|
261 FeatureManager::UnInitializeLib(); |
|
262 |
|
263 // Get extension for querying and manipulating the window and screen attributes. |
|
264 iExt = reinterpret_cast<MAnimGeneralFunctionsWindowExtension*>(iFunctions->ExtendedInterface( |
|
265 MAnimGeneralFunctions::EWindowExtensionInterface)); |
|
266 |
|
267 iLight = CHWRMLight::NewL(); |
|
268 } |
|
269 |
|
270 // ----------------------------------------------------------------------------- |
|
271 // CAknAnimKeySound::Redraw |
|
272 // ----------------------------------------------------------------------------- |
|
273 // |
|
274 void CAknAnimKeySound::Redraw() |
|
275 { |
|
276 } |
|
277 |
|
278 // ----------------------------------------------------------------------------- |
|
279 // CAknAnimKeySound::FocusChanged |
|
280 // ----------------------------------------------------------------------------- |
|
281 // |
|
282 void CAknAnimKeySound::FocusChanged( TBool /*aState*/ ) |
|
283 { |
|
284 } |
|
285 |
|
286 // ----------------------------------------------------------------------------- |
|
287 // CAknAnimKeySound::IsBlockedKeyCode |
|
288 // ----------------------------------------------------------------------------- |
|
289 // |
|
290 TBool CAknAnimKeySound::IsBlockedKeyCode( TInt aScanCode ) |
|
291 { |
|
292 for ( TInt ii=0; ii < KBlockedKeyCodeTableSize; ii++ ) |
|
293 { |
|
294 if ( aScanCode == KBlockedKeyCodes[ii] ) |
|
295 { |
|
296 return ETrue; |
|
297 } |
|
298 } |
|
299 return EFalse; |
|
300 } |
|
301 |
|
302 // ----------------------------------------------------------------------------- |
|
303 // CAknAnimKeySound::NonBlockedKeyCode |
|
304 // ----------------------------------------------------------------------------- |
|
305 // |
|
306 TBool CAknAnimKeySound::NonBlockedKeyCode( TInt aScanCode ) |
|
307 { |
|
308 // Return ETrue if this key is never blocked - typically just modifiers |
|
309 if ( aScanCode == EStdKeyLeftShift || aScanCode == EStdKeyRightShift || |
|
310 aScanCode == EStdKeyLeftCtrl || aScanCode == EStdKeyRightCtrl || |
|
311 aScanCode == EStdKeyLeftAlt || aScanCode == EStdKeyRightAlt || |
|
312 aScanCode == EStdKeyLeftFunc || aScanCode == EStdKeyRightFunc ) |
|
313 { |
|
314 return ETrue; |
|
315 } |
|
316 return EFalse; |
|
317 } |
|
318 |
|
319 // ----------------------------------------------------------------------------- |
|
320 // CAknAnimKeySound::IsBlockedEvent |
|
321 // HW keys and touch event interaction |
|
322 // ----------------------------------------------------------------------------- |
|
323 // |
|
324 TBool CAknAnimKeySound::IsBlockedEvent( const TRawEvent &aRawEvent ) |
|
325 { |
|
326 // Check key event exceptions |
|
327 if ( iBlockKeyEvents ) |
|
328 { |
|
329 if ( aRawEvent.Type() == TRawEvent::EKeyDown || |
|
330 aRawEvent.Type() == TRawEvent::EKeyRepeat || |
|
331 aRawEvent.Type() == TRawEvent::EKeyUp ) |
|
332 { |
|
333 // Vkb generated key event |
|
334 if ( aRawEvent.IsTip () ) |
|
335 { |
|
336 return EFalse; |
|
337 } |
|
338 TInt scan = aRawEvent.ScanCode() & 0xFFFF; |
|
339 if ( IsAlwaysAcceptedKey( scan ) ) |
|
340 { |
|
341 return EFalse; |
|
342 } |
|
343 } |
|
344 } |
|
345 |
|
346 // if key down, block pointer events and vice versa |
|
347 switch ( aRawEvent.Type() ) |
|
348 { |
|
349 case TRawEvent::EKeyDown: |
|
350 { |
|
351 if ( iBlockKeyEvents ) |
|
352 { |
|
353 return ETrue; |
|
354 } |
|
355 else |
|
356 { |
|
357 // If exception key, don't block pointer events |
|
358 TInt scan = aRawEvent.ScanCode() & 0xFFFF; |
|
359 if ( IsAlwaysAcceptedKey( scan ) ) |
|
360 { |
|
361 iBlockPointerEvents = EFalse; |
|
362 } |
|
363 else |
|
364 { |
|
365 iBlockPointerEvents = ETrue; |
|
366 } |
|
367 } |
|
368 break; |
|
369 } |
|
370 |
|
371 case TRawEvent::EKeyRepeat: |
|
372 { |
|
373 if ( iBlockKeyEvents ) |
|
374 { |
|
375 return ETrue; |
|
376 } |
|
377 break; |
|
378 } |
|
379 |
|
380 case TRawEvent::EKeyUp: |
|
381 { |
|
382 if ( iBlockKeyEvents ) |
|
383 { |
|
384 return ETrue; |
|
385 } |
|
386 else |
|
387 { |
|
388 iBlockPointerEvents = EFalse; |
|
389 } |
|
390 break; |
|
391 } |
|
392 |
|
393 case TRawEvent::EButton1Down: |
|
394 { |
|
395 if ( iBlockPointerEvents ) |
|
396 { |
|
397 return ETrue; |
|
398 } |
|
399 else |
|
400 { |
|
401 iBlockKeyEvents = ETrue; |
|
402 } |
|
403 break; |
|
404 } |
|
405 |
|
406 case TRawEvent::EPointerMove: |
|
407 { |
|
408 if ( iBlockPointerEvents ) |
|
409 { |
|
410 return ETrue; |
|
411 } |
|
412 break; |
|
413 } |
|
414 |
|
415 case TRawEvent::EButton1Up: |
|
416 { |
|
417 if ( iBlockPointerEvents ) |
|
418 { |
|
419 return ETrue; |
|
420 } |
|
421 else |
|
422 { |
|
423 iBlockKeyEvents = EFalse; |
|
424 } |
|
425 break; |
|
426 } |
|
427 |
|
428 default: |
|
429 break; |
|
430 } |
|
431 return EFalse; |
|
432 } |
|
433 |
|
434 // ----------------------------------------------------------------------------- |
|
435 // CAknAnimKeySound::IsAlwaysAcceptedKey |
|
436 // HW keys and touch event interaction - keys that work even if touch is active |
|
437 // ----------------------------------------------------------------------------- |
|
438 // |
|
439 TBool CAknAnimKeySound::IsAlwaysAcceptedKey( TInt aScanCode ) |
|
440 { |
|
441 if ( aScanCode == EStdKeyLeftShift || aScanCode == EStdKeyRightShift || |
|
442 aScanCode == EStdKeyLeftCtrl || aScanCode == EStdKeyRightCtrl || |
|
443 aScanCode == EStdKeyLeftAlt || aScanCode == EStdKeyRightAlt || |
|
444 aScanCode == EStdKeyApplication10 || // Layout switch to landscape |
|
445 aScanCode == EStdKeyApplication14 || // Layout switch to portrait |
|
446 aScanCode == EStdKeyDevice2 || // Power button |
|
447 // Device & application keys |
|
448 ( aScanCode >= EStdKeyDevice4 && aScanCode <= EStdKeyDeviceF )|| |
|
449 ( aScanCode >= EStdKeyApplication6 && aScanCode <= EStdKeyApplicationF ) || |
|
450 ( aScanCode >= EStdKeyDevice10 && aScanCode <= EStdKeyApplication27 ) ) |
|
451 { |
|
452 return ETrue; |
|
453 } |
|
454 return EFalse; |
|
455 } |
|
456 |
|
457 |
|
458 // ----------------------------------------------------------------------------- |
|
459 // IsIdleAppOnTop |
|
460 // |
|
461 // Returns ETrue, if the window group of Idle application is topmost. |
|
462 // ----------------------------------------------------------------------------- |
|
463 // |
|
464 TBool IsIdleAppOnTop(MAnimGeneralFunctionsWindowExtension* aExt) |
|
465 { |
|
466 TBool retval = ETrue; |
|
467 TInt idleWgId = 0; |
|
468 MAnimGeneralFunctionsWindowExtension::TWindowGroupInfo wgInfo; |
|
469 |
|
470 // Check screen having focus and the number of existing window groups. |
|
471 TInt focused = aExt->FocusScreens(); |
|
472 TInt groups = aExt->WindowGroups(focused); |
|
473 |
|
474 // Get the idle application window group id. |
|
475 TInt err = RProperty::Get(KPSUidAvkonInternal, KAknIdleAppWindowGroupId, idleWgId); |
|
476 |
|
477 // If there is an error fetching the window group id, it is safer to assume that |
|
478 // Idle application is on top. The power menu will be shown then. |
|
479 if(!err && idleWgId != -1) |
|
480 { |
|
481 // Got valid window group id. Go through the window group list and find if there is a |
|
482 // focusable group on top of Idle. |
|
483 for (TInt i = 0; i < groups; i++) |
|
484 { |
|
485 const TBool exist = aExt->WindowGroupInfo(wgInfo, focused, i); |
|
486 |
|
487 if(exist) |
|
488 { |
|
489 if (wgInfo.iId == idleWgId) |
|
490 { |
|
491 // Idle app is on top. |
|
492 break; |
|
493 } |
|
494 else if (wgInfo.IsFocusable()) |
|
495 { |
|
496 // We have some notification on top of the idle app. |
|
497 retval = EFalse; |
|
498 break; |
|
499 } |
|
500 } |
|
501 } |
|
502 } |
|
503 else |
|
504 { |
|
505 #ifdef _DEBUG |
|
506 RDebug::Print(_L("AknAnimKeySound:IsIdleAppOnTop() - Error fetching idleWgId, id=%d"), err); |
|
507 #endif |
|
508 } |
|
509 return retval; |
|
510 } |
|
511 |
|
512 // ----------------------------------------------------------------------------- |
|
513 // EmulateEndKeyL |
|
514 // |
|
515 // Emulates end key. Used if the device has combined power and end key. |
|
516 // ----------------------------------------------------------------------------- |
|
517 // |
|
518 void EmulateEndKeyL(TKeyEmulationAction& aResult, const TRawEvent &aRawEvent, |
|
519 /*TInt& aEmulatedScanCode,*/ MAnimGeneralFunctionsWindowExtension* aExt) |
|
520 { |
|
521 aResult = EDoNothing; |
|
522 if (aRawEvent.Type() == TRawEvent::EKeyDown) |
|
523 { |
|
524 TInt ps(0), startupOk(0), idle(0); |
|
525 |
|
526 // If system is not in idle or there are calls ongoing, then end key ought to be generated. |
|
527 User::LeaveIfError( RProperty::Get( KPSUidCtsyCallInformation, KCTsyCallState, ps ) ); |
|
528 User::LeaveIfError( RProperty::Get( KPSUidAiInformation, KActiveIdleState, idle ) ); |
|
529 User::LeaveIfError( RProperty::Get( KPSUidUikon, KUikGlobalNotesAllowed, startupOk ) ); |
|
530 |
|
531 RDebug::Print(_L("call: %d, idle %d, notes %d"), ps, idle, startupOk); |
|
532 |
|
533 // Call state not yet initialized or startup not yet complete but no emergency call ongoing. |
|
534 if (ps == EPSCTsyCallStateUninitialized || |
|
535 (ps == EPSCTsyCallStateNone && !startupOk) ) |
|
536 { |
|
537 return; |
|
538 } |
|
539 |
|
540 if ( idle == EPSAiForeground ) |
|
541 { |
|
542 // Notify active idle plugins that combined end key / power key has been pressed. |
|
543 RProperty::Set(KPSUidAvkonDomain, KAknEndKeyEvent, 1); |
|
544 } |
|
545 |
|
546 if ( ps != EPSCTsyCallStateNone ) |
|
547 { |
|
548 // A phone call is active. |
|
549 aResult = EEmulateNowPhoneCallActive; |
|
550 } |
|
551 else if ( idle != EPSAiForeground ) |
|
552 { |
|
553 // We are not in idle view. No active phone calls. |
|
554 aResult = EEmulateNow; |
|
555 } |
|
556 else |
|
557 { |
|
558 // We are in idle view with no active phone calls. |
|
559 TInt powerMenuActive(0); |
|
560 |
|
561 // If power menu is active, do not check windows on top of the Idle app, short power |
|
562 // key presses must change the item in the power menu, not to close the power menu. |
|
563 User::LeaveIfError(RProperty::Get(KPSUidAvkonDomain, KAknPowerMenuStatus, powerMenuActive)); |
|
564 if(!powerMenuActive) |
|
565 { |
|
566 // If there is a notification (window) on top of idle, the event is changed to |
|
567 // end key for closing it. Otherwise we continue normally. |
|
568 if(!IsIdleAppOnTop(aExt)) |
|
569 { |
|
570 aResult = EEmulateNowNotificationOnTop; |
|
571 return; |
|
572 } |
|
573 } |
|
574 |
|
575 // Make bearer resolution. |
|
576 User::LeaveIfError(RProperty::Get(KPSUidNetworkInfo, KNWTelephonyNetworkMode, ps)); |
|
577 if (ps == ENWNetworkModeWcdma) |
|
578 { |
|
579 User::LeaveIfError(RProperty::Get(KUidSystemCategory, KPSUidWcdmaStatusValue, ps)); |
|
580 if (ps != EPSWcdmaStatusUninitialized && ps != EPSWcdmaUnattached && ps != KErrUnknown) |
|
581 { |
|
582 // Wcdma is active (or attached). |
|
583 aResult = ESetEventPending; |
|
584 } |
|
585 else |
|
586 { |
|
587 // Wcdma is not active, do nothing. |
|
588 } |
|
589 } |
|
590 else // gsm et als |
|
591 { |
|
592 User::LeaveIfError(RProperty::Get(KUidSystemCategory, KPSUidGprsStatusValue, ps)); |
|
593 if (ps != EPSGprsUnattached && ps != EPSGprsStatusUninitialized && ps != KErrUnknown) |
|
594 { |
|
595 // Gprs is active (or attached). |
|
596 aResult = ESetEventPending; |
|
597 } |
|
598 else |
|
599 { |
|
600 // Gprs is not active, do nothing. |
|
601 } |
|
602 } |
|
603 } |
|
604 } |
|
605 } |
|
606 |
|
607 // ----------------------------------------------------------------------------- |
|
608 // EmulateEndKey |
|
609 // |
|
610 // Emulates end key. Used if the device has combined power and end key. |
|
611 // ----------------------------------------------------------------------------- |
|
612 // |
|
613 TKeyEmulationAction EmulateEndKey(const TRawEvent &aRawEvent, /*TInt& aEmulatedScanCode,*/ |
|
614 MAnimGeneralFunctionsWindowExtension* aExt) |
|
615 { |
|
616 TKeyEmulationAction result(EDoNothing); |
|
617 { |
|
618 TRAP_IGNORE(EmulateEndKeyL(result, aRawEvent/*, aEmulatedScanCode*/, aExt)); |
|
619 } |
|
620 return result; |
|
621 } |
|
622 |
|
623 // ----------------------------------------------------------------------------- |
|
624 // CAknAnimKeySound::OfferRawEvent |
|
625 // ----------------------------------------------------------------------------- |
|
626 // |
|
627 TBool CAknAnimKeySound::OfferRawEvent(const TRawEvent &aRawEvent) |
|
628 { |
|
629 // Check HW and touch interaction |
|
630 if ( IsBlockedEvent ( aRawEvent ) ) |
|
631 { |
|
632 return ETrue; |
|
633 } |
|
634 |
|
635 // Check key blocking enable / disable codes: |
|
636 if ( (TAknKeySoundOpcode)( aRawEvent.Type() ) == EEnableKeyBlock ) |
|
637 { |
|
638 iEnableKeyBlock = ETrue; |
|
639 return ETrue; |
|
640 } |
|
641 if ( (TAknKeySoundOpcode)( aRawEvent.Type() ) == EDisableKeyBlock ) |
|
642 { |
|
643 iEnableKeyBlock = EFalse; |
|
644 return ETrue; |
|
645 } |
|
646 |
|
647 if (iFeatureNoPowerKey && !iPendingEvent->IsMadeUpEvent() |
|
648 && (aRawEvent.Type () == TRawEvent::EKeyDown || aRawEvent.Type () == TRawEvent::EKeyUp )) |
|
649 { |
|
650 if (aRawEvent.ScanCode() != EStdKeyDevice2) |
|
651 { |
|
652 if (aRawEvent.ScanCode() != iNoPowerKeyScanCode) // handle here so it won't fall through |
|
653 { |
|
654 iPendingEvent->Cancel(); |
|
655 } |
|
656 } |
|
657 else if (iPendingEvent->IsActive()) |
|
658 { |
|
659 if (iPendingEvent->HandleKeyReleased(aRawEvent)) |
|
660 { |
|
661 return ETrue; |
|
662 } |
|
663 // else let it just fall trough of KEF also |
|
664 } |
|
665 else |
|
666 { |
|
667 // evaluate now |
|
668 TInt action = EmulateEndKey(aRawEvent, iExt); |
|
669 |
|
670 switch(action) |
|
671 { |
|
672 case EEmulateNow: |
|
673 case EEmulateNowPhoneCallActive: |
|
674 case EEmulateNowNotificationOnTop: |
|
675 { |
|
676 TRawEvent newEvent(aRawEvent); |
|
677 newEvent.Set( aRawEvent.Type(), EStdKeyNo ); |
|
678 iFunctions->PostRawEvent(newEvent); |
|
679 |
|
680 if (action == EEmulateNow) |
|
681 { |
|
682 // Start timer for extra long key press (both keys generated). |
|
683 iPendingEvent->SetLongTimerForEvent(newEvent); |
|
684 } |
|
685 else |
|
686 { |
|
687 // No timers are set. A long power key press must not switch the phone off |
|
688 // if there is an active phone call or a notification is on top of the Idle app. |
|
689 // Only the call needs to be disconnected or notification closed. |
|
690 iPendingEvent->JustEmulateUpEvent(newEvent); |
|
691 } |
|
692 return ETrue; |
|
693 } |
|
694 case ESetEventPending: |
|
695 { |
|
696 // set short timer for down event |
|
697 iPendingEvent->SetShortTimerForEvent(aRawEvent); |
|
698 return ETrue; |
|
699 } |
|
700 default: |
|
701 break; |
|
702 } |
|
703 } |
|
704 } |
|
705 |
|
706 // If key event map is in use, then forward events. |
|
707 if ( iKeyEventMap ) |
|
708 { |
|
709 if ( iKeyEventMap->OfferRawEvent( aRawEvent, EFalse ) ) |
|
710 { |
|
711 return ETrue; |
|
712 } |
|
713 } |
|
714 else |
|
715 { |
|
716 // If key rotator is in use, then forward key events. |
|
717 // Note that key event map and key rotator cannot be in use at |
|
718 // the same time. |
|
719 if( iKeyRotator ) |
|
720 { |
|
721 if ( iKeyRotator->CheckRotation( aRawEvent, *iFunctions ) ) |
|
722 { |
|
723 return ETrue; |
|
724 } |
|
725 } |
|
726 } |
|
727 |
|
728 // If key event map is disabled, then use default approach. |
|
729 // Also, if key event map did not consume event, handle blocking here. |
|
730 // However, key sounds are handled in key event map. |
|
731 |
|
732 // Then, check the key blocking |
|
733 TBool blockEvent = EFalse; |
|
734 |
|
735 switch ( aRawEvent.Type() ) |
|
736 { |
|
737 case TRawEvent::EKeyDown: |
|
738 { |
|
739 TInt scan = aRawEvent.ScanCode() & 0xFFFF; |
|
740 if ( !NonBlockedKeyCode( scan ) |
|
741 && iKeyPressed && iEnableKeyBlock && IsBlockedKeyCode( scan ) ) |
|
742 { |
|
743 blockEvent = ETrue; |
|
744 } |
|
745 else |
|
746 { |
|
747 if ( iConnected ) // to avoid playing tones twice with KEF |
|
748 { |
|
749 iSoundSession->KeyPressed( scan ); |
|
750 } |
|
751 if ( !NonBlockedKeyCode( scan ) ) |
|
752 { |
|
753 iKeyPressed = scan; |
|
754 } |
|
755 else |
|
756 { |
|
757 iKeyPressed = 0; |
|
758 } |
|
759 } |
|
760 } |
|
761 break; |
|
762 |
|
763 case TRawEvent::EKeyRepeat: |
|
764 { |
|
765 TInt scan = aRawEvent.ScanCode() & 0xFFFF; |
|
766 if ( !NonBlockedKeyCode( scan ) && iKeyPressed != scan && |
|
767 iEnableKeyBlock && IsBlockedKeyCode( scan ) ) |
|
768 { |
|
769 // If down event is not passed forward, then |
|
770 // repeat events are not passed either. |
|
771 blockEvent = ETrue; |
|
772 } |
|
773 } |
|
774 break; |
|
775 |
|
776 case TRawEvent::EKeyUp: |
|
777 { |
|
778 TInt scan = aRawEvent.ScanCode() & 0xFFFF; |
|
779 if ( !NonBlockedKeyCode( scan ) && iKeyPressed != scan && |
|
780 iEnableKeyBlock && IsBlockedKeyCode( scan ) ) |
|
781 { |
|
782 // Do not need to block key-up events - there's not a problem |
|
783 // if there's an unexpected key-up events delivery to an app |
|
784 } |
|
785 else |
|
786 { |
|
787 iKeyPressed = 0; |
|
788 } |
|
789 } |
|
790 break; |
|
791 |
|
792 // If pointer down is received when the lights are out, |
|
793 // all pointer events are blocked until next pointer down. |
|
794 case TRawEvent::EButton1Down: |
|
795 { |
|
796 if( iBlockedPointerDown ) |
|
797 { |
|
798 iBlockedPointerDown = EFalse; |
|
799 } |
|
800 |
|
801 if( iLight && iLight->LightStatus( CHWRMLight::EPrimaryDisplay ) == CHWRMLight::ELightOff ) |
|
802 { |
|
803 blockEvent = ETrue; |
|
804 iBlockedPointerDown = ETrue; |
|
805 } |
|
806 } |
|
807 break; |
|
808 case TRawEvent::EButton1Up: |
|
809 case TRawEvent::EPointerMove: |
|
810 { |
|
811 if( iBlockedPointerDown ) |
|
812 { |
|
813 blockEvent = ETrue; |
|
814 } |
|
815 } |
|
816 break; |
|
817 |
|
818 default: |
|
819 break; |
|
820 } |
|
821 |
|
822 return blockEvent; |
|
823 } |
|
824 |
|
825 // ----------------------------------------------------------------------------- |
|
826 // CAknAnimKeySound::KefPostRawEvent |
|
827 // ----------------------------------------------------------------------------- |
|
828 // |
|
829 void CAknAnimKeySound::KefPostRawEvent(const TRawEvent& aRawEvent) const |
|
830 { |
|
831 iFunctions->PostRawEvent( aRawEvent ); |
|
832 } |
|
833 |
|
834 // ----------------------------------------------------------------------------- |
|
835 // CAknAnimKeySound::KefPostKeyEvent |
|
836 // ----------------------------------------------------------------------------- |
|
837 // |
|
838 void CAknAnimKeySound::KefPostKeyEvent(const TKeyEvent& aKeyEvent) const |
|
839 { |
|
840 iFunctions->PostKeyEvent( aKeyEvent ); |
|
841 } |
|
842 |
|
843 // ----------------------------------------------------------------------------- |
|
844 // CAknAnimKeySound::KefGenerateKeySound |
|
845 // ----------------------------------------------------------------------------- |
|
846 // |
|
847 void CAknAnimKeySound::KefGenerateKeySound( TInt aKey ) |
|
848 { |
|
849 iSoundSession->KeyPressed( aKey, EFalse ); |
|
850 } |
|
851 |
|
852 // ----------------------------------------------------------------------------- |
|
853 // CAknAnimKeySound::KefGenerateFeedback |
|
854 // ----------------------------------------------------------------------------- |
|
855 // |
|
856 void CAknAnimKeySound::KefGenerateFeedback( TUint16 aFeedback ) |
|
857 { |
|
858 if ( iFeedback ) |
|
859 { |
|
860 iFeedback->InstantFeedback( (TTouchLogicalFeedback)aFeedback ); |
|
861 } |
|
862 } |
|
863 |
|
864 // ----------------------------------------------------------------------------- |
|
865 // CAknPendingKeyEvent::NewL |
|
866 // ----------------------------------------------------------------------------- |
|
867 // |
|
868 CAknPendingKeyEvent* CAknPendingKeyEvent::NewL(MAnimGeneralFunctions* aFunctions, TInt& aEmulatedKey) |
|
869 { |
|
870 CAknPendingKeyEvent* me = new (ELeave) CAknPendingKeyEvent(aFunctions, aEmulatedKey); |
|
871 CleanupStack::PushL(me); |
|
872 me->ConstructL(); |
|
873 CleanupStack::Pop(); |
|
874 return me; |
|
875 } |
|
876 |
|
877 // ----------------------------------------------------------------------------- |
|
878 // CAknPendingKeyEvent::CAknPendingKeyEvent |
|
879 // ----------------------------------------------------------------------------- |
|
880 // |
|
881 CAknPendingKeyEvent::CAknPendingKeyEvent(MAnimGeneralFunctions* aFunctions, TInt& aEmulatedKey) |
|
882 :CTimer(CActive::EPriorityHigh),iEmulatedKey(aEmulatedKey),iFunctions(aFunctions) |
|
883 { |
|
884 CActiveScheduler::Add(this); |
|
885 } |
|
886 |
|
887 // ----------------------------------------------------------------------------- |
|
888 // CAknPendingKeyEvent::~CAknPendingKeyEvent |
|
889 // ----------------------------------------------------------------------------- |
|
890 // |
|
891 CAknPendingKeyEvent::~CAknPendingKeyEvent() |
|
892 { |
|
893 } |
|
894 |
|
895 // ----------------------------------------------------------------------------- |
|
896 // CAknPendingKeyEvent::HandleKeyReleased |
|
897 // ----------------------------------------------------------------------------- |
|
898 // |
|
899 TBool CAknPendingKeyEvent::HandleKeyReleased(const TRawEvent& /*aRawEvent*/) |
|
900 { |
|
901 TBool result(EFalse); |
|
902 TInt state = iState; |
|
903 Cancel(); |
|
904 if (state == EShort) |
|
905 { |
|
906 // generate short powerkey |
|
907 iIsMadeUpEvent = ETrue; |
|
908 iFunctions->PostRawEvent(iPendingEvent); // contains powerkey down |
|
909 iIsMadeUpEvent = EFalse; |
|
910 |
|
911 result = EFalse; // let the up event go through |
|
912 } |
|
913 else if (state == ELong) |
|
914 { |
|
915 result = ETrue; // just block the original |
|
916 } |
|
917 |
|
918 else if (state == EWaitingUpEvent) |
|
919 { |
|
920 result = ETrue; // just block the original |
|
921 } |
|
922 |
|
923 return result; |
|
924 } |
|
925 |
|
926 // ----------------------------------------------------------------------------- |
|
927 // CAknPendingKeyEvent::SetShortTimerForEvent |
|
928 // ----------------------------------------------------------------------------- |
|
929 // |
|
930 void CAknPendingKeyEvent::SetShortTimerForEvent(const TRawEvent &aRawEvent) |
|
931 { |
|
932 iPendingEvent = aRawEvent; |
|
933 After(KShortPress); |
|
934 iState = EShort; |
|
935 } |
|
936 |
|
937 // ----------------------------------------------------------------------------- |
|
938 // CAknPendingKeyEvent::SetLongTimerForEvent |
|
939 // ----------------------------------------------------------------------------- |
|
940 // |
|
941 void CAknPendingKeyEvent::SetLongTimerForEvent(const TRawEvent &aRawEvent) |
|
942 { |
|
943 iEmulatedKey = aRawEvent.ScanCode(); |
|
944 iPendingEvent = aRawEvent; |
|
945 After(KLongPress); |
|
946 iState = ELong; |
|
947 } |
|
948 |
|
949 // ----------------------------------------------------------------------------- |
|
950 // CAknPendingKeyEvent::JustEmulateUpEvent |
|
951 // ----------------------------------------------------------------------------- |
|
952 // |
|
953 void CAknPendingKeyEvent::JustEmulateUpEvent(const TRawEvent &aRawEvent) |
|
954 { |
|
955 if (!IsActive()) |
|
956 { |
|
957 iEmulatedKey = aRawEvent.ScanCode(); |
|
958 iPendingEvent = aRawEvent; |
|
959 iStatus = KRequestPending; |
|
960 SetActive(); |
|
961 iState = EWaitingUpEvent; |
|
962 } |
|
963 } |
|
964 |
|
965 // ----------------------------------------------------------------------------- |
|
966 // CAknPendingKeyEvent::RunL |
|
967 // ----------------------------------------------------------------------------- |
|
968 // |
|
969 void CAknPendingKeyEvent::RunL() |
|
970 { |
|
971 switch(iState) |
|
972 { |
|
973 case EShort: // Generate end-key and start waiting again |
|
974 { |
|
975 iEmulatedKey = EStdKeyEnd; // please note that this is not standard end-key !! |
|
976 |
|
977 iIsMadeUpEvent = ETrue; |
|
978 iPendingEvent.Set(TRawEvent::EKeyDown,iEmulatedKey); |
|
979 iFunctions->PostRawEvent(iPendingEvent); |
|
980 iIsMadeUpEvent = EFalse; |
|
981 |
|
982 After(KLongPress); |
|
983 iState = ELong; |
|
984 break; |
|
985 } |
|
986 |
|
987 case ELong: |
|
988 { |
|
989 iIsMadeUpEvent = ETrue; |
|
990 if (iEmulatedKey != EKeyNull) |
|
991 { |
|
992 iPendingEvent.Set(TRawEvent::EKeyUp,iEmulatedKey); |
|
993 iFunctions->PostRawEvent(iPendingEvent); |
|
994 iEmulatedKey = EKeyNull; |
|
995 } |
|
996 |
|
997 iPendingEvent.Set(TRawEvent::EKeyDown,EStdKeyDevice2); |
|
998 iFunctions->PostRawEvent(iPendingEvent); |
|
999 iIsMadeUpEvent = EFalse; |
|
1000 |
|
1001 iState = EBreathe; |
|
1002 break; |
|
1003 } |
|
1004 |
|
1005 default: |
|
1006 break; |
|
1007 } |
|
1008 } |
|
1009 |
|
1010 // ----------------------------------------------------------------------------- |
|
1011 // CAknPendingKeyEvent::DoCancel |
|
1012 // ----------------------------------------------------------------------------- |
|
1013 // |
|
1014 void CAknPendingKeyEvent::DoCancel() |
|
1015 { |
|
1016 if (iEmulatedKey != EKeyNull) |
|
1017 { |
|
1018 iIsMadeUpEvent = ETrue; |
|
1019 iPendingEvent.Set(TRawEvent::EKeyUp,iEmulatedKey); |
|
1020 iFunctions->PostRawEvent(iPendingEvent); |
|
1021 iEmulatedKey = EKeyNull; |
|
1022 iIsMadeUpEvent = EFalse; |
|
1023 } |
|
1024 |
|
1025 if (iState == EWaitingUpEvent) |
|
1026 { |
|
1027 TRequestStatus* sptr = &iStatus; |
|
1028 User::RequestComplete(sptr, KErrNone); |
|
1029 } |
|
1030 else |
|
1031 { |
|
1032 CTimer::DoCancel(); |
|
1033 } |
|
1034 |
|
1035 iState = EBreathe; |
|
1036 } |
|
1037 |
|
1038 // End of File |