/*
* Copyright (c) 2005-2006 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: Implementation for peninput server session class
*
*/
//INCLUDE FILES
#include <e32svr.h>
#include "peninputcmd.h"
#include "peninputclientserver.h"
#include "peninputanimcommand.h"
#include "peninputserver.h"
#include "peninputserversession.h"
const TInt KAllEventIndex = -1;
const TInt KFirstEventIndex = 0;
const TInt KMaxEventBuf = 50;
// ======== MEMBER FUNCTIONS ========
// ---------------------------------------------------------------------------
// CPeninputServerSession::CPeninputServerSession
// ---------------------------------------------------------------------------
//
CPeninputServerSession::CPeninputServerSession( RThread &aClient,
CPeninputServer& aServer)
: iPenInputSvr( aServer ),
iObserverActive(EFalse),
iCombinedMsgNum(0),
iCombinedEventId(ESignalKeyEvent),
iAppInfoType(EAppIndicatorMsg),
iDisabledUiType(0)
{
iPenInputSvr.IncreaseSessionCount();
iClientId = aClient.Id();
RProcess process;
if ( KErrNone == aClient.Process( process ) )
{
iClientProcess = process.Id();
process.Close();
}
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::ConstructL
// ---------------------------------------------------------------------------
//
void CPeninputServerSession::ConstructL()
{
iAppInfo = KNullDesC().AllocL();
iCombinedEventBuf.CreateMaxL(KMaxEventBuf);
iCombinedEventBuf.Zero();
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::NewL
// ---------------------------------------------------------------------------
//
CPeninputServerSession* CPeninputServerSession::NewL( RThread &aClient,
CPeninputServer& aServer)
{
CPeninputServerSession* session = new(ELeave) CPeninputServerSession(
aClient, aServer);
CleanupStack::PushL(session);
session->ConstructL();
CleanupStack::Pop(session);
return session;
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::ServiceL
// Possible leave is handled by the CPeninputServer::RunError
// ---------------------------------------------------------------------------
//
void CPeninputServerSession::ServiceL( const RMessage2& aMessage )
{
switch ( aMessage.Function() )
{
case EPeninputServerRequestMessageNotification:
// asynchnorous observation request issued, store it
// a client can have only one observation request at a time
if(!iObserverActive)
{
iPendingRequest = aMessage;
iObserverActive = ETrue;
//if already some events buffered,send the event
if(iDataBuf.Count())
{
iPendingRequest.Complete(iSignalCodeArray[0]);
iObserverActive = EFalse;
}
}
else
{
// cancel this request because notify request has already been issued
aMessage.Complete(KErrCancel);
}
break;
case EPeninputServerCancelMessageNotification:
{
aMessage.Complete(KErrNone);
if(iObserverActive)
{
iPendingRequest.Complete(KErrCancel);
iObserverActive = EFalse;
}
ProcessPendingEventBeforeExit();
//iSemaphore.Signal();
}
break;
default:
{
//TRAPD(err, DoServiceL(aMessage));
//if(KErrNone != err)
// aMessage.Complete(err);
TInt ret = DoServiceL(aMessage);
//aMessage.Complete(ret);
}
}
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::GetDisabledLayouts
// ---------------------------------------------------------------------------
//
const TProcessId& CPeninputServerSession::ClientProcessId( )
{
return iClientProcess ;
}
TInt CPeninputServerSession::BuildEventData()
{
if(iCombinedMsgNum > 0) //the previous combined msg was not sent yet. No need to do again
return iCombinedMsgNum;
TInt n = 0;
//check how many signal can be combined
while( n < iSignalCodeArray.Count() && iSignalCodeArray[n] == iCombinedEventId)
++n;
if(n <= 0)
return 0;
iCombinedMsgNum = 0;
for(; iCombinedMsgNum < n ; ++iCombinedMsgNum)
{
//check memory fist
if(iCombinedEventBuf.MaxLength() < iCombinedEventBuf.Length() + iDataBuf[iCombinedMsgNum]->Length())
{
TInt err = iCombinedEventBuf.ReAlloc( KMaxEventBuf +
iCombinedEventBuf.Length() +
iDataBuf[iCombinedMsgNum]->Length());
if(err != KErrNone)
{
break;
}
}
//copy data
iCombinedEventBuf.Append(*(iDataBuf[iCombinedMsgNum]));
}
return iCombinedMsgNum;
}
void CPeninputServerSession::RemoveEventDatas(TInt aNum)
{
aNum = aNum > 0 ? aNum : 1;
for(TInt i = 0 ; i < aNum; ++i)
RemoveEventDataByIdx(KFirstEventIndex);
iCombinedEventBuf.Zero();
iCombinedMsgNum = 0;
}
TInt CPeninputServerSession::SendEventData(const RMessage2& aMessage, const TDesC& aData)
{
TInt ret = KErrNone;
TInt maxBufLen = aMessage.Int0();
if(maxBufLen >= aData.Length())
{
TRAP_IGNORE(aMessage.WriteL(1,aData));
//remove the data
RemoveEventDatas(iCombinedMsgNum > 0 ? iCombinedMsgNum : 1);
}
else
{
ret = aData.Length();
}
return ret;
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::DoServiceL
// Possible leave is handled by the CPeninputServer::RunError
// ---------------------------------------------------------------------------
//
TInt CPeninputServerSession::DoServiceL( const RMessage2& aMessage )
{
//TInt err = KErrNone;
TInt ret = KErrNone;
switch ( aMessage.Function() )
{
case EPeninputRequestUiNotificationCompleted:
{
RemoveEventDataByIdx(KFirstEventIndex);
iPenInputSvr.ExecutePendingAnimCmd();
}
break;
case EPeninputServerClearServerEvent:
{
RemoveEventDataByIdx(KAllEventIndex);
}
break;
case EPeninputRequestGetServerEventData:
{
if(iDataBuf.Count())
{
TInt combinedEventNum = BuildEventData();
if(combinedEventNum)
ret = SendEventData(aMessage,iCombinedEventBuf);
else
ret = SendEventData(aMessage,*iDataBuf[KFirstEventIndex]);
// if(ret == KErrNone)
// RemoveEventDatas(combinedEventNum);
}
else
{
aMessage.WriteL(1,KNullDesC);
}
}
break;
case EPeninputRequestGetServerEventDataNumber:
{
TInt num = iDataBuf.Count();
TPckgC<TInt> msg(num);
aMessage.WriteL(0,msg);
}
break;
case EPeninputRequestGetDisableLayout:
{
//TInt layoyts = 0;
//CPeninputServerSession* pSession = static_cast<CPeninputServerSession*>(aMessage.Session());
//GetProcessLayouts( pSession->ClientProcessId(), layoyts );
TInt dsaDisableUIType = iPenInputSvr.DisabledByDSA();
TInt orientationDisableType = iPenInputSvr.DisabledByOrientation();
if( dsaDisableUIType )
{
iDsaEverHappened = ETrue;
}
TPckg<TInt> msg(iDisabledUiType | dsaDisableUIType | orientationDisableType);
aMessage.WriteL(0,msg);
}
break;
case EPeninputRequestDisableLayout:
{
TInt layouts = aMessage.Int0();
//CPeninputServerSession* pSession = static_cast<CPeninputServerSession*>(aMessage.Session());
//SetProcessLayouts( pSession->ClientProcessId(), layouts );
if(layouts < 0 )
{
iDisabledUiType = 0; //reset.
}
else
{
iDisabledUiType |= layouts;
}
}
break;
case EPeninputRequestUiIsVisible:
case EPeninputServerRequestSetDisplayMode:
case EPeninputRequestUiEditorMaxLength:
case EPeninputRequestUiSetUiPos:
case EPeninputRequestUiGetUiPos:
case EPeninputRequestUiSendAppEditorText:
case EPeninputRequestActivateLayout:
case EPeninputRequestActivateLayoutInGlobalNotes:
case EPeninputRequestDimLayout:
case EPeninputRequestSetUiLayoutId:
case EPeninputRequestSetUiLayoutIdWithData:
case EPeninputRequestResourceChanged:
case EPenInputRequestGetImePluginIdList:
case EPenInputRequestGetPenSupportLanguages:
case EPeninputRequestIsForeground:
case EPeninputRequestSetForeground:
case EPeninputRequestRelinquishForeground:
case EPeninputRequestAddUiObserver:
case EPeninputRequestIsLayoutDimmed:
//case EPeninputRequestChangeUiObserverType:
case EPeninputRequestRemoveUiObserver:
//case EPeninputRequestDisableLayout:
case EPeninputRequestServerThreadId:
//case EPeninputRequestGetDisableLayout:
case EPeninputBackgroudDefaultOri:
case EPeninputRequestInternalDimLayout:
case EPeninputRequestDimResChangeLayout:
case EPeninputRequestSupportInputMode:
case EPeninputRequestSetInputLanguage:
ret = iPenInputSvr.HandleMessageL(aMessage);
break;
case EPeninputRequestUpdateAppInfo:
{
ret = HandleAppInfoChange(aMessage);
if (ret == EBadRequest)
{
PanicClient(aMessage,EBadRequest );
return EBadRequest;
}
}
break;
case EPeninputRequestHandleClientCommand:
{
ret = iPenInputSvr.HandleCommandL(aMessage);
}
break;
// requests we don't understand at all are a different thing,
// so panic the client here, this function also completes the message
default:
{
PanicClient(aMessage,EBadRequest );
return EBadRequest;
}
}
aMessage.Complete(ret);
return ret;
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::SignalClientL
// ---------------------------------------------------------------------------
//
TBool CPeninputServerSession::CompletePendingRequestL(TInt aSignalCode,
const TDesC& aEventData, int aPos)
{
TBool ok = EFalse;
HBufC* data = aEventData.AllocLC();
// iDataBuf.AppendL(data);
if(aPos < 0) //append to the end
{
iSignalCodeArray.Append(aSignalCode);
iDataBuf.AppendL(data);
}
else
{
iSignalCodeArray.Insert(aSignalCode,aPos);
iDataBuf.InsertL(data,aPos);
}
CleanupStack::Pop();//data
if(iObserverActive)
{
iPendingRequest.Complete(aSignalCode);
iObserverActive = EFalse;
ok = ETrue;
}
return ok;
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::SignalClientL
// ---------------------------------------------------------------------------
//
TBool CPeninputServerSession::SignalClientL(TInt aSignalCode,
const TDesC& aEventData)
{
return CompletePendingRequestL(aSignalCode,aEventData);
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::SignalUiActivationObserver
// ---------------------------------------------------------------------------
//
TBool CPeninputServerSession::SignalUiActivationObserver(TInt aSignalCode,
TInt aType)
{
//check registerd UI type
if((aType & iRegistedPenUiType) || (iRegistedPenUiType == EPluginInputModeAll))
{
//insert the notification event before other event as anim object is waiting
// for client process.
TInt i = iSignalCodeArray.Count() - 1;
for( ; i >=0 ; i--)
{
if(ESignalPenUiActivated == iSignalCodeArray[i] ||
ESignalPenUiDeActivated == iSignalCodeArray[i])
break;
}
TRAP_IGNORE( CompletePendingRequestL(aSignalCode,KNullDesC,++i) );
return ETrue;
}
return EFalse;
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::ProcessPendingEventBeforeExit
// ---------------------------------------------------------------------------
//
void CPeninputServerSession::ProcessPendingEventBeforeExit()
{
//only process pen ui notification event. Other events are discarded
//for(TInt i = 0; i < iDelayedCmd.Count(); i++)
//for(TInt i = 0; i < iDelayedCmd; i++)
{
iPenInputSvr.ExecutePendingAnimCmd();
// iDelayedCmd --;
}
//remove any command
for(TInt i = 0; i < iDataBuf.Count(); i++)
{
delete iDataBuf[i];
}
iDataBuf.Reset();
iSignalCodeArray.Reset();
//iDelayedCmd.Reset();
iDelayedCmd = 0;
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::PanicClient
// ---------------------------------------------------------------------------
//
void CPeninputServerSession::PanicClient(const RMessage2& aMessage,TInt aPanic)
{
aMessage.Panic(KPeninputServerName, aPanic);
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::~CPeninputServerSession
// ---------------------------------------------------------------------------
//
CPeninputServerSession::~CPeninputServerSession()
{
ProcessPendingEventBeforeExit();
iPenInputSvr.DecreaseSessionCount(this);
iPenInputSvr.DelProcessLayouts( iClientProcess );
iDataBuf.Close();
iSignalCodeArray.Close();
iCombinedEventBuf.Close();
//iDelayedCmd.Close();
delete iAppInfo;
}
// ---------------------------------------------------------------------------
// CPeninputServerSession::ClientId
// ---------------------------------------------------------------------------
//
TInt CPeninputServerSession::ClientId()
{
return iClientId;
}
void CPeninputServerSession::RemoveEventDataByIdx(TInt aIndex)
{
//remove all if aIndex < 0
if( aIndex == KAllEventIndex )
{
for(TInt i = iDataBuf.Count() - 1; i >= 0; i--)
{
HBufC* usedData = iDataBuf[i];
iDataBuf.Remove(i);
delete usedData;
iSignalCodeArray.Remove(i);
}
}
else
{
if( aIndex >= 0 && aIndex < iDataBuf.Count() )
{
HBufC* usedData = iDataBuf[aIndex];
iDataBuf.Remove(aIndex);
delete usedData;
iSignalCodeArray.Remove(aIndex);
}
}
}
//void CPeninputServerSession::AddDelayedCmd(TAnimationCommand aCmd)
void CPeninputServerSession::AddDelayedCmd()
{
//iDelayedCmd.Append(aCmd);
//iDelayedCmd++;
}
void CPeninputServerSession::RegisterPenUiType(TInt aType)
{
iRegistedPenUiType = aType;
}
TInt CPeninputServerSession::HandleAppInfoChange(const RMessage2& aMessage)
{
TInt ret = 0;
TRAP_IGNORE(ret = HandleAppInfoChangeL(aMessage));
return ret;
}
TInt CPeninputServerSession::HandleAppInfoChangeL(const RMessage2& aMessage)
{
//TPeninputAppInfo type;
if (aMessage.Ptr0() == NULL || aMessage.Ptr1() == NULL)
{
return EBadRequest;
}
TPckg<TPeninputAppInfo> typeData(iAppInfoType);
TInt rst = aMessage.Read(KMsgSlot0,typeData);
if (rst != KErrNone)
{
return EBadRequest;
}
delete iAppInfo;
iAppInfo = NULL;
TInt len = aMessage.GetDesLength(KMsgSlot1);
if (len < 0)
{
return EBadRequest;
}
iAppInfo = HBufC::NewL(len);
TPtr appInfo = iAppInfo->Des();
rst = aMessage.Read(KMsgSlot1,appInfo);
if (rst != KErrNone)
{
return EBadRequest;
}
return DoUpdateAppInfo();
}
TInt CPeninputServerSession::DoUpdateAppInfo()
{
return iPenInputSvr.HandleAppInfoChange(this,*iAppInfo,iAppInfoType);
}
TInt CPeninputServerSession::DisabledUiType()
{
return iDisabledUiType;
}
//end of implementation of Class CPeninputServerSession
// End of File