|
1 /* |
|
2 * Copyright (c) 1999 - 2003 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: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 #include <coecntrl.h> |
|
20 #include <coeccntx.h> |
|
21 #include <coecobs.h> |
|
22 #include <apgwgnam.h> |
|
23 #include <coemain.h> |
|
24 #include <eikenv.h> |
|
25 #include <eikappui.h> |
|
26 #include <apgtask.h> |
|
27 #include <bautils.h> |
|
28 #include <s32stor.h> |
|
29 #include <s32file.h> |
|
30 #include <e32property.h> |
|
31 #include <centralrepository.h> |
|
32 #include <settingsinternalcrkeys.h> |
|
33 #include <ScreensaverInternalPSKeys.h> // to work with screensaver |
|
34 #include <gfxtranseffect/gfxtranseffect.h> // For transition effects |
|
35 #include <akntranseffect.h> // For transition effects |
|
36 // |
|
37 #include "lcdui.h" |
|
38 #include "lcdgr.h" |
|
39 #include "mevents.h" |
|
40 #include "jutils.h" |
|
41 #include "MIDUtils.h" |
|
42 #include "CJavaEventServer.h" |
|
43 #include "CMIDToolkit.h" |
|
44 #include "CMIDEvent.h" |
|
45 #include "CMIDBuffer.h" |
|
46 #include "CMIDNotify.h" |
|
47 #include <stdio.h> |
|
48 #include "LcduiThread.h" |
|
49 |
|
50 #include "coreuiavkonlcdui.h" |
|
51 #include "coreuiappui.h" |
|
52 |
|
53 #include "MMIDCanvasGraphicsItemPainter.h" |
|
54 |
|
55 #include <jdebug.h> |
|
56 #ifdef LCDUI_DEBUG_ON |
|
57 #define LCDUI_DEBUG(msg) DEBUG(msg) |
|
58 #define LCDUI_DEBUG_INT(msg, x) DEBUG_INT(msg, x) |
|
59 #else |
|
60 #define LCDUI_DEBUG(msg) |
|
61 #define LCDUI_DEBUG_INT(msg, x) |
|
62 #endif |
|
63 |
|
64 /** |
|
65 * Macro controlling synthesis of AppArc foreground event when the |
|
66 * MIdlet requests that the Display be brought to the foreground. |
|
67 * |
|
68 * Some UI's may require this event, others may not. |
|
69 * |
|
70 * Generation of this event should be moved to the plugin. |
|
71 */ |
|
72 #define GENERATE_APPARC_FOREGROUND_EVENT 1 |
|
73 |
|
74 /** |
|
75 * Macro controlling whether the tasklist entry is cleared early in |
|
76 * CMIDToolkit::Close() or left in place until the window group is |
|
77 * destroyed (when the eikonenv is destroyed). |
|
78 * |
|
79 */ |
|
80 #define CLEAR_TASKLIST_IN_CLOSE 1 |
|
81 |
|
82 /** |
|
83 * Macro extracting the weak reference corresponding to a component. |
|
84 */ |
|
85 #define MIDJOBJECT(component) ( reinterpret_cast<jobject>((component)->iPeer) ) |
|
86 |
|
87 /** |
|
88 * Graphics plugin library name. |
|
89 */ |
|
90 _LIT(KGrLibName,"lcdgr"); |
|
91 |
|
92 /** |
|
93 * Window group ordinal position (z-order) for sending to background. |
|
94 */ |
|
95 const TInt KWgOrdinalBackground = -1; |
|
96 |
|
97 /** |
|
98 * Window group ordinal position (z-order) for bringing to foreground. |
|
99 */ |
|
100 const TInt KWgOrdinalForeground = 0; |
|
101 |
|
102 |
|
103 /** |
|
104 * This timeout (microseconds) defines how long we prevent MIDlet from becoming |
|
105 * back to foregound after user has switched it to background. |
|
106 * Some MIDlets change the current displayable in hideNotify(), which (without this prevention) |
|
107 * would cause them to become back to foreground immediately. |
|
108 */ |
|
109 const TInt KChangingToBackgroundTimeout = 5000000; |
|
110 |
|
111 |
|
112 /** |
|
113 * LCDGR graphics plugin factory function. |
|
114 */ |
|
115 typedef MMIDGraphicsFactory*(*TCreateGraphicsFactoryFunc)(RFs&, TDisplayMode); |
|
116 |
|
117 |
|
118 /** |
|
119 * Exception safe reversion to previous displayable if CMIDToolkit::SetCurrentL fails. |
|
120 * |
|
121 */ |
|
122 class TRevertCurrent |
|
123 { |
|
124 public: |
|
125 TRevertCurrent(MMIDDisplayable*& aCurrentPointer) |
|
126 : iCurrentPointer(aCurrentPointer) |
|
127 , iPrevious(aCurrentPointer) |
|
128 { |
|
129 } |
|
130 static void Revert(TAny*); |
|
131 |
|
132 private: |
|
133 MMIDDisplayable*& iCurrentPointer; |
|
134 MMIDDisplayable* iPrevious; |
|
135 }; |
|
136 |
|
137 /** |
|
138 * process entries on finalize queue. |
|
139 */ |
|
140 class CMIDFinalizeEvent : public CJavaEvent<CMIDToolkit> |
|
141 { |
|
142 private: |
|
143 void Dispatch(JNIEnv& aJni); |
|
144 }; |
|
145 |
|
146 |
|
147 const static TInt KPayload = 16; // Number of weak references on queue before dispose event |
|
148 |
|
149 /** |
|
150 * Register an MMIDComponent and its peer with the Toolkit. |
|
151 * |
|
152 *@return an object handle. |
|
153 */ |
|
154 TInt CMIDToolkit::RegisterComponentL(MMIDComponent* aComponent, TJavaPeer aPeer) |
|
155 { |
|
156 ASSERT(aComponent); |
|
157 TObjectEntry* entry = new(ELeave) TObjectEntry(aComponent); |
|
158 CleanupStack::PushL(entry); |
|
159 User::LeaveIfError(iObjects.Append(entry)); |
|
160 CleanupStack::Pop(entry); |
|
161 aComponent->iPeer = aPeer; |
|
162 return MIDHandle(aComponent); |
|
163 } |
|
164 |
|
165 /** |
|
166 * CONSTRUCTION PHASE 1 . Java side. |
|
167 */ |
|
168 CMIDToolkit::CMIDToolkit() |
|
169 : iPhase(EPhase1) |
|
170 , iOldFullScreenDisplayable(NULL), iObjects(EGranularity), iSentToBgTime(0), mFirst(ETrue) |
|
171 { |
|
172 LCDUI_DEBUG_INT("CMIDToolkit::CMIDToolkit(%d) CONSTRUCTION PHASE 1", (TInt)this); |
|
173 iFinalizeMutex.CreateLocal(); |
|
174 } |
|
175 |
|
176 /** |
|
177 * DESTRUCTION PHASE 1 . Java side |
|
178 */ |
|
179 CMIDToolkit::~CMIDToolkit() |
|
180 { |
|
181 LCDUI_DEBUG_INT("CMIDToolkit::~CMIDToolkit(%d): DESTRUCTION PHASE 1 <BEGIN>", (TInt)this); |
|
182 ASSERT(iPhase == EPhase1); |
|
183 |
|
184 iFinalizeMutex.Close(); |
|
185 iObjects.Close(); |
|
186 |
|
187 // |
|
188 // We cannot delete any server side objects in the |
|
189 // destructor since it runs Java side. Therefore if |
|
190 // any of the following invariants fail, we have |
|
191 // leaked or failed to zero the pointer. |
|
192 // |
|
193 |
|
194 ASSERT(0 == iObjects.Count()); |
|
195 ASSERT(NULL == iDisposedQueue); |
|
196 ASSERT(0 == iDisposedCount); |
|
197 ASSERT(NULL == iFinalizeQueue); |
|
198 ASSERT(NULL == iFinalizeCount); |
|
199 |
|
200 // Not owned but worth checking we clean everything. |
|
201 ASSERT(NULL == iCoeEnv); |
|
202 |
|
203 // Owned - if these are non-null we leaked. |
|
204 ASSERT(NULL == iWgName); |
|
205 ASSERT(NULL == iHomeDir); |
|
206 ASSERT(NULL == iEnv); |
|
207 ASSERT(NULL == iMidletSuite); |
|
208 ASSERT(NULL == iUtils); |
|
209 ASSERT(NULL == iUiFactory); |
|
210 ASSERT(NULL == iGrFactory); |
|
211 |
|
212 ASSERT(0 == iGrLibrary.Handle()); // Did we unload the gr library |
|
213 ASSERT(NULL == iCurrentDisplayable); // Did we clean up correctly |
|
214 |
|
215 LCDUI_DEBUG_INT("CMIDToolkit::~CMIDToolkit(%d): DESTRUCTION PHASE 1 <END>", (TInt)this); |
|
216 } |
|
217 |
|
218 void CMIDToolkit::HandleExitL() |
|
219 { |
|
220 PostDisplayEvent(EExit); |
|
221 } |
|
222 |
|
223 |
|
224 void CMIDToolkit::HandleForegroundL(TBool aForeground) |
|
225 { |
|
226 if (aForeground) |
|
227 { |
|
228 // reset flag |
|
229 iMidletRequestedBg = EFalse; |
|
230 iSentToBgTime = 0; |
|
231 LCDUI_DEBUG("**FE**"); |
|
232 } |
|
233 else |
|
234 { |
|
235 iSentToBgTime.HomeTime(); |
|
236 LCDUI_DEBUG("**BE**"); |
|
237 } |
|
238 iEnv->HandleForegroundL(aForeground); |
|
239 PostDisplayEvent(aForeground?EForeground:EBackground); |
|
240 } |
|
241 |
|
242 void CMIDToolkit::HandleResourceChangeL(TInt aType) |
|
243 { |
|
244 iEnv->HandleResourceChangeL(aType); |
|
245 } |
|
246 |
|
247 void CMIDToolkit::HandleSwitchOnEventL() |
|
248 { |
|
249 iEnv->HandleSwitchOnL(ETrue); |
|
250 } |
|
251 |
|
252 #ifdef RD_JAVA_NGA_ENABLED |
|
253 void CMIDToolkit::HandleFullOrPartialForegroundL(TBool aFullOrPartialFg) |
|
254 { |
|
255 iEnv->HandleFullOrPartialForegroundL(aFullOrPartialFg); |
|
256 } |
|
257 |
|
258 void CMIDToolkit::HandleFreeGraphicsMemory() |
|
259 { |
|
260 iEnv->HandleFreeGraphicsMemory(); |
|
261 } |
|
262 #endif |
|
263 |
|
264 /** |
|
265 * CONSTRUCTION PHASE 2. |
|
266 * Java Side. |
|
267 */ |
|
268 void CMIDToolkit::ConstructL |
|
269 ( |
|
270 JNIEnv& aJni, |
|
271 jobject aPeer, |
|
272 TJavaEventServer aServer, |
|
273 const TDesC& aAppName, |
|
274 TInt aAppUid, |
|
275 const TDesC& aAppHome, |
|
276 RPointerArray<HBufC>* aAttributes |
|
277 ) |
|
278 { |
|
279 LCDUI_DEBUG_INT("CMIDToolkit::ConstructL(%x) CONSTRUCTION PHASE 2 ", (TInt)this); |
|
280 ASSERT(iPhase == EPhase1); |
|
281 iPhase = EPhase2; |
|
282 |
|
283 CJavaEventSourceBase::ConstructL(aJni,aPeer,aServer); |
|
284 |
|
285 jclass clz = aJni.GetObjectClass(aPeer); |
|
286 iHandleItemEvent = aJni.GetMethodID(clz, "handleItemEvent", "(Ljavax/microedition/lcdui/Item;IIII)V"); |
|
287 iHandleDisplayableEvent = aJni.GetMethodID(clz, "handleDisplayableEvent", "(Ljavax/microedition/lcdui/Displayable;IIII)V"); |
|
288 iHandleDisplayEvent = aJni.GetMethodID(clz, "handleDisplayEvent", "(Ljavax/microedition/lcdui/Toolkit;IIII)V"); |
|
289 iHandleNotifyMethod = aJni.GetMethodID(clz, "handleAsyncEvent", "(Ljava/lang/Object;I)V"); |
|
290 iHandleCanavsGraphicsItemPainterEvent = aJni.GetMethodID( |
|
291 clz, |
|
292 "handleCanvasGraphicsItemPainterEvent", |
|
293 "(Ljavax/microedition/lcdui/CanvasGraphicsItemPainter;IIII)V"); |
|
294 |
|
295 aJni.DeleteLocalRef(clz); |
|
296 |
|
297 if (0 == iHandleNotifyMethod || |
|
298 0 == iHandleDisplayEvent || |
|
299 0 == iHandleDisplayableEvent || |
|
300 0 == iHandleItemEvent |
|
301 ) |
|
302 { |
|
303 User::Leave(KErrGeneral); |
|
304 } |
|
305 |
|
306 iHomeDir=aAppHome.AllocL(); |
|
307 iAppUid=TUid::Uid(aAppUid); |
|
308 |
|
309 iMidletSuite = new(ELeave) CMIDletSuite; |
|
310 if (aAttributes) |
|
311 { |
|
312 iMidletSuite->SetAttributesL(*aAttributes); |
|
313 } |
|
314 |
|
315 CMIDToolkit* toolkit = this; |
|
316 const TDesC* appName = &aAppName; |
|
317 |
|
318 TInt err = ExecuteTrap(&CMIDToolkit::InvokeSvrConstructL, toolkit, appName); |
|
319 User::LeaveIfError(err); |
|
320 } |
|
321 |
|
322 void CMIDToolkit::InvokeSvrConstructL(CMIDToolkit* aToolkit, const TDesC* aName) |
|
323 { |
|
324 User::LeaveIfError(RLcdui::Get()->CreateAppUi()); |
|
325 |
|
326 aToolkit->SvrConstructL(*aName); |
|
327 } |
|
328 |
|
329 |
|
330 /** |
|
331 * CONSTRUCTION PHASE 3. |
|
332 * Server Side. |
|
333 */ |
|
334 void CMIDToolkit::SvrConstructL(const TDesC& aAppName) |
|
335 { |
|
336 LCDUI_DEBUG_INT("CMIDToolkit::SvrConstructL(%x) CONSTRUCTION PHASE 3", (TInt)this); |
|
337 ASSERT(iPhase == EPhase2); |
|
338 iPhase = EPhase3; // fully constructed |
|
339 |
|
340 // |
|
341 // This is the first method called server side, so the first place |
|
342 // we can safely obtain these pointers. |
|
343 // |
|
344 iCoeEnv = CCoeEnv::Static(); |
|
345 |
|
346 iEnv = new(ELeave) CMIDEnv(this, TSize()); |
|
347 iEnv->ConstructL(); |
|
348 |
|
349 CreateTaskListEntryL(aAppName); |
|
350 SetTaskListEntry(EFalse); |
|
351 |
|
352 // |
|
353 // |
|
354 // |
|
355 LoadLibrariesL(); |
|
356 } |
|
357 |
|
358 void CMIDToolkit::CreateTaskListEntryL(const TDesC& aAppName) |
|
359 { |
|
360 ASSERT(NULL == iWgName); |
|
361 iWgName = java::ui::CoreUiAvkonLcdui::getInstance().getWindowGroupName(); |
|
362 iWgName->SetRespondsToSwitchFilesEvent(EFalse); |
|
363 iWgName->SetCaptionL(aAppName); |
|
364 } |
|
365 |
|
366 void CMIDToolkit::LoadLibrariesL() |
|
367 { |
|
368 ASSERT(NULL == iGrFactory); |
|
369 ASSERT(NULL == iUiFactory); |
|
370 |
|
371 RFs& fs = iCoeEnv->FsSession(); |
|
372 TDisplayMode screenMode=iCoeEnv->ScreenDevice()->DisplayMode(); |
|
373 #ifdef RD_JAVA_S60_RELEASE_9_2 |
|
374 if (screenMode == EColor16MAP) |
|
375 { |
|
376 screenMode = EColor16MA; |
|
377 } |
|
378 #endif |
|
379 |
|
380 // |
|
381 // Load the GR dll |
|
382 // |
|
383 User::LeaveIfError(iGrLibrary.Load(KGrLibName)); |
|
384 TCreateGraphicsFactoryFunc CreateGraphicsFactoryL; |
|
385 CreateGraphicsFactoryL = (TCreateGraphicsFactoryFunc)iGrLibrary.Lookup(1); |
|
386 if (!CreateGraphicsFactoryL) |
|
387 { |
|
388 User::Leave(KErrBadLibraryEntryPoint); |
|
389 } |
|
390 iGrFactory = (*CreateGraphicsFactoryL)(fs, screenMode); |
|
391 |
|
392 MLcduiPlugin* plugin = RLcdui::Get()->Plugin(); |
|
393 if (!plugin) |
|
394 { |
|
395 User::Leave(KErrGeneral); |
|
396 } |
|
397 |
|
398 iUiFactory = plugin->CreateComponentFactoryL(); |
|
399 iUiFactory->ConstructL(*iEnv); |
|
400 |
|
401 iUtils = iUiFactory->CreateUtilsL(); |
|
402 iEnv->SetUtils(iUtils); |
|
403 } |
|
404 |
|
405 MMIDCanvas* CMIDToolkit::GetCurrentCanvas() const |
|
406 { |
|
407 MMIDCanvas* ret = NULL; |
|
408 MMIDComponent* content = iCurrentDisplayable ? iCurrentDisplayable->Component() : NULL; |
|
409 if (content && content->Type() == MMIDComponent::ECanvas) |
|
410 { |
|
411 ret = static_cast<MMIDCanvas*>(content); |
|
412 } |
|
413 return ret; |
|
414 } |
|
415 |
|
416 // |
|
417 // Enables events |
|
418 // |
|
419 void CMIDToolkit::ActivateL() |
|
420 { |
|
421 iOpen=ETrue; |
|
422 SetTaskListEntry(ETrue); |
|
423 RLcdui::Get()->Plugin()->SetObserverL(this); |
|
424 iCoeEnv->RootWin().EnableReceiptOfFocus(ETrue); |
|
425 } |
|
426 |
|
427 void CMIDToolkit::SetTaskListEntry(TBool aVisible) |
|
428 { |
|
429 iWgName->SetRespondsToShutdownEvent(aVisible); |
|
430 iWgName->SetHidden(!aVisible); |
|
431 iWgName->SetAppUid(iAppUid); |
|
432 iWgName->SetWindowGroupName(iCoeEnv->RootWin()); |
|
433 } |
|
434 |
|
435 TPtrC CMIDToolkit::MidletName() const |
|
436 { |
|
437 return iWgName->Caption(); |
|
438 } |
|
439 |
|
440 void CMIDToolkit::SetCurrentL(MMIDDisplayable* aDisplayable) |
|
441 { |
|
442 MMIDDisplayable* newDisplayable = aDisplayable; |
|
443 MMIDDisplayable* oldDisplayable = iCurrentDisplayable; |
|
444 |
|
445 // Prepare switch |
|
446 TRevertCurrent revert(iCurrentDisplayable); |
|
447 CleanupStack::PushL(TCleanupItem(TRevertCurrent::Revert, &revert)); |
|
448 |
|
449 ASSERT(newDisplayable != oldDisplayable); |
|
450 |
|
451 if (NULL == newDisplayable) |
|
452 { |
|
453 ASSERT(oldDisplayable); |
|
454 ASSERT(oldDisplayable->Component()->Type() == MMIDComponent::EAlert); |
|
455 } |
|
456 |
|
457 ResetInactivityTimeL(); |
|
458 |
|
459 // Set it, revert will rollback if required. |
|
460 iCurrentDisplayable = newDisplayable; |
|
461 |
|
462 // Activate new displayable first. If this leaves the java toolkit |
|
463 // will have to cope with an unwanted pending switch event. |
|
464 if (newDisplayable) |
|
465 { |
|
466 newDisplayable->HandleCurrentL(ETrue); |
|
467 } |
|
468 // When new Displayable is EAlert and old Displayable is ECanvas then |
|
469 // variable iOldFullScreenDisplayable will have the value ECanvas. |
|
470 // This applies for Canvas in Normal mode and in Full Screen mode. |
|
471 // Deactivate old displayable - if this fails the |
|
472 // displayable is itself responsible for cleanup. |
|
473 // Deactivate also old Full Screen displayable. |
|
474 if (oldDisplayable) |
|
475 { |
|
476 TInt ignore1; |
|
477 TRAP(ignore1, oldDisplayable->HandleCurrentL(EFalse)); |
|
478 MMIDComponent::TType newType = newDisplayable->Component()->Type(); |
|
479 if ((newType == MMIDComponent::EAlert || (newType == MMIDComponent::ETextBox && |
|
480 newDisplayable->IsPopupTextBox()))) |
|
481 { |
|
482 if (!iOldFullScreenDisplayable) |
|
483 { |
|
484 iOldFullScreenDisplayable = oldDisplayable; |
|
485 } |
|
486 } |
|
487 else |
|
488 { |
|
489 if (newDisplayable == iOldFullScreenDisplayable) |
|
490 { |
|
491 iOldFullScreenDisplayable = NULL; |
|
492 } |
|
493 else |
|
494 { |
|
495 if (iOldFullScreenDisplayable) |
|
496 { |
|
497 TRAP(ignore1, |
|
498 iOldFullScreenDisplayable->HandleCurrentL(EFalse)); |
|
499 iOldFullScreenDisplayable = NULL; |
|
500 } |
|
501 } |
|
502 } |
|
503 |
|
504 MMIDComponent::TType oldType = oldDisplayable->Component()->Type(); |
|
505 |
|
506 if (newType == MMIDComponent::ECanvas && newType == oldType) |
|
507 { |
|
508 // When old and new displayable type is canvas during |
|
509 // deactivation of old displayable osk is set to background |
|
510 // and no pointer events goes to new displayable. |
|
511 // Change OSK background state to false |
|
512 newDisplayable->ChangeOSKBackgroundState(EFalse); |
|
513 } |
|
514 } |
|
515 |
|
516 CleanupStack::Pop(); // revert |
|
517 } |
|
518 |
|
519 void CMIDToolkit::ResetInactivityTimeL() |
|
520 { |
|
521 TInt status = KErrNotFound; |
|
522 RProperty::Get(KPSUidScreenSaver, KScreenSaverAllowScreenSaver,status); |
|
523 |
|
524 // If Screen Saver is enabled and is inactive reset timers |
|
525 // Keep lights on and screensaver disabled. When status is >0 it means |
|
526 // that screen saver is not allowed to be activated |
|
527 if (!status) |
|
528 { |
|
529 TInt isTimeoutEnabled = KErrNone; |
|
530 TInt errPCenrep = KErrNone; |
|
531 CRepository* pCenrep = CRepository::NewLC(KCRUidPersonalizationSettings); |
|
532 if (pCenrep) |
|
533 { |
|
534 errPCenrep = pCenrep->Get( |
|
535 KSettingsScreensaverTimeoutItemVisibility, |
|
536 isTimeoutEnabled); |
|
537 } |
|
538 CleanupStack::PopAndDestroy(pCenrep); |
|
539 |
|
540 #if defined(__WINSCW__) |
|
541 if (!isTimeoutEnabled) |
|
542 { |
|
543 isTimeoutEnabled = 1; |
|
544 } |
|
545 #endif |
|
546 |
|
547 // Screen Saver Time out value |
|
548 TInt screenSaverTimeout = KErrNone; |
|
549 TInt errSCenrep = KErrNone; |
|
550 CRepository* securityCenrep = CRepository::NewLC(KCRUidSecuritySettings); |
|
551 if (securityCenrep) |
|
552 { |
|
553 errSCenrep = securityCenrep->Get( |
|
554 KSettingsAutomaticKeyguardTime, screenSaverTimeout); |
|
555 } |
|
556 CleanupStack::PopAndDestroy(securityCenrep); |
|
557 |
|
558 // Inactivity time in seconds |
|
559 TInt userInactivity = User::InactivityTime().Int(); |
|
560 |
|
561 // Check if screen saver is inactive, if so reset timers |
|
562 if (errPCenrep == KErrNone && errSCenrep == KErrNone && |
|
563 isTimeoutEnabled && userInactivity < screenSaverTimeout) |
|
564 { |
|
565 User::ResetInactivityTime(); |
|
566 } |
|
567 } |
|
568 } |
|
569 |
|
570 void CMIDToolkit::BringToForeground() |
|
571 { |
|
572 LCDUI_DEBUG("**RF**"); |
|
573 |
|
574 // Block the foreground granting to MIDlet immediately after user has switched |
|
575 // MIDlet to background. If the background was requested by the MIDlet, |
|
576 // the foreground request made by MIDlet should not be prevented. |
|
577 TTime now; |
|
578 now.HomeTime(); |
|
579 TTimeIntervalMicroSeconds elapsedTime = now.MicroSecondsFrom(iSentToBgTime); |
|
580 if (elapsedTime > TTimeIntervalMicroSeconds(KChangingToBackgroundTimeout) || |
|
581 iMidletRequestedBg) |
|
582 { |
|
583 if (mFirst) |
|
584 { |
|
585 TRAP_IGNORE(HandleForegroundL(ETrue)); |
|
586 } |
|
587 |
|
588 SetOrdinalPosition(KWgOrdinalForeground); |
|
589 |
|
590 if (mFirst) |
|
591 { |
|
592 mFirst = EFalse; |
|
593 } |
|
594 } |
|
595 |
|
596 // Stop the start screen if it is still active. |
|
597 java::ui::CoreUiAvkonAppUi* appUi = java::ui::CoreUiAvkonLcdui::getInstance().getJavaUiAppUi(); |
|
598 if (appUi && appUi->hasStartScreen()) |
|
599 { |
|
600 MMIDComponent* content = iCurrentDisplayable ? iCurrentDisplayable->Component() : NULL; |
|
601 |
|
602 TBool isCanvas = EFalse; |
|
603 TBool isCanvasReadyToBlit = EFalse; |
|
604 TBool isFullscreenUI = ETrue; |
|
605 if (content) |
|
606 { |
|
607 MMIDComponent::TType contentType = content->Type(); |
|
608 |
|
609 if (contentType == MMIDComponent::ECanvas) |
|
610 { |
|
611 isCanvas = ETrue; |
|
612 MMIDCanvas* canvas = static_cast<MMIDCanvas*>(content); |
|
613 isCanvasReadyToBlit = canvas->ReadyToBlit(); |
|
614 } |
|
615 else |
|
616 { |
|
617 if (contentType == MMIDComponent::EAlert || |
|
618 (contentType == MMIDComponent::ETextBox && |
|
619 iCurrentDisplayable->IsPopupTextBox())) |
|
620 { |
|
621 isFullscreenUI = EFalse; |
|
622 } |
|
623 } |
|
624 } |
|
625 |
|
626 if (!content || !isCanvas || isCanvasReadyToBlit) |
|
627 { |
|
628 if (iCurrentDisplayable) |
|
629 { |
|
630 iCurrentDisplayable->DrawNow(); |
|
631 } |
|
632 |
|
633 appUi->stopStartScreen(isFullscreenUI); |
|
634 } |
|
635 } |
|
636 } |
|
637 |
|
638 void CMIDToolkit::SendToBackground() |
|
639 { |
|
640 LCDUI_DEBUG("**RB**"); |
|
641 |
|
642 if (mFirst) |
|
643 { |
|
644 java::ui::CoreUiAvkonAppUi* appUi = java::ui::CoreUiAvkonLcdui::getInstance().getJavaUiAppUi(); |
|
645 appUi->stopStartScreen(false); // no screenshot |
|
646 mFirst = EFalse; |
|
647 } |
|
648 iMidletRequestedBg = ETrue; |
|
649 SetOrdinalPosition(KWgOrdinalBackground); |
|
650 } |
|
651 |
|
652 void CMIDToolkit::SetOrdinalPosition(TInt aPos) |
|
653 { |
|
654 RWindowGroup& group = iCoeEnv->RootWin(); |
|
655 group.SetOrdinalPosition(aPos); |
|
656 } |
|
657 |
|
658 void CMIDToolkit::ClearDisplayable() |
|
659 { |
|
660 MMIDDisplayable* current = iCurrentDisplayable; |
|
661 iCurrentDisplayable = NULL; |
|
662 if (current) |
|
663 { |
|
664 TInt ignore; |
|
665 TRAP(ignore, current->HandleCurrentL(EFalse)); |
|
666 } |
|
667 SendToBackground(); |
|
668 } |
|
669 |
|
670 /** |
|
671 * SERVER SIDE |
|
672 */ |
|
673 void CMIDToolkit::DisposeObject(MMIDComponent* aObject) |
|
674 { |
|
675 for (TInt i = iObjects.Count(); i--;) |
|
676 { |
|
677 TObjectEntry* entry = iObjects[i]; |
|
678 if (entry->iComponent == aObject) |
|
679 { |
|
680 DisposeEntry(i, ETrue); |
|
681 return; |
|
682 } |
|
683 } |
|
684 ASSERT(NULL == aObject); |
|
685 } |
|
686 |
|
687 void CMIDToolkit::DestroyUi() |
|
688 { |
|
689 // |
|
690 // Cleanup any components which have not been finalized yet. |
|
691 // |
|
692 // This is the last change to finalize them. |
|
693 // |
|
694 const TInt count = iObjects.Count(); |
|
695 for (TInt i=count-1; i>=0; --i) |
|
696 { |
|
697 DisposeEntry(i, EFalse); |
|
698 } |
|
699 |
|
700 if (iGrFactory) |
|
701 { |
|
702 iGrFactory->Dispose(); |
|
703 iGrFactory = NULL; |
|
704 } |
|
705 |
|
706 if (iUtils) |
|
707 { |
|
708 if (iEnv) |
|
709 { |
|
710 iEnv->SetUtils(NULL); |
|
711 } |
|
712 iUtils->Dispose(); |
|
713 iUtils = NULL; |
|
714 } |
|
715 |
|
716 if (iUiFactory) |
|
717 { |
|
718 iUiFactory->Dispose(); |
|
719 iUiFactory = NULL; |
|
720 } |
|
721 |
|
722 iGrLibrary.Close(); |
|
723 |
|
724 // Null MMIDEnv pointer from CMIDAppUi before |
|
725 // destroying iEnv |
|
726 if (RLcdui::Get()->Plugin()) |
|
727 { |
|
728 RLcdui::Get()->Plugin()->SetEnv(NULL); |
|
729 } |
|
730 |
|
731 delete iEnv; |
|
732 iEnv = NULL; |
|
733 } |
|
734 |
|
735 /** |
|
736 * DESTRUCTION PHASE 3 - SERVER SIDE |
|
737 * |
|
738 * This method is called when the event source has no more references |
|
739 * and is about to be deleted. It is called in the context of the |
|
740 * server thread, allowing server side resources to be cleaned up. |
|
741 * |
|
742 * It is called before FinalizeJni() so there may still be live JNI |
|
743 * weak references contained in MMIDComponent objects referenced by |
|
744 * the iObjects array. |
|
745 * |
|
746 * If SvrConstructL fails, the calling thread is responsible for calling |
|
747 * Dispose() on the toolkit, which will lead to FinalizeSvr being called |
|
748 * in the context of the server thread. This is therefore the appropriate |
|
749 * place to cleanup server side resources. |
|
750 * |
|
751 * Like any normal destructor it should be able to cope with cleaning up |
|
752 * partically constructed objects. Unlike a normal destructor, additional |
|
753 * code (including FinalizeJni and the real destructor) will be run *after* |
|
754 * this method - so any instance variables that could be queried by these |
|
755 * methods should be cleaned up appropriately. |
|
756 * |
|
757 * Here we take down instance members in reverse order that they were |
|
758 * allocated/constructed. |
|
759 * |
|
760 */ |
|
761 void CMIDToolkit::FinalizeSvr() |
|
762 { |
|
763 LCDUI_DEBUG_INT("CMIDToolkit::FinalizeSvr(%d) DESTRUCTOR PHASE 3", (TInt)this); |
|
764 |
|
765 switch (iPhase) |
|
766 { |
|
767 case ENone: |
|
768 ASSERT(iPhase != ENone); |
|
769 break; |
|
770 |
|
771 case EPhase1: |
|
772 case EPhase2: |
|
773 return; |
|
774 |
|
775 case EPhase3: |
|
776 iPhase = EPhase2; |
|
777 break; |
|
778 } |
|
779 |
|
780 #ifdef RD_JAVA_NGA_ENABLED |
|
781 // Notify canvas about exit, so that canvas MIDlets |
|
782 // get system effect in exit |
|
783 MMIDCanvas* canvas = GetCurrentCanvas(); |
|
784 if (canvas) |
|
785 { |
|
786 canvas->MidletExiting(); |
|
787 } |
|
788 #endif // RD_JAVA_NGA_ENABLED |
|
789 |
|
790 |
|
791 // Always use exit effect when exiting midlet |
|
792 GfxTransEffect::BeginFullScreen(AknTransEffect::EApplicationExit, TRect(), |
|
793 AknTransEffect::EParameterType, AknTransEffect::GfxTransParam(iAppUid)); |
|
794 |
|
795 |
|
796 // |
|
797 // Send MIDlet to background. |
|
798 // |
|
799 ClearDisplayable(); |
|
800 |
|
801 #ifdef CLEAR_TASKLIST_IN_CLOSE |
|
802 // |
|
803 // Remove tasklist entry. |
|
804 // |
|
805 iAppUid.iUid=0; |
|
806 SetTaskListEntry(EFalse); |
|
807 #endif |
|
808 |
|
809 DestroyUi(); |
|
810 |
|
811 if (iCoeEnv) |
|
812 { |
|
813 // |
|
814 // Refuse focus |
|
815 // |
|
816 iCoeEnv->RootWin().EnableReceiptOfFocus(EFalse); |
|
817 iCoeEnv = NULL; |
|
818 } |
|
819 |
|
820 if (RLcdui::Get()->Plugin()) |
|
821 { |
|
822 // The leave can occur only when starting MIDlet |
|
823 TRAP_IGNORE(RLcdui::Get()->Plugin()->SetObserverL(NULL)); |
|
824 } |
|
825 |
|
826 DestroyUi(); |
|
827 |
|
828 iWgName = NULL; |
|
829 |
|
830 iCurrentDisplayable = NULL; |
|
831 |
|
832 } |
|
833 |
|
834 /** |
|
835 * DESTRUCTION PHASE 2 - Java Side. |
|
836 * |
|
837 * Multi-thead note: |
|
838 * |
|
839 * Although this method runs Java side, there should be no remaining server |
|
840 * side references to the object by the time this method runs. It is safe |
|
841 * to access server side data structures - such as the disposed reference |
|
842 * queue. |
|
843 * |
|
844 */ |
|
845 void CMIDToolkit::FinalizeJni(JNIEnv& aJni) |
|
846 { |
|
847 LCDUI_DEBUG_INT("CMIDToolkit::FinalizeJni(%d) DESTRUCTION PHASE 2", (TInt)this); |
|
848 |
|
849 switch (iPhase) |
|
850 { |
|
851 case ENone: |
|
852 ASSERT(iPhase != ENone); |
|
853 break; |
|
854 |
|
855 case EPhase1: |
|
856 // We didn't even get as far as running ConstructL() |
|
857 return; |
|
858 |
|
859 case EPhase2: |
|
860 // We got at least part way through ConstructL(). |
|
861 iPhase = EPhase1; |
|
862 break; |
|
863 |
|
864 case EPhase3: |
|
865 ASSERT(iPhase != EPhase3); |
|
866 break; |
|
867 } |
|
868 |
|
869 // |
|
870 // There should be no more entries in the object map, only |
|
871 // entries on the finalization queue. |
|
872 // |
|
873 ASSERT(0 == iObjects.Count()); |
|
874 |
|
875 FinalizeReferences(aJni); // dispose finalize queue |
|
876 |
|
877 // |
|
878 // MUTEX NOTE: FinalizeMutex not needed as the calling |
|
879 // thread holds the last reference. |
|
880 // |
|
881 iFinalizeQueue = iDisposedQueue; |
|
882 iFinalizeCount = iDisposedCount; |
|
883 iDisposedQueue = NULL; |
|
884 iDisposedCount = 0; |
|
885 |
|
886 FinalizeReferences(aJni); // dispose finalize queue |
|
887 |
|
888 delete iHomeDir; |
|
889 iHomeDir = NULL; |
|
890 |
|
891 delete iMidletSuite; |
|
892 iMidletSuite = NULL; |
|
893 } |
|
894 |
|
895 void CMIDToolkit::DisposeEntry(TInt aIndex, TBool aPostEvent) |
|
896 { |
|
897 TObjectEntry* entry = iObjects[aIndex]; |
|
898 iObjects.Remove(aIndex); |
|
899 |
|
900 if (entry->iComponent) |
|
901 { |
|
902 /* |
|
903 * Make weak ref available for cleanup. |
|
904 */ |
|
905 entry->iDisposed = entry->iComponent->iPeer; |
|
906 entry->iComponent->iPeer = NULL; |
|
907 entry->iComponent->Dispose(); |
|
908 entry->iComponent = NULL; |
|
909 } |
|
910 |
|
911 if (entry->iDisposed) |
|
912 { |
|
913 // |
|
914 // Park entry on the dispose queue. |
|
915 // |
|
916 entry->iNextEntry = iDisposedQueue; |
|
917 iDisposedQueue = entry; |
|
918 iDisposedCount++; |
|
919 |
|
920 // MUTEX NOTE - can test iFinalizeQueue as we only write it when NULL |
|
921 // in which case no-one else will be reading/writing. |
|
922 if (aPostEvent && (iDisposedCount > KPayload) && (NULL == iFinalizeQueue)) |
|
923 { |
|
924 iFinalizeMutex.Wait(); |
|
925 iFinalizeQueue = iDisposedQueue; |
|
926 iFinalizeCount = iDisposedCount; |
|
927 PostEvent(new CMIDFinalizeEvent); |
|
928 iDisposedQueue = NULL; |
|
929 iDisposedCount = 0; |
|
930 iFinalizeMutex.Signal(); |
|
931 } |
|
932 } |
|
933 else |
|
934 { |
|
935 // |
|
936 // There is no peer to dispose, so we are free to |
|
937 // delete the entry immediately, or part it on |
|
938 // on a free list. |
|
939 // |
|
940 delete entry; |
|
941 } |
|
942 } |
|
943 |
|
944 void TRevertCurrent::Revert(TAny* aPtr) |
|
945 { |
|
946 TRevertCurrent& revert = *static_cast<TRevertCurrent*>(aPtr); |
|
947 revert.iCurrentPointer = revert.iPrevious; |
|
948 } |
|
949 |
|
950 |
|
951 void CMIDFinalizeEvent::Dispatch(JNIEnv& aJni) |
|
952 { |
|
953 Object().FinalizeReferences(aJni); |
|
954 } |
|
955 |
|
956 CMIDToolkit::TObjectEntry::TObjectEntry(MMIDComponent* aComponent) |
|
957 : iComponent(aComponent) |
|
958 , iDisposed(NULL) |
|
959 { |
|
960 } |
|
961 |
|
962 TInt CMIDToolkit::New |
|
963 ( |
|
964 JNIEnv& aJni, |
|
965 jobject aPeer, |
|
966 TJavaEventServer aServer, |
|
967 const TDesC& aAppName, |
|
968 TInt aAppUid, |
|
969 const TDesC& aAppHome, |
|
970 RPointerArray<HBufC>* aAttributes |
|
971 ) |
|
972 { |
|
973 TRAPD(handle, handle=CreateToolkitL(aJni, aPeer, aServer, aAppName, aAppUid, aAppHome, aAttributes)); |
|
974 return handle; |
|
975 } |
|
976 |
|
977 TInt CMIDToolkit::CreateToolkitL |
|
978 ( |
|
979 JNIEnv& aJni, |
|
980 jobject aPeer, |
|
981 TJavaEventServer aServer, |
|
982 const TDesC& aAppName, |
|
983 TInt aAppUid, |
|
984 const TDesC& aAppHome, |
|
985 RPointerArray<HBufC>* aAttributes |
|
986 ) |
|
987 { |
|
988 TConstructor self(aJni); |
|
989 self->ConstructL(aJni,aPeer,aServer,aAppName,aAppUid,aAppHome,aAttributes); |
|
990 return self.GetHandle(); |
|
991 } |
|
992 |
|
993 TBool CMIDToolkit::CheckEvent(CJavaEventBase* /* aEvent */) |
|
994 { |
|
995 return iOpen; |
|
996 } |
|
997 |
|
998 void CMIDToolkit::FinalizeReferences(JNIEnv& aEnv) |
|
999 { |
|
1000 TObjectEntry* queue = NULL; |
|
1001 TInt count = 0; |
|
1002 |
|
1003 iFinalizeMutex.Wait(); |
|
1004 |
|
1005 queue = iFinalizeQueue; |
|
1006 count = iFinalizeCount; |
|
1007 |
|
1008 iFinalizeQueue = NULL; |
|
1009 iFinalizeCount = 0; |
|
1010 |
|
1011 iFinalizeMutex.Signal(); |
|
1012 |
|
1013 while (queue) |
|
1014 { |
|
1015 TObjectEntry* next = queue->iNextEntry; |
|
1016 ASSERT(queue->iDisposed); |
|
1017 aEnv.DeleteWeakGlobalRef((jweak)(queue->iDisposed)); |
|
1018 delete queue; |
|
1019 queue = next; |
|
1020 --count; |
|
1021 } |
|
1022 |
|
1023 ASSERT(0 == count); |
|
1024 } |
|
1025 |
|
1026 CMIDletSuite::CMIDletSuite() |
|
1027 :iAttributes() |
|
1028 { |
|
1029 } |
|
1030 |
|
1031 /** |
|
1032 * Takes ownership of pointed objects. |
|
1033 */ |
|
1034 void CMIDletSuite::SetAttributesL(RPointerArray<HBufC>& aAttributes) |
|
1035 { |
|
1036 const TInt count = aAttributes.Count(); |
|
1037 for (TInt i=0; i<count; i++) |
|
1038 { |
|
1039 HBufC* entry = aAttributes[i]; |
|
1040 iAttributes.InsertL(entry, i); |
|
1041 aAttributes[i]=NULL; |
|
1042 } |
|
1043 aAttributes.Reset(); |
|
1044 } |
|
1045 |
|
1046 CMIDletSuite::~CMIDletSuite() |
|
1047 { |
|
1048 iAttributes.ResetAndDestroy(); |
|
1049 iAttributes.Close(); |
|
1050 } |
|
1051 |
|
1052 TInt CMIDletSuite::GetAttribute(const TDesC& aName, TPtrC& aValue) |
|
1053 { |
|
1054 const TInt length = iAttributes.Count(); |
|
1055 for (TInt ii=0; ii<length; ii+=2) |
|
1056 { |
|
1057 if (aName.CompareC(*iAttributes[ii]) == 0) |
|
1058 { |
|
1059 aValue.Set(*iAttributes[ii+1]); |
|
1060 return KErrNone; |
|
1061 } |
|
1062 } |
|
1063 return KErrNotFound; |
|
1064 } |
|
1065 |
|
1066 TInt CMIDToolkit::MidletAttribute(const TDesC& aAttributeName, TPtrC& aAttributeValue) |
|
1067 { |
|
1068 return iMidletSuite->GetAttribute(aAttributeName, aAttributeValue); |
|
1069 } |
|
1070 |
|
1071 |
|
1072 TInt CMIDToolkit::PostDisplayEvent(TEventType aEvent) |
|
1073 { |
|
1074 // |
|
1075 // We pass the toolkit peer as CMIDEvent checks the source weak ref and |
|
1076 // will nop any events to expired objects. |
|
1077 // |
|
1078 jweak toolkit = Peer(); |
|
1079 |
|
1080 CMIDEvent* event = new CMIDEvent(iHandleDisplayEvent, toolkit, aEvent); |
|
1081 |
|
1082 if (event) |
|
1083 { |
|
1084 return PostEvent(event); |
|
1085 } |
|
1086 return KErrNoMemory; |
|
1087 } |
|
1088 |
|
1089 TInt CMIDToolkit::PostDisplayableEvent(MMIDComponent& aDisplayable, TEventType aEvent, TInt aParam0, TInt aParam1) |
|
1090 { |
|
1091 jobject displayable = MIDJOBJECT(&aDisplayable); |
|
1092 |
|
1093 // Even if displayable is null it is safe to post the event as the event will |
|
1094 // dispose itself without posting itself. |
|
1095 CMIDEvent* event = new CMIDEvent(iHandleDisplayableEvent, displayable, aEvent, aParam0, aParam1); |
|
1096 if (event) |
|
1097 { |
|
1098 return PostEvent(event); |
|
1099 } |
|
1100 return KErrNoMemory; |
|
1101 } |
|
1102 |
|
1103 TInt CMIDToolkit::PostItemEvent(MMIDComponent& aItem, TEventType aEvent, TInt aParam0, TInt aParam1, TInt aParam2) |
|
1104 { |
|
1105 jobject item = MIDJOBJECT(&aItem); |
|
1106 ASSERT(item); |
|
1107 CMIDEvent* event = new CMIDEvent(iHandleItemEvent, item, aEvent, aParam0, aParam1, aParam2); |
|
1108 if (event) |
|
1109 { |
|
1110 return PostEvent(event); |
|
1111 } |
|
1112 return KErrNoMemory; |
|
1113 } |
|
1114 |
|
1115 TInt CMIDToolkit::PostCanvasGraphicsItemPainterEvent(MMIDComponent& aCanvasGraphicsItemPainter, |
|
1116 TEventType aEvent, TInt aParam0, TInt aParam1) |
|
1117 { |
|
1118 jobject canvasgraphicsitempainter = MIDJOBJECT(&aCanvasGraphicsItemPainter); |
|
1119 CMIDEvent* event = new CMIDEvent(iHandleCanavsGraphicsItemPainterEvent, canvasgraphicsitempainter, |
|
1120 aEvent, aParam0, aParam1); |
|
1121 if (event) |
|
1122 { |
|
1123 return PostEvent(event); |
|
1124 } |
|
1125 return KErrNoMemory; |
|
1126 } |