diff -r f5050f1da672 -r 04becd199f91 javauis/lcdui_akn/javalcdui/src/CMIDToolkit.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javauis/lcdui_akn/javalcdui/src/CMIDToolkit.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,998 @@ +/* +* Copyright (c) 1999 - 2003 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // For transition effects +#include // For transition effects +// +#include "lcdui.h" +#include "lcdgr.h" +#include "mevents.h" +#include "jutils.h" +#include "MIDUtils.h" +#include "CJavaEventServer.h" +#include "CMIDToolkit.h" +#include "CMIDEvent.h" +#include "CMIDBuffer.h" +#include "CMIDNotify.h" +#include +#include "LcduiThread.h" + +#include "coreuiavkonlcdui.h" +#include "coreuiappui.h" + +#include "MMIDCanvasGraphicsItemPainter.h" + +#include +#ifdef LCDUI_DEBUG_ON +#define LCDUI_DEBUG(msg) DEBUG(msg) +#define LCDUI_DEBUG_INT(msg, x) DEBUG_INT(msg, x) +#else +#define LCDUI_DEBUG(msg) +#define LCDUI_DEBUG_INT(msg, x) +#endif + +/** + * Macro controlling synthesis of AppArc foreground event when the + * MIdlet requests that the Display be brought to the foreground. + * + * Some UI's may require this event, others may not. + * + * Generation of this event should be moved to the plugin. + */ +#define GENERATE_APPARC_FOREGROUND_EVENT 1 + +/** + * Macro controlling whether the tasklist entry is cleared early in + * CMIDToolkit::Close() or left in place until the window group is + * destroyed (when the eikonenv is destroyed). + * + */ +#define CLEAR_TASKLIST_IN_CLOSE 1 + +/** + * Macro extracting the weak reference corresponding to a component. + */ +#define MIDJOBJECT(component) ( reinterpret_cast((component)->iPeer) ) + +/** + * Graphics plugin library name. + */ +_LIT(KGrLibName,"lcdgr"); + +/** + * Window group ordinal position (z-order) for sending to background. + */ +const TInt KWgOrdinalBackground = -1; + +/** + * Window group ordinal position (z-order) for bringing to foreground. + */ +const TInt KWgOrdinalForeground = 0; + + +/** + * This timeout (microseconds) defines how long we prevent MIDlet from becoming + * back to foregound after user has switched it to background. + * Some MIDlets change the current displayable in hideNotify(), which (without this prevention) + * would cause them to become back to foreground immediately. + */ +const TInt KChangingToBackgroundTimeout = 5000000; + + +/** + * LCDGR graphics plugin factory function. + */ +typedef MMIDGraphicsFactory*(*TCreateGraphicsFactoryFunc)(RFs&, TDisplayMode); + + +/** + * Exception safe reversion to previous displayable if CMIDToolkit::SetCurrentL fails. + * + */ +class TRevertCurrent +{ +public: + TRevertCurrent(MMIDDisplayable*& aCurrentPointer) + : iCurrentPointer(aCurrentPointer) + , iPrevious(aCurrentPointer) + { + } + static void Revert(TAny*); + +private: + MMIDDisplayable*& iCurrentPointer; + MMIDDisplayable* iPrevious; +}; + +/** + * process entries on finalize queue. + */ +class CMIDFinalizeEvent : public CJavaEvent +{ +private: + void Dispatch(JNIEnv& aJni); +}; + + +const static TInt KPayload = 16; // Number of weak references on queue before dispose event + +/** + * Register an MMIDComponent and its peer with the Toolkit. + * + *@return an object handle. + */ +TInt CMIDToolkit::RegisterComponentL(MMIDComponent* aComponent, TJavaPeer aPeer) +{ + ASSERT(aComponent); + TObjectEntry* entry = new(ELeave) TObjectEntry(aComponent); + CleanupStack::PushL(entry); + User::LeaveIfError(iObjects.Append(entry)); + CleanupStack::Pop(entry); + aComponent->iPeer = aPeer; + return MIDHandle(aComponent); +} + +/** + * CONSTRUCTION PHASE 1 . Java side. + */ +CMIDToolkit::CMIDToolkit() + : iPhase(EPhase1) + , iOldFullScreenDisplayable(NULL), iObjects(EGranularity), iSentToBgTime(0), mFirst(ETrue) +{ + LCDUI_DEBUG_INT("CMIDToolkit::CMIDToolkit(%d) CONSTRUCTION PHASE 1", (TInt)this); + iFinalizeMutex.CreateLocal(); +} + +/** + * DESTRUCTION PHASE 1 . Java side + */ +CMIDToolkit::~CMIDToolkit() +{ + LCDUI_DEBUG_INT("CMIDToolkit::~CMIDToolkit(%d): DESTRUCTION PHASE 1 ", (TInt)this); + ASSERT(iPhase == EPhase1); + + iFinalizeMutex.Close(); + iObjects.Close(); + + // + // We cannot delete any server side objects in the + // destructor since it runs Java side. Therefore if + // any of the following invariants fail, we have + // leaked or failed to zero the pointer. + // + + ASSERT(0 == iObjects.Count()); + ASSERT(NULL == iDisposedQueue); + ASSERT(0 == iDisposedCount); + ASSERT(NULL == iFinalizeQueue); + ASSERT(NULL == iFinalizeCount); + + // Not owned but worth checking we clean everything. + ASSERT(NULL == iCoeEnv); + + // Owned - if these are non-null we leaked. + ASSERT(NULL == iWgName); + ASSERT(NULL == iHomeDir); + ASSERT(NULL == iEnv); + ASSERT(NULL == iMidletSuite); + ASSERT(NULL == iUtils); + ASSERT(NULL == iUiFactory); + ASSERT(NULL == iGrFactory); + + ASSERT(0 == iGrLibrary.Handle()); // Did we unload the gr library + ASSERT(NULL == iCurrentDisplayable); // Did we clean up correctly + + LCDUI_DEBUG_INT("CMIDToolkit::~CMIDToolkit(%d): DESTRUCTION PHASE 1 ", (TInt)this); +} + +void CMIDToolkit::HandleExitL() +{ + PostDisplayEvent(EExit); +} + + +void CMIDToolkit::HandleForegroundL(TBool aForeground) +{ + if (aForeground) + { + // reset flag + iMidletRequestedBg = EFalse; + iSentToBgTime = 0; + LCDUI_DEBUG("**FE**"); + } + else + { + iSentToBgTime.HomeTime(); + LCDUI_DEBUG("**BE**"); + } + iEnv->HandleForegroundL(aForeground); + PostDisplayEvent(aForeground?EForeground:EBackground); +} + +void CMIDToolkit::HandleResourceChangeL(TInt aType) +{ + iEnv->HandleResourceChangeL(aType); +} + +void CMIDToolkit::HandleSwitchOnEventL() +{ + iEnv->HandleSwitchOnL(ETrue); +} + +/** + * CONSTRUCTION PHASE 2. + * Java Side. + */ +void CMIDToolkit::ConstructL +( + JNIEnv& aJni, + jobject aPeer, + TJavaEventServer aServer, + const TDesC& aAppName, + TInt aAppUid, + const TDesC& aAppHome, + RPointerArray* aAttributes +) +{ + LCDUI_DEBUG_INT("CMIDToolkit::ConstructL(%x) CONSTRUCTION PHASE 2 ", (TInt)this); + ASSERT(iPhase == EPhase1); + iPhase = EPhase2; + + CJavaEventSourceBase::ConstructL(aJni,aPeer,aServer); + + jclass clz = aJni.GetObjectClass(aPeer); + iHandleItemEvent = aJni.GetMethodID(clz, "handleItemEvent", "(Ljavax/microedition/lcdui/Item;IIII)V"); + iHandleDisplayableEvent = aJni.GetMethodID(clz, "handleDisplayableEvent", "(Ljavax/microedition/lcdui/Displayable;IIII)V"); + iHandleDisplayEvent = aJni.GetMethodID(clz, "handleDisplayEvent", "(Ljavax/microedition/lcdui/Toolkit;IIII)V"); + iHandleNotifyMethod = aJni.GetMethodID(clz, "handleAsyncEvent", "(Ljava/lang/Object;I)V"); + iHandleCanavsGraphicsItemPainterEvent = aJni.GetMethodID( + clz, + "handleCanvasGraphicsItemPainterEvent", + "(Ljavax/microedition/lcdui/CanvasGraphicsItemPainter;IIII)V"); + + aJni.DeleteLocalRef(clz); + + if (0 == iHandleNotifyMethod || + 0 == iHandleDisplayEvent || + 0 == iHandleDisplayableEvent || + 0 == iHandleItemEvent + ) + { + User::Leave(KErrGeneral); + } + + iHomeDir=aAppHome.AllocL(); + iAppUid=TUid::Uid(aAppUid); + + iMidletSuite = new(ELeave) CMIDletSuite; + if (aAttributes) + { + iMidletSuite->SetAttributesL(*aAttributes); + } + + CMIDToolkit* toolkit = this; + const TDesC* appName = &aAppName; + + TInt err = ExecuteTrap(&CMIDToolkit::InvokeSvrConstructL, toolkit, appName); + User::LeaveIfError(err); +} + +void CMIDToolkit::InvokeSvrConstructL(CMIDToolkit* aToolkit, const TDesC* aName) +{ + User::LeaveIfError(RLcdui::Get()->CreateAppUi()); + + aToolkit->SvrConstructL(*aName); +} + + +/** + * CONSTRUCTION PHASE 3. + * Server Side. + */ +void CMIDToolkit::SvrConstructL(const TDesC& aAppName) +{ + LCDUI_DEBUG_INT("CMIDToolkit::SvrConstructL(%x) CONSTRUCTION PHASE 3", (TInt)this); + ASSERT(iPhase == EPhase2); + iPhase = EPhase3; // fully constructed + + // + // This is the first method called server side, so the first place + // we can safely obtain these pointers. + // + iCoeEnv = CCoeEnv::Static(); + + iEnv = new(ELeave) CMIDEnv(this, TSize()); + iEnv->ConstructL(); + + CreateTaskListEntryL(aAppName); + SetTaskListEntry(EFalse); + + // + // + // + LoadLibrariesL(); +} + +void CMIDToolkit::CreateTaskListEntryL(const TDesC& aAppName) +{ + ASSERT(NULL == iWgName); + iWgName = java::ui::CoreUiAvkonLcdui::getInstance().getWindowGroupName(); + iWgName->SetRespondsToSwitchFilesEvent(EFalse); + iWgName->SetCaptionL(aAppName); +} + +void CMIDToolkit::LoadLibrariesL() +{ + ASSERT(NULL == iGrFactory); + ASSERT(NULL == iUiFactory); + + RFs& fs = iCoeEnv->FsSession(); + TDisplayMode screenMode=iCoeEnv->ScreenDevice()->DisplayMode(); +#ifdef RD_JAVA_S60_RELEASE_9_2 + if (screenMode == EColor16MAP) + { + screenMode = EColor16MA; + } +#endif + + // + // Load the GR dll + // + User::LeaveIfError(iGrLibrary.Load(KGrLibName)); + TCreateGraphicsFactoryFunc CreateGraphicsFactoryL; + CreateGraphicsFactoryL = (TCreateGraphicsFactoryFunc)iGrLibrary.Lookup(1); + if (!CreateGraphicsFactoryL) + { + User::Leave(KErrBadLibraryEntryPoint); + } + iGrFactory = (*CreateGraphicsFactoryL)(fs, screenMode); + + MLcduiPlugin* plugin = RLcdui::Get()->Plugin(); + if (!plugin) + { + User::Leave(KErrGeneral); + } + + iUiFactory = plugin->CreateComponentFactoryL(); + iUiFactory->ConstructL(*iEnv); + + iUtils = iUiFactory->CreateUtilsL(); + iEnv->SetUtils(iUtils); +} + +// +// Enables events +// +void CMIDToolkit::ActivateL() +{ + iOpen=ETrue; + SetTaskListEntry(ETrue); + RLcdui::Get()->Plugin()->SetObserver(this); + iCoeEnv->RootWin().EnableReceiptOfFocus(ETrue); +} + +void CMIDToolkit::SetTaskListEntry(TBool aVisible) +{ + iWgName->SetRespondsToShutdownEvent(aVisible); + iWgName->SetHidden(!aVisible); + iWgName->SetAppUid(iAppUid); + iWgName->SetWindowGroupName(iCoeEnv->RootWin()); +} + +TPtrC CMIDToolkit::MidletName() const +{ + return iWgName->Caption(); +} + +void CMIDToolkit::SetCurrentL(MMIDDisplayable* aDisplayable) +{ + MMIDDisplayable* newDisplayable = aDisplayable; + MMIDDisplayable* oldDisplayable = iCurrentDisplayable; + + // Prepare switch + TRevertCurrent revert(iCurrentDisplayable); + CleanupStack::PushL(TCleanupItem(TRevertCurrent::Revert, &revert)); + + ASSERT(newDisplayable != oldDisplayable); + + if (NULL == newDisplayable) + { + ASSERT(oldDisplayable); + ASSERT(oldDisplayable->Component()->Type() == MMIDComponent::EAlert); + } + + // Set it, revert will rollback if required. + iCurrentDisplayable = newDisplayable; + + // Activate new displayable first. If this leaves the java toolkit + // will have to cope with an unwanted pending switch event. + if (newDisplayable) + { + newDisplayable->HandleCurrentL(ETrue); + } + // When new Displayable is EAlert and old Displayable is ECanvas then + // variable iOldFullScreenDisplayable will have the value ECanvas. + // This applies for Canvas in Normal mode and in Full Screen mode. + // Deactivate old displayable - if this fails the + // displayable is itself responsible for cleanup. + // Deactivate also old Full Screen displayable. + if (oldDisplayable) + { + TInt ignore1; + TRAP(ignore1, oldDisplayable->HandleCurrentL(EFalse)); + MMIDComponent::TType newType = newDisplayable->Component()->Type(); + if ((newType == MMIDComponent::EAlert || (newType == MMIDComponent::ETextBox && + newDisplayable->IsPopupTextBox()))) + { + if (!iOldFullScreenDisplayable) + { + iOldFullScreenDisplayable = oldDisplayable; + } + } + else + { + if (newDisplayable == iOldFullScreenDisplayable) + { + iOldFullScreenDisplayable = NULL; + } + else + { + if (iOldFullScreenDisplayable) + { + TRAP(ignore1, + iOldFullScreenDisplayable->HandleCurrentL(EFalse)); + iOldFullScreenDisplayable = NULL; + } + } + } + + MMIDComponent::TType oldType = oldDisplayable->Component()->Type(); + + if (newType == MMIDComponent::ECanvas && newType == oldType) + { + // When old and new displayable type is canvas during + // deactivation of old displayable osk is set to background + // and no pointer events goes to new displayable. + // Change OSK background state to false + newDisplayable->ChangeOSKBackgroundState(EFalse); + } + } + + CleanupStack::Pop(); // revert +} + +void CMIDToolkit::BringToForeground() +{ + LCDUI_DEBUG("**RF**"); + + // Block the foreground granting to MIDlet immediately after user has switched + // MIDlet to background. If the background was requested by the MIDlet, + // the foreground request made by MIDlet should not be prevented. + TTime now; + now.HomeTime(); + TTimeIntervalMicroSeconds elapsedTime = now.MicroSecondsFrom(iSentToBgTime); + if (elapsedTime > TTimeIntervalMicroSeconds(KChangingToBackgroundTimeout) || + iMidletRequestedBg) + { + if (mFirst) + { + TRAP_IGNORE(HandleForegroundL(ETrue)); + } + + SetOrdinalPosition(KWgOrdinalForeground); + + if (mFirst) + { + java::ui::CoreUiAvkonAppUi* appUi = java::ui::CoreUiAvkonLcdui::getInstance().getJavaUiAppUi(); + if (appUi && appUi->hasStartScreen()) + { + MMIDComponent* content = iCurrentDisplayable ? iCurrentDisplayable->Component() : NULL; + if (!content || content->Type() != MMIDComponent::ECanvas) + { + if (iCurrentDisplayable) + iCurrentDisplayable->DrawNow(); + appUi->stopStartScreen(); + } + } + + mFirst = EFalse; + } + } +} + +void CMIDToolkit::SendToBackground() +{ + LCDUI_DEBUG("**RB**"); + + if (mFirst) + { + java::ui::CoreUiAvkonAppUi* appUi = java::ui::CoreUiAvkonLcdui::getInstance().getJavaUiAppUi(); + appUi->stopStartScreen(); + mFirst = EFalse; + } + iMidletRequestedBg = ETrue; + SetOrdinalPosition(KWgOrdinalBackground); +} + +void CMIDToolkit::SetOrdinalPosition(TInt aPos) +{ + RWindowGroup& group = iCoeEnv->RootWin(); + group.SetOrdinalPosition(aPos); +} + +void CMIDToolkit::ClearDisplayable() +{ + MMIDDisplayable* current = iCurrentDisplayable; + iCurrentDisplayable = NULL; + if (current) + { + TInt ignore; + TRAP(ignore, current->HandleCurrentL(EFalse)); + } + SendToBackground(); +} + +/** + * SERVER SIDE + */ +void CMIDToolkit::DisposeObject(MMIDComponent* aObject) +{ + for (TInt i = iObjects.Count(); i--;) + { + TObjectEntry* entry = iObjects[i]; + if (entry->iComponent == aObject) + { + DisposeEntry(i, ETrue); + return; + } + } + ASSERT(NULL == aObject); +} + +void CMIDToolkit::DestroyUi() +{ + // + // Cleanup any components which have not been finalized yet. + // + // This is the last change to finalize them. + // + const TInt count = iObjects.Count(); + for (TInt i=count-1; i>=0; --i) + { + DisposeEntry(i, EFalse); + } + + if (iGrFactory) + { + iGrFactory->Dispose(); + iGrFactory = NULL; + } + + if (iUtils) + { + if (iEnv) + { + iEnv->SetUtils(NULL); + } + iUtils->Dispose(); + iUtils = NULL; + } + + if (iUiFactory) + { + iUiFactory->Dispose(); + iUiFactory = NULL; + } + + iGrLibrary.Close(); + + delete iEnv; + iEnv = NULL; +} + +/** + * DESTRUCTION PHASE 3 - SERVER SIDE + * + * This method is called when the event source has no more references + * and is about to be deleted. It is called in the context of the + * server thread, allowing server side resources to be cleaned up. + * + * It is called before FinalizeJni() so there may still be live JNI + * weak references contained in MMIDComponent objects referenced by + * the iObjects array. + * + * If SvrConstructL fails, the calling thread is responsible for calling + * Dispose() on the toolkit, which will lead to FinalizeSvr being called + * in the context of the server thread. This is therefore the appropriate + * place to cleanup server side resources. + * + * Like any normal destructor it should be able to cope with cleaning up + * partically constructed objects. Unlike a normal destructor, additional + * code (including FinalizeJni and the real destructor) will be run *after* + * this method - so any instance variables that could be queried by these + * methods should be cleaned up appropriately. + * + * Here we take down instance members in reverse order that they were + * allocated/constructed. + * + */ +void CMIDToolkit::FinalizeSvr() +{ + LCDUI_DEBUG_INT("CMIDToolkit::FinalizeSvr(%d) DESTRUCTOR PHASE 3", (TInt)this); + + switch (iPhase) + { + case ENone: + ASSERT(iPhase != ENone); + break; + + case EPhase1: + case EPhase2: + return; + + case EPhase3: + iPhase = EPhase2; + break; + } + + // Always use exit effect when exiting midlet + GfxTransEffect::BeginFullScreen(AknTransEffect::EApplicationExit, TRect(), + AknTransEffect::EParameterType, AknTransEffect::GfxTransParam(iAppUid)); + + + // + // Send MIDlet to background. + // + ClearDisplayable(); + +#ifdef CLEAR_TASKLIST_IN_CLOSE + // + // Remove tasklist entry. + // + iAppUid.iUid=0; + SetTaskListEntry(EFalse); +#endif + + DestroyUi(); + + if (iCoeEnv) + { + // + // Refuse focus + // + iCoeEnv->RootWin().EnableReceiptOfFocus(EFalse); + iCoeEnv = NULL; + } + + if (RLcdui::Get()->Plugin()) + { + RLcdui::Get()->Plugin()->SetObserver(NULL); + } + + DestroyUi(); + + iWgName = NULL; + + iCurrentDisplayable = NULL; + +} + +/** + * DESTRUCTION PHASE 2 - Java Side. + * + * Multi-thead note: + * + * Although this method runs Java side, there should be no remaining server + * side references to the object by the time this method runs. It is safe + * to access server side data structures - such as the disposed reference + * queue. + * + */ +void CMIDToolkit::FinalizeJni(JNIEnv& aJni) +{ + LCDUI_DEBUG_INT("CMIDToolkit::FinalizeJni(%d) DESTRUCTION PHASE 2", (TInt)this); + + switch (iPhase) + { + case ENone: + ASSERT(iPhase != ENone); + break; + + case EPhase1: + // We didn't even get as far as running ConstructL() + return; + + case EPhase2: + // We got at least part way through ConstructL(). + iPhase = EPhase1; + break; + + case EPhase3: + ASSERT(iPhase != EPhase3); + break; + } + + // + // There should be no more entries in the object map, only + // entries on the finalization queue. + // + ASSERT(0 == iObjects.Count()); + + FinalizeReferences(aJni); // dispose finalize queue + + // + // MUTEX NOTE: FinalizeMutex not needed as the calling + // thread holds the last reference. + // + iFinalizeQueue = iDisposedQueue; + iFinalizeCount = iDisposedCount; + iDisposedQueue = NULL; + iDisposedCount = 0; + + FinalizeReferences(aJni); // dispose finalize queue + + delete iHomeDir; + iHomeDir = NULL; + + delete iMidletSuite; + iMidletSuite = NULL; +} + +void CMIDToolkit::DisposeEntry(TInt aIndex, TBool aPostEvent) +{ + TObjectEntry* entry = iObjects[aIndex]; + iObjects.Remove(aIndex); + + if (entry->iComponent) + { + /* + * Make weak ref available for cleanup. + */ + entry->iDisposed = entry->iComponent->iPeer; + entry->iComponent->iPeer = NULL; + entry->iComponent->Dispose(); + entry->iComponent = NULL; + } + + if (entry->iDisposed) + { + // + // Park entry on the dispose queue. + // + entry->iNextEntry = iDisposedQueue; + iDisposedQueue = entry; + iDisposedCount++; + + // MUTEX NOTE - can test iFinalizeQueue as we only write it when NULL + // in which case no-one else will be reading/writing. + if (aPostEvent && (iDisposedCount > KPayload) && (NULL == iFinalizeQueue)) + { + iFinalizeMutex.Wait(); + iFinalizeQueue = iDisposedQueue; + iFinalizeCount = iDisposedCount; + PostEvent(new CMIDFinalizeEvent); + iDisposedQueue = NULL; + iDisposedCount = 0; + iFinalizeMutex.Signal(); + } + } + else + { + // + // There is no peer to dispose, so we are free to + // delete the entry immediately, or part it on + // on a free list. + // + delete entry; + } +} + +void TRevertCurrent::Revert(TAny* aPtr) +{ + TRevertCurrent& revert = *static_cast(aPtr); + revert.iCurrentPointer = revert.iPrevious; +} + + +void CMIDFinalizeEvent::Dispatch(JNIEnv& aJni) +{ + Object().FinalizeReferences(aJni); +} + +CMIDToolkit::TObjectEntry::TObjectEntry(MMIDComponent* aComponent) + : iComponent(aComponent) + , iDisposed(NULL) +{ +} + +TInt CMIDToolkit::New +( + JNIEnv& aJni, + jobject aPeer, + TJavaEventServer aServer, + const TDesC& aAppName, + TInt aAppUid, + const TDesC& aAppHome, + RPointerArray* aAttributes +) +{ + TRAPD(handle, handle=CreateToolkitL(aJni, aPeer, aServer, aAppName, aAppUid, aAppHome, aAttributes)); + return handle; +} + +TInt CMIDToolkit::CreateToolkitL +( + JNIEnv& aJni, + jobject aPeer, + TJavaEventServer aServer, + const TDesC& aAppName, + TInt aAppUid, + const TDesC& aAppHome, + RPointerArray* aAttributes +) +{ + TConstructor self(aJni); + self->ConstructL(aJni,aPeer,aServer,aAppName,aAppUid,aAppHome,aAttributes); + return self.GetHandle(); +} + +TBool CMIDToolkit::CheckEvent(CJavaEventBase* /* aEvent */) +{ + return iOpen; +} + +void CMIDToolkit::FinalizeReferences(JNIEnv& aEnv) +{ + TObjectEntry* queue = NULL; + TInt count = 0; + + iFinalizeMutex.Wait(); + + queue = iFinalizeQueue; + count = iFinalizeCount; + + iFinalizeQueue = NULL; + iFinalizeCount = 0; + + iFinalizeMutex.Signal(); + + while (queue) + { + TObjectEntry* next = queue->iNextEntry; + ASSERT(queue->iDisposed); + aEnv.DeleteWeakGlobalRef((jweak)(queue->iDisposed)); + delete queue; + queue = next; + --count; + } + + ASSERT(0 == count); +} + +CMIDletSuite::CMIDletSuite() + :iAttributes() +{ +} + +/** + * Takes ownership of pointed objects. + */ +void CMIDletSuite::SetAttributesL(RPointerArray& aAttributes) +{ + const TInt count = aAttributes.Count(); + for (TInt i=0; iGetAttribute(aAttributeName, aAttributeValue); +} + + +TInt CMIDToolkit::PostDisplayEvent(TEventType aEvent) +{ + // + // We pass the toolkit peer as CMIDEvent checks the source weak ref and + // will nop any events to expired objects. + // + jweak toolkit = Peer(); + + CMIDEvent* event = new CMIDEvent(iHandleDisplayEvent, toolkit, aEvent); + + if (event) + { + return PostEvent(event); + } + return KErrNoMemory; +} + +TInt CMIDToolkit::PostDisplayableEvent(MMIDComponent& aDisplayable, TEventType aEvent, TInt aParam0, TInt aParam1) +{ + jobject displayable = MIDJOBJECT(&aDisplayable); + +// Even if displayable is null it is safe to post the event as the event will +// dispose itself without posting itself. + CMIDEvent* event = new CMIDEvent(iHandleDisplayableEvent, displayable, aEvent, aParam0, aParam1); + if (event) + { + return PostEvent(event); + } + return KErrNoMemory; +} + +TInt CMIDToolkit::PostItemEvent(MMIDComponent& aItem, TEventType aEvent, TInt aParam0, TInt aParam1, TInt aParam2) +{ + jobject item = MIDJOBJECT(&aItem); + ASSERT(item); + CMIDEvent* event = new CMIDEvent(iHandleItemEvent, item, aEvent, aParam0, aParam1, aParam2); + if (event) + { + return PostEvent(event); + } + return KErrNoMemory; +} + +TInt CMIDToolkit::PostCanvasGraphicsItemPainterEvent(MMIDComponent& aCanvasGraphicsItemPainter, + TEventType aEvent, TInt aParam0, TInt aParam1) +{ + jobject canvasgraphicsitempainter = MIDJOBJECT(&aCanvasGraphicsItemPainter); + CMIDEvent* event = new CMIDEvent(iHandleCanavsGraphicsItemPainterEvent, canvasgraphicsitempainter, + aEvent, aParam0, aParam1); + if (event) + { + return PostEvent(event); + } + return KErrNoMemory; +}