|
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: CSysApKeyManagement implementation. |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // INCLUDE FILES |
|
20 |
|
21 #include "sysapkeymanagement.h" |
|
22 #include "SysAp.hrh" |
|
23 #include "SysApAppUi.h" |
|
24 #include <e32debug.h> |
|
25 #include <ecom/implementationinformation.h> |
|
26 #include <sysapkeyhandlerplugininterface.h> |
|
27 |
|
28 // CONSTANTS |
|
29 const TInt KCurrentSupportedPluginVersion=2; |
|
30 //text constant indicating that the plugin is non-resident, i.e. instantiated only when needed |
|
31 _LIT8(KNonResidentPlugin,"NonResidentPlugin"); |
|
32 |
|
33 // ============================ MEMBER FUNCTIONS =============================== |
|
34 |
|
35 // ---------------------------------------------------------------------------- |
|
36 // CSysApPluginInfo::CSysApPluginInfo() |
|
37 // ----------------------------------------------------------------------------- |
|
38 // |
|
39 CSysApKeyManagement::CSysApPluginInfo::CSysApPluginInfo( TUid aPluginUid ) : iPluginUid(aPluginUid), |
|
40 iPtrPlugin(NULL), |
|
41 iIsKeyProvider(EFalse) |
|
42 { |
|
43 } |
|
44 |
|
45 // ---------------------------------------------------------------------------- |
|
46 // CSysApPluginInfo::CSysApPluginInfo() |
|
47 // ----------------------------------------------------------------------------- |
|
48 // |
|
49 CSysApKeyManagement::CSysApPluginInfo::~CSysApPluginInfo() |
|
50 { |
|
51 delete iPtrPlugin; |
|
52 iKeys.Close(); |
|
53 iKeyHandles.Close(); |
|
54 iUpAndDownKeyHandles.Close(); |
|
55 } |
|
56 |
|
57 // ---------------------------------------------------------------------------- |
|
58 // CSysApKeyManagement::CSysApKeyManagement() |
|
59 // C++ default constructor can NOT contain any code, that |
|
60 // might leave. |
|
61 // ---------------------------------------------------------------------------- |
|
62 |
|
63 CSysApKeyManagement::CSysApKeyManagement( RWindowGroup& aRootWindowGroup, MSysapCallback& aSysApCallback ): |
|
64 iRootWindowGroup(aRootWindowGroup), |
|
65 iSysApCallback(aSysApCallback) |
|
66 { |
|
67 TRACES( RDebug::Print( _L("CSysApKeyManagement::CSysApKeyManagement")) ); |
|
68 } |
|
69 |
|
70 // ---------------------------------------------------------------------------- |
|
71 // CSysApKeyManagement::ConstructL() |
|
72 // Symbian 2nd phase constructor can leave. |
|
73 // ----------------------------------------------------------------------------- |
|
74 // |
|
75 |
|
76 void CSysApKeyManagement::ConstructL() |
|
77 { |
|
78 TRACES( RDebug::Print( _L("CSysApKeyManagement::ConstructL")) ); |
|
79 GetPluginsL(); //gets info for all available plugins |
|
80 CaptureKeys(); //registers to capture all needed keys |
|
81 } |
|
82 |
|
83 |
|
84 // ---------------------------------------------------------------------------- |
|
85 // CSysApKeyManagement::NewL() |
|
86 // Two-phased constructor. |
|
87 // ----------------------------------------------------------------------------- |
|
88 // |
|
89 |
|
90 CSysApKeyManagement* CSysApKeyManagement::NewL( RWindowGroup& aRootWindowGroup, MSysapCallback& aSysApCallback ) |
|
91 { |
|
92 TRACES( RDebug::Print( _L("CSysApKeyManagement::NewL" ) ) ); |
|
93 CSysApKeyManagement* self = new ( ELeave ) CSysApKeyManagement( aRootWindowGroup, aSysApCallback ); |
|
94 CleanupStack::PushL( self ); |
|
95 self->ConstructL(); |
|
96 CleanupStack::Pop(self); //self |
|
97 return self; |
|
98 } |
|
99 |
|
100 |
|
101 // ---------------------------------------------------------------------------- |
|
102 // CSysApKeyManagement::~CSysApKeyManagement() |
|
103 // ---------------------------------------------------------------------------- |
|
104 // |
|
105 CSysApKeyManagement::~CSysApKeyManagement() |
|
106 { |
|
107 TRACES( RDebug::Print( _L("CSysApKeyManagement::~CSysApKeyManagement")) ); |
|
108 |
|
109 CancelCaptureKeys(); //first cancel the capturing of the keys |
|
110 |
|
111 iSysApPlugins.ResetAndDestroy(); |
|
112 } |
|
113 |
|
114 |
|
115 // ---------------------------------------------------------------------------- |
|
116 // CSysApKeyManagement::CancelCaptureKeys() |
|
117 // ---------------------------------------------------------------------------- |
|
118 // |
|
119 void CSysApKeyManagement::CancelCaptureKeys() |
|
120 { |
|
121 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys")) ); |
|
122 |
|
123 // iterate through plugins and cancel key capture |
|
124 for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- ) |
|
125 { |
|
126 CSysApPluginInfo* info = iSysApPlugins[pluginCounter]; |
|
127 |
|
128 for ( TInt keyHandleCounter = info->iKeyHandles.Count()-1; keyHandleCounter >= 0; keyHandleCounter-- ) |
|
129 { |
|
130 iRootWindowGroup.CancelCaptureKey( info->iKeyHandles[keyHandleCounter] ); |
|
131 } |
|
132 |
|
133 for ( TInt upAndDownKeyHandleCounter = info->iUpAndDownKeyHandles.Count()-1; upAndDownKeyHandleCounter >= 0; upAndDownKeyHandleCounter-- ) |
|
134 { |
|
135 iRootWindowGroup.CancelCaptureKeyUpAndDowns( info->iUpAndDownKeyHandles[upAndDownKeyHandleCounter] ); |
|
136 } |
|
137 } |
|
138 } |
|
139 |
|
140 |
|
141 // ---------------------------------------------------------------------------- |
|
142 // CSysApKeyManagement::CaptureKeys() |
|
143 // registers to window server for the keys we want. Callback is in SysappUi |
|
144 // ---------------------------------------------------------------------------- |
|
145 |
|
146 void CSysApKeyManagement::CaptureKeys() |
|
147 { |
|
148 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys")) ); |
|
149 |
|
150 for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- ) |
|
151 { |
|
152 CSysApPluginInfo* info = iSysApPlugins[pluginCounter]; |
|
153 |
|
154 for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- ) |
|
155 { |
|
156 TUint captureKey = info->iKeys[keyCounter].iCode; |
|
157 |
|
158 // Special handling for flip key simulation |
|
159 if ( captureKey == EKeyFlipOpen || captureKey == EKeyFlipClose ) |
|
160 { |
|
161 // don't capture flip, it is simulated to plugins from P&S |
|
162 continue; |
|
163 } |
|
164 |
|
165 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: capturing key 0x%x for plugin 0x%x"), |
|
166 captureKey, info->iPluginUid ) ); |
|
167 if (info->iIsKeyProvider) |
|
168 { |
|
169 TInt captureUpDownKey = info->iKeys[keyCounter].iScanCode; |
|
170 TUint modifiers = info->iKeys[keyCounter].iModifiers; |
|
171 |
|
172 TInt32 keyHandle = iRootWindowGroup.CaptureKey( captureKey, modifiers, modifiers ); |
|
173 |
|
174 if ( keyHandle < KErrNone ) |
|
175 { |
|
176 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: error %d"), keyHandle ) ); |
|
177 continue; // other keys may be possible to capture, so continue |
|
178 } |
|
179 |
|
180 if ( ( keyHandle = info->iKeyHandles.Append( keyHandle ) ) != KErrNone ) //store handle for CancelCaptureKey |
|
181 { |
|
182 //error of Append ignored, key will not be cancelled. We can live with that. |
|
183 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: Append failed, error %d"), keyHandle ) ); |
|
184 } |
|
185 |
|
186 TInt32 upAndDownKeyHandle = iRootWindowGroup.CaptureKeyUpAndDowns( captureUpDownKey, modifiers, modifiers ); |
|
187 |
|
188 if ( upAndDownKeyHandle < KErrNone ) |
|
189 { |
|
190 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys UpAndDowns: error %d"), upAndDownKeyHandle ) ); |
|
191 continue; // other keys may be possible to capture, so continue |
|
192 } |
|
193 |
|
194 if ( ( upAndDownKeyHandle = info->iUpAndDownKeyHandles.Append( upAndDownKeyHandle ) ) != KErrNone ) //store handle for CancelCaptureKeyUpAndDowns |
|
195 { |
|
196 //error of Append ignored, key will not be cancelled. We can live with that. |
|
197 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys UpAndDowns: Append failed, error %d"), upAndDownKeyHandle ) ); |
|
198 } |
|
199 } |
|
200 else |
|
201 { |
|
202 TInt32 handle = iRootWindowGroup.CaptureKey( captureKey, 0, 0 ); |
|
203 |
|
204 if ( handle < KErrNone ) |
|
205 { |
|
206 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: error %d"), handle ) ); |
|
207 continue; // other keys may be possible to capture, so continue |
|
208 } |
|
209 |
|
210 if ( ( handle = info->iKeyHandles.Append( handle ) ) != KErrNone ) //store handle for CancelCaptureKey |
|
211 { |
|
212 //error of Append ignored, key will not be cancelled. We can live with that. |
|
213 TRACES( RDebug::Print( _L("CSysApKeyManagement::CaptureKeys: Append failed, error %d"), handle ) ); |
|
214 } |
|
215 } |
|
216 } |
|
217 } |
|
218 } |
|
219 |
|
220 // ---------------------------------------------------------------------------- |
|
221 // CSysApKeyManagement::GetPluginsL() |
|
222 // Gets plugins and extracts key and plugin information form them |
|
223 // ---------------------------------------------------------------------------- |
|
224 |
|
225 void CSysApKeyManagement::GetPluginsL() |
|
226 { |
|
227 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL")) ); |
|
228 //lists all plugins implementing interface identified with SysapPluginUID |
|
229 |
|
230 RImplInfoPtrArray pluginInfoArray; |
|
231 |
|
232 CleanupClosePushL( pluginInfoArray ); |
|
233 |
|
234 REComSession::ListImplementationsL( KSysapKeyHandlerPluginInterfaceUid, |
|
235 pluginInfoArray ); |
|
236 |
|
237 TInt count = pluginInfoArray.Count(); |
|
238 |
|
239 for ( TInt index = 0; index < count; ++index) |
|
240 { |
|
241 //extract key from data of plugin |
|
242 CImplementationInformation* info = pluginInfoArray[index]; |
|
243 |
|
244 TInt version = info->Version(); |
|
245 |
|
246 if ( version > KCurrentSupportedPluginVersion ) |
|
247 { |
|
248 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, version conflict: version=%d"), info->ImplementationUid(), version ) ); |
|
249 continue; |
|
250 } |
|
251 |
|
252 CSysApPluginInfo* pluginInfo = new (ELeave) CSysApPluginInfo( info->ImplementationUid() ); |
|
253 CleanupStack::PushL( pluginInfo ); |
|
254 |
|
255 if ( info->OpaqueData().Compare( KNonResidentPlugin ) == 0 ) //plugin tells itself in opaquedata that if it shall be resident |
|
256 { |
|
257 // do nothing for non-resident plugins |
|
258 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x is non-resident."), pluginInfo->iPluginUid ) ); |
|
259 } |
|
260 else |
|
261 { |
|
262 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: loading resident plugin 0x%x"), pluginInfo->iPluginUid ) ); |
|
263 pluginInfo->iPtrPlugin = CSysapKeyHandlerPlugin::NewL( pluginInfo->iPluginUid, &iSysApCallback ); |
|
264 if ( version > 1 ) |
|
265 { |
|
266 //plugin is a key provider plugin (plugin version 2) |
|
267 pluginInfo->iIsKeyProvider = ETrue; |
|
268 } |
|
269 } |
|
270 |
|
271 TInt err = KErrNone; |
|
272 if (pluginInfo->iIsKeyProvider) |
|
273 { |
|
274 TRAP(err, pluginInfo->iPtrPlugin->ProvideKeyEventsL(pluginInfo->iKeys)); |
|
275 if (err == KErrNone) |
|
276 { |
|
277 err = CheckKeys(pluginInfo->iKeys); |
|
278 } |
|
279 } |
|
280 else |
|
281 { |
|
282 const TDesC8& data = info->DataType(); |
|
283 TLex8 lex(data); //convert data to TUint. We suppose that there is one TUint in the data |
|
284 err = GetKeys( lex, pluginInfo->iKeys ); |
|
285 } |
|
286 |
|
287 if ( err != KErrNone ) //plugin has no valid keys |
|
288 { |
|
289 if( err == KErrAbort ) //this means that there was some error in the key definitions, which makes the plugin useless, |
|
290 { |
|
291 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, err=%d. Probably error in key definitons."), pluginInfo->iPluginUid, err ) ); |
|
292 CleanupStack::PopAndDestroy( pluginInfo ); |
|
293 continue; //just ignore this plugin |
|
294 } |
|
295 else |
|
296 { |
|
297 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x load failure, err=%d.Leaving..."), pluginInfo->iPluginUid, err ) ); |
|
298 User::Leave( err ); |
|
299 } |
|
300 } |
|
301 |
|
302 //append to array of plugins |
|
303 err = iSysApPlugins.Append( pluginInfo ); |
|
304 |
|
305 if ( err != KErrNone ) //error in append |
|
306 { |
|
307 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: resident plugin 0x%x load failure, err=%d"), pluginInfo->iPluginUid, err ) ); |
|
308 CleanupStack::PopAndDestroy( pluginInfo ); //this deletes also ptrPlugin |
|
309 break; //probably no more plugins can be read |
|
310 } |
|
311 |
|
312 TRACES( RDebug::Print( _L("CSysApKeyManagement::GetPluginsL: plugin 0x%x succesfully loaded."), pluginInfo->iPluginUid ) ); |
|
313 |
|
314 CleanupStack::Pop( pluginInfo ); |
|
315 } |
|
316 |
|
317 pluginInfoArray.Close(); |
|
318 |
|
319 CleanupStack::Pop( &pluginInfoArray ); |
|
320 } |
|
321 |
|
322 // ---------------------------------------------------------------------------- |
|
323 // CSysApKeyManagement::HandleKeyEventL() |
|
324 // Handles key events. SysAppUi calls this function |
|
325 // ---------------------------------------------------------------------------- |
|
326 |
|
327 TKeyResponse CSysApKeyManagement::HandleKeyEventL(const TKeyEvent& aKeyEvent, TEventCode aType ) |
|
328 { |
|
329 TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL")) ); |
|
330 |
|
331 TKeyResponse response(EKeyWasNotConsumed); //not consumed by default |
|
332 |
|
333 for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- ) |
|
334 { |
|
335 CSysApPluginInfo* info = iSysApPlugins[pluginCounter]; |
|
336 |
|
337 for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- ) |
|
338 { |
|
339 if (aType == EEventKey) |
|
340 { |
|
341 if ( info->iKeys[keyCounter].iCode == aKeyEvent.iCode ) |
|
342 { |
|
343 // a plug-in, don't continue |
|
344 TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL: offering key=%d to plugin 0x%x"), |
|
345 aKeyEvent.iCode, info->iPluginUid ) ); |
|
346 |
|
347 if ( info->iPtrPlugin ) |
|
348 { |
|
349 response = info->iPtrPlugin->HandleKeyEventL( aKeyEvent, aType ); |
|
350 } |
|
351 else // non-resident plug-in, needs to be loaded |
|
352 { |
|
353 TUid pluginuid(info->iPluginUid); //gets plugin info for this key |
|
354 CSysapKeyHandlerPlugin* plugin = CSysapKeyHandlerPlugin::NewL( pluginuid, &iSysApCallback ); //instantiates plugin |
|
355 CleanupStack::PushL( plugin ); |
|
356 response = plugin->HandleKeyEventL( aKeyEvent, aType ); |
|
357 CleanupStack::PopAndDestroy( plugin ); |
|
358 } |
|
359 |
|
360 // only one plugin is allowed to capture a key event, so there is no sense to continue looping regardless |
|
361 // whether key has been consumed or not |
|
362 return response; |
|
363 } |
|
364 } |
|
365 else if (info->iIsKeyProvider && (aType == EEventKeyUp || aType == EEventKeyDown)) |
|
366 { |
|
367 if ( info->iKeys[keyCounter].iScanCode == aKeyEvent.iScanCode ) |
|
368 { |
|
369 // a plug-in, don't continue |
|
370 TRACES( RDebug::Print( _L("CSysApKeyManagement::HandleKeyEventL: offering up or down key scancode =%d to plugin 0x%x"), |
|
371 aKeyEvent.iScanCode, info->iPluginUid ) ); |
|
372 //key provider plugins are always resident |
|
373 return info->iPtrPlugin->HandleKeyEventL( aKeyEvent, aType ); |
|
374 } |
|
375 } |
|
376 else |
|
377 { |
|
378 continue; |
|
379 } |
|
380 } |
|
381 } |
|
382 return response; |
|
383 } |
|
384 |
|
385 // ---------------------------------------------------------------------------- |
|
386 // CSysApKeyManagement::FindKeyCode() |
|
387 // Helper function for finding a key in plugins. |
|
388 // ---------------------------------------------------------------------------- |
|
389 |
|
390 TInt CSysApKeyManagement::FindKeyCode( TUint aKeycode ) |
|
391 { |
|
392 for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- ) |
|
393 { |
|
394 CSysApPluginInfo* info = iSysApPlugins[pluginCounter]; |
|
395 |
|
396 for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- ) |
|
397 { |
|
398 if ( info->iKeys[keyCounter].iCode == aKeycode ) |
|
399 { |
|
400 return keyCounter; |
|
401 } |
|
402 } |
|
403 } |
|
404 |
|
405 return KErrNotFound; |
|
406 } |
|
407 |
|
408 // ---------------------------------------------------------------------------- |
|
409 // CSysApKeyManagement::FindScanCode() |
|
410 // Helper function for finding a key scancode in plugins. |
|
411 // ---------------------------------------------------------------------------- |
|
412 |
|
413 TInt CSysApKeyManagement::FindScanCode( TInt aScanCode ) |
|
414 { |
|
415 for ( TInt pluginCounter = iSysApPlugins.Count()-1; pluginCounter >= 0; pluginCounter-- ) |
|
416 { |
|
417 CSysApPluginInfo* info = iSysApPlugins[pluginCounter]; |
|
418 |
|
419 for ( TInt keyCounter = info->iKeys.Count()-1; keyCounter >= 0; keyCounter-- ) |
|
420 { |
|
421 if ( info->iKeys[keyCounter].iScanCode == aScanCode ) |
|
422 { |
|
423 return keyCounter; |
|
424 } |
|
425 } |
|
426 } |
|
427 |
|
428 return KErrNotFound; |
|
429 } |
|
430 |
|
431 |
|
432 // ---------------------------------------------------------------------------- |
|
433 // CSysApKeyManagement::GetKeys() |
|
434 // Helper function for getting the keys supported by plugins |
|
435 // ---------------------------------------------------------------------------- |
|
436 |
|
437 TInt CSysApKeyManagement::GetKeys( TLex8& aLex, RArray<TKeyEvent>& aKeys ) |
|
438 { |
|
439 aLex.SkipSpace(); |
|
440 |
|
441 TUint thiskey; |
|
442 TInt err = aLex.Val( thiskey ); |
|
443 |
|
444 if ( err != KErrNone ) //there must be at least one number |
|
445 { |
|
446 return KErrAbort; |
|
447 } |
|
448 |
|
449 while ( err == KErrNone ) //while we have a new key |
|
450 { |
|
451 if ( FindKeyCode( thiskey ) == KErrNotFound ) // keys not to be duplicated |
|
452 { |
|
453 TKeyEvent event; |
|
454 //other values in event not initialized, but |
|
455 //they are not used anyway |
|
456 event.iCode = thiskey; |
|
457 err = aKeys.Append( event ); //append to keys. |
|
458 |
|
459 if ( err != KErrNone ) |
|
460 { |
|
461 return err; |
|
462 } |
|
463 } |
|
464 |
|
465 aLex.SkipSpace(); |
|
466 |
|
467 err = aLex.Val( thiskey ); //get next new key |
|
468 } |
|
469 |
|
470 if ( aKeys.Count() == 0 ) //no valid keys |
|
471 { |
|
472 return KErrAbort; |
|
473 } |
|
474 |
|
475 return KErrNone; |
|
476 } |
|
477 |
|
478 // ---------------------------------------------------------------------------- |
|
479 // CSysApKeyManagement::CheckKeys() |
|
480 // Helper function for checking plugin keys |
|
481 // ---------------------------------------------------------------------------- |
|
482 |
|
483 TInt CSysApKeyManagement::CheckKeys(RArray<TKeyEvent>& aKeys ) |
|
484 { |
|
485 for ( TInt keyCounter = aKeys.Count()-1; keyCounter >= 0; keyCounter-- ) |
|
486 { |
|
487 if ( FindKeyCode(aKeys[keyCounter].iCode) != KErrNotFound ) |
|
488 { |
|
489 aKeys.Remove(keyCounter); |
|
490 } |
|
491 } |
|
492 //check scancodes also just to be sure |
|
493 //no duplicates should be found is TKeyEvents are properly constructed |
|
494 for ( TInt keyCounter = aKeys.Count()-1; keyCounter >= 0; keyCounter-- ) |
|
495 { |
|
496 if ( FindScanCode(aKeys[keyCounter].iScanCode) != KErrNotFound ) |
|
497 { |
|
498 aKeys.Remove(keyCounter); |
|
499 } |
|
500 } |
|
501 if ( aKeys.Count() ) |
|
502 { |
|
503 return KErrNone; |
|
504 } |
|
505 return KErrAbort; |
|
506 } |
|
507 |
|
508 // End of File |
|
509 |