javauis/lcdui_akn/javalcdui/src/CMIDToolkit.cpp
branchRCL_3
changeset 26 2455ef1f5bbc
equal deleted inserted replaced
25:ae942d28ec0e 26:2455ef1f5bbc
       
     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 }