diff -r 000000000000 -r bde4ae8d615e os/graphics/windowing/windowserver/nga/SERVER/openwfc/CLIENT.CPP --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/windowing/windowserver/nga/SERVER/openwfc/CLIENT.CPP Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,2245 @@ +// Copyright (c) 1994-2010 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: +// Client handling +// +// + +#include "CLIENT.H" + +#include "ANIM.H" +#include "Direct.H" +#include "EVENT.H" +#include "KEYCLICK.H" +#include "server.h" +#include "gc.h" +#include "rootwin.h" +#include "windowgroup.h" +#include "wstop.h" +#include "panics.h" +#include "../CLIENT/w32comm.h" +#include "password.h" +#include "pointer.h" +#include <u32hal.h> // EHalGroupEmulator +#include "WsMemMgr.h" +#include <e32hashtab.h> // for RHashMap +#include "registeredsurfacemap.h" +#include <graphics/wselement.h> + +#include "windowelementset.h" +#include "drawresource.h" + +extern CDebugLogBase* wsDebugLog; +_LIT(KWSERVSessionPanicCategory,"WSERV"); + +GLREF_D TPtr nullDescriptor; + +TWsCmdHeaderBase CWsClient::iCurrentCommand; +TBuf8<EClientBufferMaxSize> CWsClient::iCmdBuf; +TInt CWsClient::iReply; +TInt CWsClient::iReplyOffset; +CWsClient* CWsClient::iCurrentClient; +CWsObject* CWsClient::iDestObj; +const TUint8* CWsClient::iNextCmd; + +TUint CWsClient::iConnectionId = CDebugLogBase::EDummyConnectionId+1; +CArrayFixFlat<CWsClient::TWsCursorArrayItem>* CWsClient::iSystemPointerCursors = NULL; +TInt CWsClient::iDefaultSystemPointerCursorIndex = 0; //Negative when there isn't one +CWsPointerCursor* CWsClient::iDefaultSystemPointerCursor; +CWsClient* CWsClient::iSystemPointerCursorListOwner = NULL; +CArrayFixFlat<CWsClient::TWsCursorArrayItem>* CWsClient::iTextCursorArray = NULL; + +TKeyArrayFix CWsClient::iCursorKey(_FOFF(CWsClient::TWsCursorArrayItem,iIndex), ECmpTInt); + +/** +Used for enforcing the redraw calling convention in emulator builds. +When enabled this will panic any client calling a CWindowGc draw operation outside a +RWindow::BeginRedraw() / RWindow::EndRedraw() pair (known as non-redraw drawing). + +Enable by adding "debug_wserv_exe_EnforceRedrawCallingConvention X" to epoc.ini +where X is either 0 (zero) for "off" or 1 (one) for "on". + +Then enable globally in WServ AutoFlush by defining __AUTO_FLUSH in ../client/client.h +or locally by calling RWsSession::SetAutoFlush(ETrue) for a specific client programatically, +or locally pressing Ctrl-Alt-Shift-F in the emulator. +*/ +TBool CWsClient::iDebug_EnforceRedrawCallingConvention = EFalse; + +// Security policy stings +static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_WriteDeviceData,ECapabilityWriteDeviceData); +static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_SwEvent,ECapabilitySwEvent); +static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_PowerMgmt,ECapabilityPowerMgmt); + +// +// class CWsClient +// + +CWsClient::CWsClient(RThread aClient) : iClient(aClient), iGraphicMessageQueue(this), iInternalFlags(ERemoveKeyCode|EFinishedProcessingCommands) + { + iScreen = CWsTop::Screen(); + } + +CWsClient::~CWsClient() + { + CWsTop::WindowServer()->RemoveAllGraphicDrawers(*this); // deindexes all graphic drawers owned by this client + + delete iTempCustomTextCursor.iCursor; + FreeSystemPointerCursorList(); + CWsTop::ClientDestroyed(this); + if (wsDebugLog) + { + _LIT(ClientDestuct,"Client %d destructing"); + wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate,ClientDestuct, iConnectionHandle); + } + + iInternalFlags |= EClientIsClosing; + delete iObjectIndex; + delete iEventQueue; + delete iRedrawQueue; + delete iPriorityKeyEvent; + CWsTop::ClearSurfaceMap(this); + + CWsTop::SessionExited(this); + iClient.Close(); + } + +void CWsClient::CompleteInitializationL() + { + iObjectIndex = new(ELeave) CWsObjectIx(); + iObjectIndex->ConstructL(); + + iEventQueue = new(ELeave) CEventQueue(this); + iEventQueue->ConstructL(); + + iRedrawQueue = new(ELeave) CRedrawQueue(this); + iRedrawQueue->ConstructL(); + + iPriorityKeyEvent = new(ELeave) CPriorityKey(this); + + CWsCliObj::NewL(this); + + iComputeMode = RWsSession::EPriorityControlComputeOff; + + CWsTop::NewSession(this); + +#ifdef __WINS__ + TBool halValue = EFalse; + if (UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty, + (TAny*)"debug_wserv_exe_EnforceRedrawCallingConvention", &halValue) == KErrNone) + { + iDebug_EnforceRedrawCallingConvention = halValue; + } +#endif + + iInternalFlags |= EIsInitialised; + } + +TBool CWsClient::DebugEnforceRedrawCallingConvention() + { + return iDebug_EnforceRedrawCallingConvention; + } + +void CWsClient::StartInitializationL(TUint aConnectionHandle) + { + if (wsDebugLog) + wsDebugLog->NewClient(aConnectionHandle); + + if (iObjectIndex) + PPanic(EWservPanicReInitialise); + else + { + iConnectionHandle = aConnectionHandle; + CompleteInitializationL(); + } + } + +// +// Convert a handle to object checking it is of the correct type. +// +void CWsClient::HandleToWindow(TInt aHandle,CWsWindowBase** pWin) + { + if ((*pWin=(CWsWindowBase* )HandleToObjUntyped(aHandle))==NULL || + ((*pWin)->Type()!=WS_HANDLE_WINDOW && (*pWin)->Type()!=WS_HANDLE_GROUP_WINDOW)) + PPanic(EWservPanicWindow); + } + +// +// Convert a handle to object checking it is of the correct type. +// +void CWsClient::HandleToClientWindow(TInt aHandle,CWsClientWindow** pWin) + { + if ((*pWin=(CWsClientWindow*)HandleToObj(aHandle, WS_HANDLE_WINDOW))==NULL) + PPanic(EWservPanicWindow); + } + +void CWsClient::CreateNewPointerCursorL(const TWsClCmdCreatePointerCursor &aCmd) + { + CWsPointerCursor* pc=new(ELeave) CWsPointerCursor(this); + CleanupStack::PushL(pc); + pc->ConstructL(aCmd); + CleanupStack::Pop(); + } + +// Create a new custom text cursor +void CWsClient::StartSetCustomTextCursorL(const TWsClCmdCustomTextCursorData& aCmd) + { + if (!iTextCursorArray) + { + const TInt textCursorArrayGranularity = 4; + iTextCursorArray = new(ELeave) CArrayFixFlat<TWsCursorArrayItem>(textCursorArrayGranularity); + } + + TInt arrayIndex = KErrNotFound; + if (FindCursorArrayItem(iTextCursorArray, aCmd.identifier, arrayIndex)) + User::Leave(KErrAlreadyExists); + + delete iTempCustomTextCursor.iCursor; + iTempCustomTextCursor.iCursor = NULL; + iTempCustomTextCursor.iCursor = new(ELeave) CWsCustomTextCursor(this, aCmd.alignment); + + static_cast<CWsCustomTextCursor*>(iTempCustomTextCursor.iCursor)->ConstructL(aCmd.flags); + iTempCustomTextCursor.iIndex = aCmd.identifier; + } + +// Add new custom text cursor to global list +void CWsClient::CompleteSetCustomTextCursorL(TInt aError) + { + if (aError) + { + delete iTempCustomTextCursor.iCursor; + iTempCustomTextCursor.iCursor = NULL; + User::Leave(aError); + } + + TWsCursorArrayItem entry = iTempCustomTextCursor; + iTempCustomTextCursor.iCursor = NULL; + CleanupStack::PushL(entry.iCursor); + + TInt arrayIndex; + if (FindCursorArrayItem(iTextCursorArray, entry.iIndex, arrayIndex)) + User::Leave(KErrAlreadyExists); + else + iTextCursorArray->InsertIsqL(entry, iCursorKey); + + CleanupStack::Pop(entry.iCursor); + } + +CWsCustomTextCursor* CWsClient::FindCustomTextCursor(TInt aIdentifier) + { + TInt arrayIndex; + if (!FindCursorArrayItem(iTextCursorArray, aIdentifier, arrayIndex)) + return NULL; + + return TextCursor(arrayIndex); + } + +void CWsClient::CreateNewSpriteL(const TWsClCmdCreateSprite &aCmd) + { + CWsSprite* sprite = new(ELeave) CWsSprite(this); + CleanupStack::PushL(sprite); + sprite->ConstructL(aCmd); + CleanupStack::Pop(); + } + +void CWsClient::CreateNewBitmapL(const TWsClCmdCreateBitmap &aCmd) + { + DWsBitmap* bitmap = new(ELeave) DWsBitmap(this); + CleanupStack::PushL(bitmap); + bitmap->ConstructL(aCmd); + CleanupStack::Pop(); + } + +/** Creates a new window. + +If the parent is a window group then a new CWsTopClientWindow instance is created. If the parent is +a window then a new CWsClientWindow instance is created. + +@param aCmd The command received from the client +@internalComponent +@released +*/ +void CWsClient::CreateNewWindowL(const TWsClCmdCreateWindow &aCmd) + { + CWsWindowBase* parent; + HandleToWindow(aCmd.parent,&parent); + CWsClientWindow* win = NULL; + TBool deviceIsInvalid = EFalse; + CScreen* screen = parent->Screen(); + if (parent->WinType()==EWinTypeGroup) + { + __ASSERT_DEBUG(!((CWsWindowGroup*)parent)->ScreenDeviceDeleted(),PPanic(EWservPanicGroupWinScreenDeviceDeleted)); + win=new(ELeave) CWsTopClientWindow(this, screen); + deviceIsInvalid=!((CWsWindowGroup*)parent)->ScreenDeviceValid(); + } + else + win=new(ELeave) CWsClientWindow(this, screen); + + CleanupStack::PushL(win); + win->ConstructL(aCmd,parent,deviceIsInvalid); + CleanupStack::Pop(win); + } + +void CWsClient::CreateNewWindowGroupL(const TWsClCmdCreateWindowGroup &aCmd) + { + CWsWindowGroup::NewL(this, NULL, aCmd); //screen is initialised inside the constructL + } + +void CWsClient::CreateNewAnimDllL(const TWsClCmdUnion &aParams) + { + CWsAnimDll* animDll = new(ELeave) CWsAnimDll(this); + CleanupStack::PushL(animDll); + animDll->LoadL(BufferTPtr((TText*)(aParams.LoadAnimDll+1),aParams.LoadAnimDll->length)); + CleanupStack::Pop(); + } + +void CWsClient::CreateNewScreenDeviceL(TInt aDefaultScreenNumber, TUint aClientScreenDevicePointer) + { + DWsScreenDevice* screenDevice = new(ELeave) DWsScreenDevice(this, aDefaultScreenNumber,aClientScreenDevicePointer); + CleanupStack::PushL(screenDevice); + screenDevice->ConstructL(); + CleanupStack::Pop(screenDevice); + if (iPrimaryScreenDevice==NULL) + { + iPrimaryScreenDevice=screenDevice; + // When client create screen device, change default screen to the one specified. + // Client should do this immediately after establishing session + iScreen = iPrimaryScreenDevice->Screen(); + InitialiseScreenDevices(); + } + } + +void CWsClient::InitialiseScreenDevices() + { + const TWsObject* ptr = iObjectIndex->FirstObject(); + const TWsObject* end = ptr+iObjectIndex->Length(); + WS_ASSERT_DEBUG(ptr->iObject==NULL, EWsPanicObjectIndexError); + while(++ptr<end) + { + if (ptr->iObject && ptr->iObject->Type()==WS_HANDLE_GROUP_WINDOW) + { + CWsWindowGroup* gw = static_cast<CWsWindowGroup*>(ptr->iObject); + if(!gw->Device()) + gw->SetScreenDevice(iPrimaryScreenDevice); + } + } + } + +void CWsClient::CreateNewClickHandlerL(const TUid& aUid) + { + CClick* click = new(ELeave) CClick(this); + CleanupStack::PushL(click); + click->ConstructL(aUid); + CleanupStack::Pop(click); + } + +void CWsClient::RequestComplete(TRequestStatus* &aStatus, TInt aErr) + { + Client().RequestComplete(aStatus,aErr); + } + +void CWsClient::PanicCurrentClient(TClientPanic aPanic) + { + iCurrentClient->PPanic(aPanic); + } + +void CWsClient::PPanic(TClientPanic aPanic) const +//This function is allowed to leave with out the 'L' convention for special reasons + { + SessionPanic(aPanic); + User::Leave(EPanicLeave); + } + +void CWsClient::SessionPanic(TClientPanic aReason) const + { + if (wsDebugLog) + wsDebugLog->Panic(iConnectionHandle, aReason); + + if (!(iInternalFlags&EPanicClientAsSoonAsPossible)) // keep the first error code + { + iInternalFlags |= EPanicClientAsSoonAsPossible; + iPanicReason = aReason; + } + } + +void CWsClient::SessionTerminate() + { + if (wsDebugLog) + wsDebugLog->Panic(iConnectionHandle, 0); + + const RThread thread=Client(); + RProcess process; + if (thread.Process(process)==KErrNone) + { + process.Terminate(0); + process.Close(); + } + } + +/** +Returns the remaining space in the descriptor +*/ +TInt CWsClient::ReplyBufSpace() + { + const TInt retVal = iCurrentClient->ClientMessage().GetDesLength(KReplyBufferMessageSlot); + + if (iReplyOffset>=0 && retVal>=iReplyOffset) + return retVal-iReplyOffset; + else + return (retVal<0 ? retVal : KErrBadDescriptor); + } + +void CWsClient::ReplyBuf(const TDesC16 &aDes) // static + { + WS_ASSERT_DEBUG(!iCurrentClient->ClientMessage().IsNull(), EWsPanicInvalidMessageHandle); + + if(iCurrentClient->ClientMessage().Write(KReplyBufferMessageSlot,aDes,iReplyOffset) != KErrNone) + PanicCurrentClient(EWservPanicDescriptor); + + iReplyOffset += aDes.Length(); + if (wsDebugLog) + wsDebugLog->ReplyBuf(aDes); + } + +void CWsClient::ReplyBuf(const TDesC8 &aDes) // static + { + WS_ASSERT_DEBUG(!iCurrentClient->ClientMessage().IsNull(), EWsPanicInvalidMessageHandle); + + if(iCurrentClient->ClientMessage().Write(KReplyBufferMessageSlot, aDes, iReplyOffset) != KErrNone) + PanicCurrentClient(EWservPanicDescriptor); + + iReplyOffset += aDes.Length(); + if (wsDebugLog) + wsDebugLog->ReplyBuf(aDes); + } + +void CWsClient::ReplyBuf(const TAny* aSource, TInt aLength) // static +// +// Send a buffer to the client process. +// + { + TPtrC8 src(reinterpret_cast<const TUint8*>(aSource),aLength); + ReplyBuf(src); + } + +void CWsClient::ReplySize(const TSize &aSize) // static + { + ReplyBuf(&aSize, sizeof(aSize)); + } + +void CWsClient::ReplyPoint(const TPoint &aPoint) // static + { + ReplyBuf(&aPoint, sizeof(aPoint)); + } + +void CWsClient::ReplyRect(const TRect &aRect) // static + { + ReplyBuf(&aRect, sizeof(aRect)); + } + +void CWsClient::SetReply(TInt reply) + { + iReply = reply; + if (wsDebugLog) + wsDebugLog->Reply(reply); + } + +const TUint8* CWsClient::EndOfCommandBuffer() + { + return(iCmdBuf.Ptr()+iCmdBuf.Size()); + } + +const TPtrC CWsClient::BufferTPtr(TText *aStart,TInt aLen) + { + TPtrC ptr; + if (!BufferTPtrGc(aStart,aLen,ptr)) + PanicCurrentClient(EWservPanicBufferPtr); + return(ptr); + } + +TBool CWsClient::BufferTPtrGc(TText* aStart,TInt aLen, TPtrC& aPtr) + { + if (iCurrentCommand.iOpcode>0) + { + if ((REINTERPRET_CAST(TUint8*,aStart)<iCmdBuf.Ptr() + || REINTERPRET_CAST(TUint8*,aStart+aLen)>(iCmdBuf.Ptr()+iCmdBuf.Size()))) + return(EFalse); + } + else + { + if (aLen>=iCurrentCommand.iCmdLength) + return(EFalse); + } + aPtr.Set(aStart,aLen); + return(ETrue); + } + +const TPtrC8 CWsClient::BufferTPtr8(TUint8* aStart,TInt aLen) + { + if (iCurrentCommand.iOpcode>0 && (REINTERPRET_CAST(TUint8*,aStart)<iCmdBuf.Ptr() + || REINTERPRET_CAST(TUint8*,aStart+aLen)>(iCmdBuf.Ptr()+iCmdBuf.Size()))) + PanicCurrentClient(EWservPanicBufferPtr); + + return(TPtrC8(aStart,aLen)); + } + +/** +Process a command buffer + +@internalComponent +@released +*/ +void CWsClient::DispatchCommandsInBufL() // (step #4) + { + if (wsDebugLog) + { + wsDebugLog->CommandBuf(iConnectionHandle); + RThread client = Client(); + wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, client.FullName()); + } + const TUint8* endCmd=iCmdBuf.Ptr()+iCmdBuf.Length(); + do + { + const TWsCmdHeader* pCmd= + reinterpret_cast<const TWsCmdHeader*>(iNextCmd); + TUint opcode = pCmd->iBase.iOpcode; + TInt headerLen = sizeof(pCmd->iBase); + iCurrentCommand = pCmd->iBase; + + // For performance reasons the handle is only included + // if it is different from the previous command. The EWsOpcodeHandle + // flag indicates whether a new handle has been included in the + // current command. If not we use the same handle as the previous + // command. + if (opcode&EWsOpcodeHandle) + { + // Find the WServ object associated with this op code + opcode &= ~EWsOpcodeHandle; + iCurrentCommand.iOpcode = reinterpret_cast<TUint16&>(opcode); + iDestObj=HandleToObjUntyped(pCmd->iDestHandle); + headerLen = sizeof(*pCmd); + } + + iNextCmd += headerLen; + const TAny* cmdParams = iNextCmd; + iNextCmd += pCmd->iBase.iCmdLength; + if (!iDestObj || iNextCmd>endCmd) // Invalid handle or Corrupt buffer + { + SessionPanic(iDestObj==NULL ? EWservPanicHandle : EWservPanicBuffer); + iInternalFlags|=EFinishedProcessingCommands; + break; + } + + if (iNextCmd==endCmd) + iInternalFlags|=EFinishedProcessingCommands; + + if (wsDebugLog) + wsDebugLog->Command(iDestObj->Type(), opcode, cmdParams, iDestObj->LogHandle()); + + // Dispatch the command to the WServ object that will process it + iDestObj->CommandL(opcode, cmdParams); // (call #5) + } + while(iNextCmd<endCmd); + + } + +void CWsClient::DoServiceCommandBuf() // (step #3.1) + { + iCurrentClient=this; + iInternalFlags&=~EFinishedProcessingCommands; + TRAPD(err, DispatchCommandsInBufL()); // (call #4) + +#if defined(_DEBUG) + if (err!=KErrNone && !(iInternalFlags&(EFinishedProcessingCommands|EPanicClientAsSoonAsPossible))) + SessionPanic(EWservPanicFunctionLeave); +#endif + + if (err<KErrNone) + SetReply(err); + + if (iInternalFlags&(EFinishedProcessingCommands|EPanicClientAsSoonAsPossible)) + CompleteMessage(iClientMessage,iReply); // (finish) + + iCurrentClient=NULL; +#if defined(_DEBUG) + User::Heap().Check(); +#endif + } + +void CWsClient::ExecuteAsyncClientCommandL(TInt aOpcode, const RMessage2& aMessage) // (step #3.2) + { + switch(aOpcode) + { + case EWsClOpEventReady: + EventReady(aMessage); + break; + case EWsClOpPriorityKeyReady: + PriorityKeyEventReady(aMessage); + break; + case EWsClOpRedrawReady: + RedrawEventReady(aMessage); + break; + case EWsClOpGraphicMessageReady: + iGraphicMessageQueue.EventReady(aMessage); + break; + default: + { + PPanic(EWservPanicOpcode); + break; + } + } + } + + + +void CWsClient::ExecuteCommandL(TInt aOpcode, const TAny* aCmdData) // (step #6) + { + TWsClCmdUnion pData; + pData.any=aCmdData; + switch(aOpcode) + { + case EWsClOpCreateWindowGroup: + CreateNewWindowGroupL(*pData.CreateWindowGroup); + break; + case EWsClOpCreateWindow: + CreateNewWindowL(*pData.CreateWindow); + break; + case EWsClOpCreateGc: + CWsGc::NewL(this); + break; + case EWsClOpCreateAnimDll: + if (!CheckBuffer(pData.LoadAnimDll->length, KMaxFileName)) + PanicCurrentClient(EWservPanicBufferPtr); + CreateNewAnimDllL(pData); + break; + case EWsClOpCreateGraphic: + CWsGraphicDrawerObject::NewL(this,pData); + break; + case EWsClOpCreateScreenDevice: + { + const TInt screenNumber = pData.CreateScreenDevice->screenNumber; + const TUint clientScreenDevicePointer = pData.CreateScreenDevice->clientScreenDevicePointer; + if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens()) + { + PPanic(EWservPanicScreenNumber); + } + else + { + CreateNewScreenDeviceL(screenNumber,clientScreenDevicePointer); + } + } + break; + case EWsClOpCreateSprite: + CreateNewSpriteL(*pData.CreateSprite); + break; + case EWsClOpCreatePointerCursor: + CreateNewPointerCursorL(*pData.CreatePointerCursor); + break; + case EWsClOpStartSetCustomTextCursor: + StartSetCustomTextCursorL(*pData.CustomTextCursorData); + break; + case EWsClOpCompleteSetCustomTextCursor: + CompleteSetCustomTextCursorL(*pData.Int); + break; + case EWsClOpCreateBitmap: + CreateNewBitmapL(*pData.CreateBitmap); + break; + case EWsClOpCreateDirectScreenAccess: + CWsDirectScreenAccess::NewL(this,EFalse); + break; + case EWsClOpCreateDirectScreenAccessRegionTrackingOnly: + CWsDirectScreenAccess::NewL(this,ETrue); //creates a DSA object that will not draw to the screen, but will use just the region tracking functionality + break; + case EWsClOpCreateClick: + CreateNewClickHandlerL(*pData.Uid); + break; + case EWsClOpSetHotKey: + { + if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetHotKey API"))) + { + User::Leave(KErrPermissionDenied); + } + TWindowServerEvent::SetHotKeyL(*pData.SetHotKey); + } + break; + case EWsClOpClearHotKeys: + { + if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::ClearHotKeys API"))) + { + User::Leave(KErrPermissionDenied); + } + TWindowServerEvent::ClearHotKeysL(*pData.UInt); + } + break; + case EWsClOpRestoreDefaultHotKey: + TWindowServerEvent::ResetDefaultHotKeyL(*pData.UInt); + break; + case EWsClOpSetShadowVector: + PPanic(EWservPanicOpcode); //this op code is deprecated, should never be generated by the client + break; + case EWsClOpShadowVector: + PPanic(EWservPanicOpcode); //this op code is deprecated, should never be generated by the client + break; + case EWsClOpSetKeyboardRepeatRate: + { + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetKeyboardRepeatRate API"))) + { + User::Leave(KErrPermissionDenied); + } + if ((pData.SetKeyboardRepeatRate->initial.Int()<0) || (pData.SetKeyboardRepeatRate->time.Int()<0)) + { + User::Leave(KErrArgument); + } + CKeyboardRepeat::SetRepeatTime(pData.SetKeyboardRepeatRate->initial,pData.SetKeyboardRepeatRate->time); + } + break; + case EWsClOpGetKeyboardRepeatRate: + { + SKeyRepeatSettings settings; + CKeyboardRepeat::GetRepeatTime(settings.iInitialTime,settings.iTime); + ReplyBuf(&settings,sizeof(settings)); + } + break; + case EWsClOpSetDoubleClick: + { + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetDoubleClick API"))) + { + User::Leave(KErrPermissionDenied); + } + TWsPointer::SetDoubleClick(pData.SetDoubleClick->interval,pData.SetDoubleClick->distance); + } + break; + case EWsClOpGetDoubleClickSettings: + { + SDoubleClickSettings settings; + TWsPointer::GetDoubleClickSettings(settings.iInterval,settings.iDistance); + ReplyBuf(&settings,sizeof(settings)); + } + break; + case EWsClOpEventReady: + // No need to do anything + break; + case EWsClOpGetEvent: + HandleClientRequestForEventData(); + // Check flag if the group message queue is overflow and has pended messages + if (iInternalFlags & EWgMsgQueueOverflow) + { + iInternalFlags &= ~EWgMsgQueueOverflow; + CWsWindowGroup::ReleasePendedMessagesToAllGroups(this); + } + break; + case EWsClOpPurgePointerEvents: + PurgePointerEvents(); + break; + case EWsClOpEventReadyCancel: + CancelClientRequestForEventData(); + break; + case EWsClOpRedrawReady: + iInternalFlags&=~EIsPerformingRedrawEvent; + break; + case EWsClOpRedrawReadyCancel: + CancelClientRequestForRedrawEvent(); + break; + case EWsClOpGetRedraw: + HandleClientRequestForRedrawData(); + break; + case EWsClOpPriorityKeyReady: + // No need to do anything + break; + case EWsClOpPriorityKeyReadyCancel: + CancelClientRequestForPriorityKeyEvent(); + break; + case EWsClOpGetPriorityKey: + HandleClientRequestForPriorityKeyData(); + break; + case EWsClOpNumWindowGroups: + SetReply(CWsWindowGroup::NumWindowGroups(EFalse,* pData.Int)); + break; + case EWsClOpNumWindowGroupsAllPriorities: + SetReply(CWsWindowGroup::NumWindowGroups(ETrue, 0)); + break; + case EWsClOpNumWindowGroupsOnScreen: + { + const TInt screenNumber=pData.NumWinGroups->screenNumber; + if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens()) + PPanic(EWservPanicScreenNumber); + else + SetReply(CWsWindowGroup::NumWindowGroupsOnScreen(CWsTop::Screen(screenNumber)->RootWindow()->Child(),(pData.NumWinGroups->priority==EAllPriorities),pData.NumWinGroups->priority)); + } + break; + case EWsClOpWindowGroupList: + { + const TInt screenNumber=pData.WindowGroupList->screenNumber; + if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens()) + PPanic(EWservPanicScreenNumber); + else + SetReply(CWsWindowGroup::SendWindowGroupListL(screenNumber,(pData.WindowGroupList->priority==EAllPriorities), pData.WindowGroupList->priority, pData.WindowGroupList->count)); + } + break; + case EWsClOpWindowGroupListAllPriorities: + { + const TInt screenNumber=pData.WindowGroupList->screenNumber; + if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens()) + PPanic(EWservPanicScreenNumber); + else + SetReply(CWsWindowGroup::SendWindowGroupListL(screenNumber,ETrue, 0, pData.WindowGroupList->count)); + } + break; + case EWsClOpWindowGroupListAndChain: + SetReply(CWsWindowGroup::SendWindowGroupListAndChainL(EFalse, pData.WindowGroupList->priority, pData.WindowGroupList->count)); + break; + case EWsClOpWindowGroupListAndChainAllPriorities: + SetReply(CWsWindowGroup::SendWindowGroupListAndChainL(ETrue, 0, pData.WindowGroupList->count)); + break; + case EWsClOpGetDefaultOwningWindow: + { + const TInt screenNumber = *pData.Int; + if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens()) + PPanic(EWservPanicScreenNumber); + else + { + CScreen* screen = (screenNumber ==KDummyScreenNumber) ? iScreen : CWsTop::Screen(screenNumber); + SetReply(screen->DefaultOwningWindowGroup() ? screen->DefaultOwningWindowGroup()->Identifier():0); + } + } + break; + case EWsClOpGetFocusWindowGroup: + { + const TInt screenNumber = *pData.Int; + if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens()) + PPanic(EWservPanicScreenNumber); + else + CWsWindowGroup::GetFocusWindowGroupL(screenNumber); + } + break; + case EWsClOpSetWindowGroupOrdinalPosition: + CWsWindowGroup::WindowGroupFromIdentifierL(pData.SetWindowGroupOrdinalPosition->identifier)->SetOrdinalPosition(pData.SetWindowGroupOrdinalPosition->position); + break; + case EWsClOpGetWindowGroupHandle: + SetReply(CWsWindowGroup::WindowGroupFromIdentifierL(*pData.Int)->ClientHandle()); + break; + case EWsClOpGetWindowGroupOrdinalPriority: + SetReply(CWsWindowGroup::WindowGroupFromIdentifierL(*pData.Int)->OrdinalPriority()); + break; + case EWsClOpGetWindowGroupClientThreadId: + { + TThreadId id=CWsWindowGroup::WindowGroupFromIdentifierL(*pData.Int)->WsOwner()->Client().Id(); + ReplyBuf(&id,sizeof(id)); + } + break; + case EWsClOpSendEventToWindowGroup: + { + CWsWindowGroup* group=CWsWindowGroup::WindowGroupFromIdentifierL(pData.SendEventToWindowGroup->parameter); + TWsEvent event=pData.SendEventToWindowGroup->event; + event.SetHandle(group->ClientHandle()); + // Events in enum TEventCode is protected by capabilities + if (group->WsOwner()!=this && event.Type()>=EEventNull && event.Type()<EEventUser) + { + if (event.Type()<EEventPowerMgmt || event.Type()>=EEventReserved) + { + if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendEventToWindowGroup API"))) + User::Leave(KErrPermissionDenied); + } + else + { + if (!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendEventToWindowGroup API"))) + User::Leave(KErrPermissionDenied); + } + } + if (event.Type()==EEventKey && event.Key()->iRepeats!=0) + CKeyboardRepeat::CancelRepeat(NULL); //Otherwise we will trip an invarient + if (!group->EventQueue()->QueueEvent(event)) + User::Leave(KErrNoMemory); + } + break; + case EWsClOpSendEventToAllWindowGroup: + case EWsClOpSendEventToAllWindowGroupPriority: + case EWsClOpSendEventToOneWindowGroupPerClient: + { + TWsEvent event=pData.SendEventToWindowGroup->event; + if (event.Type()<0) + User::Leave(KErrArgument); + if(event.Type()<EEventUser) + { + if (event.Type()<EEventPowerMgmt || event.Type()>=EEventReserved) + { + if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendEventToAllWindowGroup API"))) + User::Leave(KErrPermissionDenied); + } + else + { + if (!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendEventToAllWindowGroup API"))) + User::Leave(KErrPermissionDenied); + } + } + if (!CWsWindowGroup::SendEventToAllGroups(aOpcode!=EWsClOpSendEventToAllWindowGroupPriority + ,aOpcode==EWsClOpSendEventToOneWindowGroupPerClient,*pData.SendEventToWindowGroup)) + User::Leave(KErrNoMemory); + } + break; + case EWsClOpSendMessageToWindowGroup: + { + CWsWindowGroup* group=CWsWindowGroup::WindowGroupFromIdentifierL(pData.SendMessageToWindowGroup->identifierOrPriority); + if (group->WsOwner()!=this) + { + if (!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendMessageToWindowGroup API"))) + { + User::Leave(KErrPermissionDenied); + } + } + group->QueueMessageL(pData.SendMessageToWindowGroup->uid, pData.SendMessageToWindowGroup->dataLength,* this); + } + break; + case EWsClOpSendMessageToAllWindowGroups: + case EWsClOpSendMessageToAllWindowGroupsPriority: + { + if ((pData.SendMessageToWindowGroup->dataLength<0) || (pData.SendMessageToWindowGroup->dataLength>=(KMaxTInt/2))) + { + User::Leave(KErrArgument); + } + CWsWindowGroup::SendMessageToAllGroupsL(*this,aOpcode==EWsClOpSendMessageToAllWindowGroups,*pData.SendMessageToWindowGroup); + } + break; + case EWsClOpFetchMessage: + CWsWindowGroup::WindowGroupFromIdentifierL(pData.FetchMessage->windowGroupIdentifier)->FetchMessageL(); + break; + case EWsClOpGetWindowGroupNameFromIdentifier: + ReplyGroupName(CWsWindowGroup::WindowGroupFromIdentifierL(pData.GetWindowGroupNameFromIdentifier->identifier)->GroupName(),pData.GetWindowGroupNameFromIdentifier->maxLength); + break; + case EWsClOpFindWindowGroupIdentifier: + { + if (pData.FindWindowGroupIdentifier->length<0) + User::Leave(KErrArgument); + TPtrC ptr(BufferTPtr((TText*)(pData.FindWindowGroupIdentifier+1),pData.FindWindowGroupIdentifier->length)); + SetReply(CWsWindowGroup::FindWindowGroupL(this, pData.FindWindowGroupIdentifier->identifier, + pData.FindWindowGroupIdentifier->offset,&ptr,NULL)->Identifier()); + } + break; + case EWsClOpFindWindowGroupIdentifierThread: + SetReply(CWsWindowGroup::FindWindowGroupL(this, pData.FindWindowGroupIdentifierThread->identifier,0,NULL, + &pData.FindWindowGroupIdentifierThread->threadId)->Identifier()); + break; + case EWsClOpSetBackgroundColor: + for(TInt i=0;i<CWsTop::NumberOfScreens();i++) + { + CWsTop::Screen(i)->RootWindow()->SetColor(*pData.rgb); + } + break; + case EWsClOpGetBackgroundColor: + SetReply(iScreen->RootWindow()->BackColor().Internal()); + break; + case EWsClOpClaimSystemPointerCursorList: + { + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::ClaimSystemPointerCursorList API"))) + { + User::Leave(KErrPermissionDenied); + } + ClaimSystemPointerCursorListL(); + } + break; + case EWsClOpFreeSystemPointerCursorList: + FreeSystemPointerCursorList(); + break; + case EWsClOpSetSystemPointerCursor: + { + CWsObject* pointercursor = NULL; + if ((pointercursor=HandleToObj(pData.SetSystemPointerCursor->handle, WS_HANDLE_POINTER_CURSOR))==NULL) + PPanic(EWservPanicSprite); + + SetSystemPointerCursorL(pData.SetSystemPointerCursor->number, (CWsPointerCursor* )pointercursor); + } + break; + case EWsClOpClearSystemPointerCursor: + ClearSystemPointerCursor(*pData.Int); + break; + case EWsClOpSetPointerCursorArea: + { + if(KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetPointerCursorArea API"))) + { + if (!iScreen->IsValidScreenSizeMode(*pData.Int)) + PPanic(EWservPanicScreenModeNumber); + iScreen->SetPointerCursorArea(pData.SetPointerCursorArea->mode,pData.SetPointerCursorArea->area); + } + } + break; + case EWsClOpPointerCursorArea: + if (!iScreen->IsValidScreenSizeMode(*pData.Int)) + PPanic(EWservPanicScreenModeNumber); + + ReplyRect(iScreen->GetPointerCursorArea(*pData.Int)); + break; + case EWsClOpSetPointerCursorMode: + { + CWsWindowGroup* focusWinGp=CWsTop::FocusWindowGroup(); + if (focusWinGp && focusWinGp->WsOwner()==this) + { + TWsPointer::SetPointerCursorMode(*pData.Mode); + TWsPointer::UpdatePointerCursor(); + } + } + break; + case EWsClOpSetClientCursorMode : + { + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetPointerCursorModeIfFocused API"))) + { + User::Leave(KErrPermissionDenied); + } + TWsPointer::SetPointerCursorMode(*pData.Mode); + TWsPointer::UpdatePointerCursor(); + } + break; + case EWsClOpPointerCursorMode: + SetReply(TWsPointer::PointerCursorMode()); + break; + case EWsClOpSetDefaultSystemPointerCursor: + SetDefaultSystemPointerCursor(*pData.Int); + break; + case EWsClOpClearDefaultSystemPointerCursor: + SetDefaultSystemPointerCursor(ENoDefaultSystemPointerCursor); + break; + case EWsClOpSetPointerCursorPosition: + { + CWsWindowGroup* focusWinGp=CWsTop::FocusWindowGroup(); + if ((!focusWinGp || focusWinGp->WsOwner()!=this)&& + (!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetPointerCursorPosition API")))) + { + User::Leave(KErrPermissionDenied); + } + TWsPointer::SetPointerCursorPos(*pData.Point); + } + break; + case EWsClOpPointerCursorPosition: + ReplyPoint(TWsPointer::PointerCursorPos()); + break; + case EWsClOpSetModifierState: + { + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetModifierState API"))) + { + User::Leave(KErrPermissionDenied); + } + TWindowServerEvent::SetModifierState(pData.SetModifierState->modifier,pData.SetModifierState->state); + } + break; + case EWsClOpGetModifierState: + SetReply(TWindowServerEvent::GetModifierState()); + break; + case EWsClOpHeapCount: + SetReply(CWsMemoryManager::Static()->Count()); + break; + case EWsClOpDebugInfo: + DebugInfoL(pData.DebugInfo->iFunction,pData.DebugInfo->iParam,EFalse); + break; + case EWsClOpDebugInfoReplyBuf: + DebugInfoL(pData.DebugInfo->iFunction,pData.DebugInfo->iParam,ETrue); + break; + case EWsClOpResourceCount: + SetReply(iObjectIndex->Count()); + break; + case EWsClOpHeapSetFail: + { + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::HeapSetFail API"))) + { + PPanic(EWservPanicPermissionDenied); + } +#if !defined(_DEBUG) + if (pData.HeapSetFail->type!=RHeap::ENone) + TWindowServerEvent::NotifyOom(); +#endif + // if there is a memory manager and we are making the allocator fail next or + // deteministic we want to make sure we test both when the memory manager + // succeeds and fails in allocating after freeing up memory. we do that by + // remapping the rate and explicitly telling the memory manager to fail: + // requested rate | fail on retry, actual rate + // 1 | true , 1 + // 2 | false , 1 + // 3 | true , 2 + CWsMemoryManager* memoryManager = NULL; + TInt rate = pData.HeapSetFail->value; + TBool memoryManagerRetryFail = EFalse; + if((pData.HeapSetFail->type == RAllocator::EFailNext || pData.HeapSetFail->type == RAllocator::EDeterministic)) + { + memoryManager = CWsMemoryManager::Static(); + if(memoryManager) + { + memoryManagerRetryFail = (rate % 2 == 1); + rate = rate / 2 + (memoryManagerRetryFail ? 1 : 0); + } + } + + switch (pData.HeapSetFail->type) + { //This log message means you can safely ignore the allocation failures in between + //see CWindowServer::ReleaseMemory() + case RAllocator::ENone: + RDebug::Printf("WSERV Heap: __DbgSetAllocFail() <<<ENone"); + break; + case RAllocator::EReset: + RDebug::Printf("WSERV Heap: __DbgSetAllocFail() <<<EReset"); + break; + default: + if (memoryManagerRetryFail) + RDebug::Printf("WSERV Heap: Memory Manager set to fail on retry"); + RDebug::Printf("WSERV Heap: __DbgSetAllocFail(EUser,%i,%i)>>>", pData.HeapSetFail->type, rate); + break; + } + + if (memoryManager && memoryManagerRetryFail) + memoryManager->SetFailNextRetry(); + + if (pData.HeapSetFail->burst >= 0) + User::__DbgSetBurstAllocFail(RHeap::EUser, pData.HeapSetFail->type, rate, pData.HeapSetFail->burst); + else + User::__DbgSetAllocFail(RHeap::EUser, pData.HeapSetFail->type, rate); + break; + } + case EWsClOpRawEvent: + { + if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SimulateRawEvent API"))) + { + PPanic(EWservPanicPermissionDenied); + } + TRawEvent event(*pData.RawEvent); + if (TWsPointer::PreProcessDriverEvent(event)) + TWindowServerEvent::ProcessRawEvent(event); + } + break; + case EWsClOpKeyEvent: + { + if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SimulateKeyEvent API"))) + { + PPanic(EWservPanicPermissionDenied); + } + TWindowServerEvent::ProcessKeyEvent(*pData.KeyEvent,0); + } + break; + case EWsClOpLogMessage: + if (wsDebugLog) + { + if (CheckBuffer(*pData.Int, KLogMessageLength)) + wsDebugLog->MiscMessage(CDebugLogBase::ELogImportant,BufferTPtr((TText* )(pData.Int+1),*pData.Int),0); + } + break; + case EWsClOpPasswordEntered: + CWsPassword::PasswordEntered(this); + break; + case EWsClOpComputeMode: + SetComputeMode(*pData.ComputeMode); + break; + case EWsClOpSendOffEventsToShell: + { + if(!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::RequestOffEvents API"))) + { + User::Leave(KErrPermissionDenied); + } + SetReply(CWsTop::SetSendOffEventsToShell(this,*pData.OffEventsToShell)); + } + break; + case EWsClOpGetDefModeMaxNumColors: + { + SDefModeMaxNumColors colors; + const TInt screenNumber = *pData.Int; + if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens()) + PPanic(EWservPanicScreenNumber); + else + { + CScreen* screen = (screenNumber==KDummyScreenNumber)?iScreen:CWsTop::Screen(screenNumber); + screen->MaxNumColors(colors.iColors,colors.iGrays); + colors.iDisplayMode=screen->FirstDefaultDisplayMode(); + } + ReplyBuf(&colors,sizeof(colors)); + } + break; + case EWsClOpGetColorModeList: + { + const TInt screenNumber = *pData.Int; + if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens()) + PPanic(EWservPanicScreenNumber); + else + SetReply((screenNumber==KDummyScreenNumber) ? iScreen->ColorModesFlag() : CWsTop::Screen(screenNumber)->ColorModesFlag()); + } + break; + case EWsClOpSetDefaultFadingParams: + { + if(KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetDefaultFadingParameters API"))) + { + iScreen->SetFadingParams(WservEncoding::ExtractFirst8BitValue(*pData.UInt),WservEncoding::ExtractSecond8BitValue(*pData.UInt)); + } + } + break; + case EWsClOpPrepareForSwitchOff: + { + if(KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::PrepareForSwitchOff API"))) + { + } + } + break; + case EWsClOpSetFaded: + { + // Deprecated - retained for BC with applications that retrieve the fade count + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetSystemFaded API"))) + User::Leave(KErrPermissionDenied); + + TUint8 blackMap; + TUint8 whiteMap; + if (pData.SetSystemFaded->UseDefaultMap()) + iScreen->GetFadingParams(blackMap,whiteMap); + else + pData.SetSystemFaded->GetFadingParams(blackMap,whiteMap); + + iScreen->RootWindow()->SetSystemFaded(pData.SetSystemFaded->Faded(),blackMap,whiteMap); + } + break; + case EWsClOpLogCommand: + CWsTop::LogCommand(*pData.LogCommand); + break; +#if defined(__WINS__) + case EWsClOpRemoveKeyCode: + iInternalFlags&=~ERemoveKeyCode; + if (*pData.Bool) + iInternalFlags|=ERemoveKeyCode; + break; + case EWsClOpSimulateXyInput: + TWsPointer::SetXyInputType(static_cast<TXYInputType>(*pData.XyInput)); + break; +#endif + case EWsClOpNoFlickerFree: + PPanic(EWservPanicOpcode); //not supported anymore + break; + case EWsClOpSetFocusScreen: + { + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetFocusScreen API"))) + { + User::Leave(KErrPermissionDenied); + } + TInt focusScreen=*pData.Int; + if (focusScreen>=0 && focusScreen<CWsTop::NumberOfScreens()) + SetReply(CWsTop::SetCurrentFocusScreen(focusScreen)); + else + SessionPanic(EWservPanicScreenNumber); + break; + } + case EWsClOpGetFocusScreen: + SetReply(CWsTop::CurrentFocusScreen()->ScreenNumber()); + break; + case EWsClOpGetNumberOfScreens: + SetReply(CWsTop::NumberOfScreens()); + break; + case EWsClOpClearAllRedrawStores: + CWsTop::ClearAllRedrawStores(); + break; + case EWsClOpGetGraphicMessage: + iGraphicMessageQueue.GetGraphicMessage(); + break; + case EWsClOpGraphicMessageCancel: + iGraphicMessageQueue.CancelRead(); + break; + case EWsClOpGraphicAbortMessage: + iGraphicMessageQueue.AbortMessage(*pData.Int); + break; + case EWsClOpGraphicFetchHeaderMessage: + SetReply(iGraphicMessageQueue.TopClientHandle()); + break; + case EWsClOpRegisterSurface: + SetReply(RegisterSurface(pData)); + break; + case EWsClOpUnregisterSurface: + UnregisterSurface(pData); + break; + case EWsClOpSetCloseProximityThresholds: + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(), + __PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetCloseProximityThresholds"))) + { + User::Leave(KErrPermissionDenied); + } + SetReply(TWsPointer::SetCloseProximityThresholds(pData.ZThresholdPair->enterThreshold, + pData.ZThresholdPair->exitThreshold)); + break; + case EWsClOpSetHighPressureThresholds: + if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(), + __PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetHighPressureThresholds"))) + { + User::Leave(KErrPermissionDenied); + } + SetReply(TWsPointer::SetHighPressureThresholds(pData.ZThresholdPair->enterThreshold, + pData.ZThresholdPair->exitThreshold)); + break; + case EWsClOpGetEnterCloseProximityThreshold: + SetReply(TWsPointer::GetEnterCloseProximityThreshold()); + break; + case EWsClOpGetExitCloseProximityThreshold: + SetReply(TWsPointer::GetExitCloseProximityThreshold()); + break; + case EWsClOpGetEnterHighPressureThreshold: + SetReply(TWsPointer::GetEnterHighPressureThreshold()); + break; + case EWsClOpGetExitHighPressureThreshold: + SetReply(TWsPointer::GetExitHighPressureThreshold()); + break; + case EWsClOpCreateDrawableSource: + CreateDrawableSourceL(*pData.CreateDrawableSource); + break; + case EWsClOpIndicateAppOrientation: + IndicateAppOrientation(*pData.Orientation); + break; + case EWsClOpUnregisterAllTFXEffect: + RDebug::Printf("[Bug 3344] OpCode EWsClOpUnregisterAllTFXEffect not supported."); + break; + default: + PPanic(EWservPanicOpcode); + break; + } + } +/** Debug information accessor. + * + * + **/ +void CWsClient::DebugInfoL(TInt aFunction, TInt aParam, TBool aHasReplyBuf) const + { + if (aFunction & EWsDebugClassMask) + SetReply(DebugInfoClassifiedL(aFunction,aParam,aHasReplyBuf)); + else + DebugInfoUnclassifiedL(aFunction,aParam,aHasReplyBuf); + } + +/** A wide variety of generally unconnected debug enquiries. + * + * + **/ +void CWsClient::DebugInfoUnclassifiedL(TInt aFunction, TInt aParam, TBool aHasReplyBuf) const + { + switch(aFunction) + { + case EWsDebugInfoHeap: + if (aHasReplyBuf) + { + TWsDebugHeapInfo heapInfo; + RHeap& heap=User::Heap(); + heapInfo.iCount=heap.AllocSize(heapInfo.iTotal); + heapInfo.iAvailable=heap.Available(heapInfo.iLargestAvailable); + ReplyBuf(&heapInfo,sizeof(heapInfo)); + } + SetReply(KErrArgument); + break; + case EWsDebugSetCheckHeapOnDisconnectClient: + if (!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::DebugInfo API"))) + { + User::Leave(KErrPermissionDenied); + } + CWsTop::SetCheckHeapOnDisconnectClient(this); + break; + case EWsDebugSetCheckHeapOnDisconnectMode: + if (!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::DebugInfo API"))) + { + User::Leave(KErrPermissionDenied); + } + CWsTop::SetCheckHeapOnDisconnectMode(STATIC_CAST(TWsCheckHeapOnDisconnectMode,aParam)); + break; + case EWsDebugFetchCheckHeapResult: + SetReply(CWsTop::FetchCheckHeapResult()); + break; + case EWsDebugSetEventQueueTest: + CWsWindowGroup::SetEventQueueTestState(aParam); + break; + default: + SetReply(KErrNotSupported); + break; + } + } + +/** Selects a debug function based on the class of debug query. + * + * + **/ +TInt CWsClient::DebugInfoClassifiedL(TInt aFunction, TInt aParam, TBool aHasReplyBuf) const + {//Duplicating the meanings of Classified... this would be a good place for a security check + //first part of param is always screen number + TInt buffSpace=aHasReplyBuf?ReplyBufSpace():0; + if (buffSpace<0) + return (buffSpace); + + const TInt screenNumber = (aParam&EWsDebugArgScreenMask)>>EWsDebugArgScreenShift; + const TInt functionClass = (aFunction&EWsDebugClassMask); + CScreen* screen = NULL; + if (functionClass<EWsDebugClassNonScreen) + { + if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens()) + return (KErrArgument); + + screen = CWsTop::Screen(screenNumber); + } + WS_ASSERT_DEBUG(screen, EWsPanicNoScreen); + switch (aFunction&EWsDebugClassMask) + { + case EWsDebugClassScreenUiElement: + return DebugInfoScreenUiL(aFunction,aParam,buffSpace,*screen); + case EWsDebugClassScreenElementSet: + return DebugInfoScreenElementSetL(aFunction, aParam, buffSpace, *screen); + case EWsDebugClassElementSetWindow: + return DebugInfoElementSetWindowL(aFunction, aParam, buffSpace, *screen); + case EWsDebugClassElementSetElement: + return DebugInfoElementSetElementL(aFunction, aParam, buffSpace, *screen); + + case EWsDebugClassClientWindow: + default: + return (KErrNotSupported); + } + } + +/** Returns debug info about the UIElement entries for a screen. + * This describes the general state or size of the element set. + * It is indexed via screen num, and optionally element index. + * Element index MUST BE 0 when not required. + * @return size of buffer required or error code. + **/ +TInt CWsClient::DebugInfoScreenUiL(TInt aFunction, TInt /* aParam */, TInt aReplyBufSize, CScreen& aScreen) const + { + switch(aFunction) + { + case EWsDebugGetFastpathMode: + { + // obsolete through preq2669 + WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState); + return KErrNotSupported; + } + + case EWsDebugSetFastpathMode: + { + // obsolete through preq2669 + WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState); + return KErrNotSupported; + } + + case EWsDebugGetUIElementInfoList: + { + // obsolete through preq2669 + WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState); + return KErrNotSupported; + } + + case EWsDebugGetUIElementBase: + { + // obsolete through preq2669 + WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState); + return KErrNotSupported; + } + + case EWsDebugGetUIElementIds: + { + // obsolete through preq2669 + WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState); + return KErrNotSupported; + } + + case EWsDebugGetSceneElementIdOrder: + { + // obsolete through preq2669 + WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState); + return KErrNotSupported; + } + case EWsDebugSetFastpathTestMode: + { + // obsolete through preq2669 + WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState); + return KErrNotSupported; + } + + case EWsDebugSetFastpathOomMode: + { + // obsolete through preq2669 + WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState); + return KErrNotSupported; + } + case EWsDebugGetUIElementConfig: + { + return DebugReturnConfig(aReplyBufSize,&aScreen.UiElement(),0); + + } + default: + return (KErrNotSupported); + } + } + +/** Returns debug info about the CWindowElementSet entry for a screen. + * This describes the general state or size of the element set + * It is indexed via screen num. + * @return size of buffer required or error code. + **/ +TInt CWsClient::DebugInfoScreenElementSetL(TInt aFunction, TInt /*aParam*/, TInt aReplyBufSize, const CScreen& aScreen) const + { + const CWindowElementSet& elementSet = aScreen.WindowElements(); + switch (aFunction) + { + case EWsDebugSerialSurfacesUpdated: + return 0; + + case EWsDebugSurfaceWindowList: + { + TInt outSize = elementSet.Count() * sizeof(TWsDebugWindowId); + if (outSize<=aReplyBufSize) + {//can stream, so I shall! + for (TInt index = 0; index < elementSet.Count(); index++) + { + const CWsClientWindow& win = *elementSet.DebugWindowAt(index); + TWsDebugWindowId id= + { + win.ClientHandle(), 0 + }; + if (win.WsOwner()!=this) + id.iOtherGroupId=win.WinGroup()->Identifier(); + ReplyBuf(&id, sizeof(id)); + } + } + return outSize; + } + default: + return (KErrNotSupported); + + } + } + +/** Returns debug info about a CWindowElement entry. + * This describes the window or the background element(s) + * It is indexed via screen num, and index in elementset. + * @return size of buffer required or error code. + **/ +TInt CWsClient::DebugInfoElementSetWindowL(TInt aFunction, TInt aParam, + TInt aReplyBufSize, const CScreen& aScreen) const + { + const CWindowElementSet& elementSet = aScreen.WindowElements(); + TUint winIndex = (aParam & EWsDebugArgWindowMask) >> EWsDebugArgWindowShift; + const TAttributes* winElement = elementSet.DebugBackgroundAt(winIndex); + if (winElement == NULL) + { + return KErrArgument; + } + + MWsElement* backElement = winElement->iElement; + TInt placedCount = elementSet.DebugPlacedCountAt(winIndex); + switch (aFunction) + { + case EWsDebugElementIdList: + { + TInt retVal = (placedCount + 1) * sizeof(MWsElement*); + if (retVal<aReplyBufSize) + { + ReplyBuf(&backElement, sizeof(MWsElement*)); + for (TInt index=0; index<placedCount; index++) + ReplyBuf(&elementSet.DebugPlacedAt(winIndex, index)->iElement, sizeof(MWsElement*)); + } + return retVal; + } + case EWsDebugBackgroundConfig: + if (backElement == NULL) + return KErrNotFound; + else + return DebugReturnConfig(aReplyBufSize, backElement, + winElement->DebugFlags()); + case EWsDebugBackgroundBase: + if (backElement == NULL) + return KErrNotFound; + else + return DebugReturnBase(aReplyBufSize, backElement); + case EWsDebugBackgroundFlags: + return DebugReturnFlags(aReplyBufSize, backElement, + winElement->DebugFlags()); + default: + return KErrNotSupported; + //This method can also be extended to return region and state information from the associated window + } + } + +/** Returns debug info about a placed element. + * It is indexed via screen num, index in elementset, and index in placed element array. + * @return size of buffer required or error code. + **/ +TInt CWsClient::DebugInfoElementSetElementL(TInt aFunction, TInt aParam, + TInt aReplyBufSize, const CScreen& aScreen) const + { + const CWindowElementSet& elementSet = aScreen.WindowElements(); + TUint winIndex = (aParam & EWsDebugArgWindowMask) >> EWsDebugArgWindowShift; + TUint placeIndex = (aParam & EWsDebugArgElementMask) >> EWsDebugArgElementShift; + const TAttributes* placedElement = elementSet.DebugPlacedAt(winIndex, placeIndex); + if (placedElement == NULL) + { + return KErrArgument; + } + + MWsElement* element = placedElement->iElement; + if (element == NULL) + { + return KErrNotFound; + } + + switch (aFunction) + { + case EWsDebugPlacedConfig: + return DebugReturnConfig(aReplyBufSize, element, + placedElement->DebugFlags()); + case EWsDebugPlacedBase: + return DebugReturnBase(aReplyBufSize, element); + case EWsDebugPlacedFlags: + return DebugReturnFlags(aReplyBufSize, element, + placedElement->DebugFlags()); + default: + return KErrNotSupported; + } + } + +/** Returns a filled in TSurfaceConfiguration from an MWsElement. + * Data is usually copied if the buffer is big enough + * @return the size of buffer required, or zero if the buffer is acceptable + **/ +TInt CWsClient::DebugReturnConfig(TInt aReplyBufSize, MWsElement* aElement, TInt /*aFlags*/) const + { + if (aElement == NULL) + { + return KErrNotReady; + } + + TSurfaceConfiguration config(aReplyBufSize); + TInt retVal=config.Size(); + if (aReplyBufSize) + { + retVal = CWindowElementSet::GetConfiguration(config, *aElement); + if (retVal==KErrNone) + { + ReplyBuf(&config, config.Size()); //return code is 0 = "just right" + } + } + return retVal; + } + +/** Returns the base region of the element. + * This region is element relative. There are a number of ways that this does not match the input region: + * First, if no region is specified then the extent rectangle is returned + * Any region returned has all negative ordinate values clipped. + * Positive values may exceed the extent, but negative values are never returned. + * Internally, a region which is only negative is "remembered illegally", but an empty region is returned. + **/ +TInt CWsClient::DebugReturnBase(TInt /*aReplyBufSize*/, const MWsElement* /*aElement*/)const + { + return KErrNotSupported; + } + +/** Returns the flags associated with the given element. + * 2 words are inserted. + * One represents the MWsElement flags, the other represents CWindowElement or UIElement flags + * @return length of two words + **/ +TInt CWsClient::DebugReturnFlags(TInt aReplyBufSize, const MWsElement* /*aElement*/, TInt aFlags)const + { + const TInt KArraySize=2; + if (aReplyBufSize>KArraySize*sizeof(TInt)) + { + // First field is for flags from scene element if any + TInt returns[KArraySize]= + { + 0, aFlags + }; + ReplyBuf(returns,KArraySize*sizeof(TInt)); + } + return KArraySize*sizeof(TInt); + } + +/** Packages a region for return ans an array of rectangles. + * If the buffer is big enough the data is transferred + * @return the buffer size required, or an error code if an empty or null pointer is passed in + **/ +TInt CWsClient::DebugReturnRegion(TInt aReplyBufSize, const TRegion* aRegion, TInt aErrCodeIfEmpty)const + { + if (aRegion==NULL) + return KErrNotReady; + + const TInt returnSize=aRegion->Count()*sizeof(TRect); + if (returnSize==0) + return aErrCodeIfEmpty; + + if (returnSize<=aReplyBufSize) + ReplyBuf(aRegion->RectangleList(),returnSize); + + return returnSize; + } + +void CWsClient::ReplyGroupName(HBufC* aName, TInt aMaxLength) // static + { + if (aName) + { + if (aName->Length()>aMaxLength) + { + ReplyBuf(aName->Left(aMaxLength)); + SetReply(KErrOverflow); + } + else + ReplyBuf(*aName); + } + else + ReplyBuf(KNullDesC); + } + +void CWsClient::TriggerRedraw() + { + RedrawQueue()->TriggerRedraw(); + } + +void CWsClient::UpdateWindowOrdinalPrioritys() + { + for(CWsWindowGroup* win=iScreen->RootWindow()->Child();win;win=win->NextSibling()) + { + if (win->WsOwner()==this) + win->UpdateOrdinalPriority(ETrue); + } + } + +void CWsClient::DeleteSystemPointerListEntry(TInt aIndex) + { + PointerCursor (aIndex)->Close(); + iSystemPointerCursors->Delete(aIndex); + } + +CWsPointerCursor* CWsClient::SystemPointerCursor(TInt aIndex) + { + TInt arrayIndex; + if (iSystemPointerCursors) + { + if (FindCursorArrayItem(iSystemPointerCursors, aIndex, arrayIndex)) + return PointerCursor(arrayIndex); + + // Cursor not defined so try for default cursor + if (FindCursorArrayItem(iSystemPointerCursors, 0, arrayIndex)) + return PointerCursor(arrayIndex); + } + + // If that fails simply return NULL for no cursor + return NULL; + } + +void CWsClient::SetSystemPointerCursorL(TInt aIndex, CWsPointerCursor* aCursor) + { + if (iSystemPointerCursorListOwner!=this) + PPanic(EWservPanicNotSystemPointerCursorListOwner); + + TInt arrayIndex = KErrNotFound; + if (FindCursorArrayItem(iSystemPointerCursors, aIndex, arrayIndex)) + { + PointerCursor(arrayIndex)->Close(); + PointerCursor(arrayIndex) = aCursor; + } + else + { + TWsCursorArrayItem entry; + entry.iIndex=aIndex; + entry.iCursor=aCursor; + iSystemPointerCursors->InsertIsqL(entry, iCursorKey); + } + + aCursor->Open(); + if (aIndex==iDefaultSystemPointerCursorIndex) + iDefaultSystemPointerCursor=aCursor; + TWsPointer::UpdatePointerCursor(); + } + +void CWsClient::ClearSystemPointerCursor(TInt aIndex) + { + if (iSystemPointerCursorListOwner!=this) + PPanic(EWservPanicNotSystemPointerCursorListOwner); + + TInt arrayIndex; + if (FindCursorArrayItem(iSystemPointerCursors, aIndex, arrayIndex)) + { + DeleteSystemPointerListEntry(arrayIndex); + if (aIndex==iDefaultSystemPointerCursorIndex) + iDefaultSystemPointerCursor=NULL; + } + } + +void CWsClient::ClaimSystemPointerCursorListL() + { + if (iSystemPointerCursorListOwner) + User::Leave(KErrInUse); + + const TInt systemPointerCursorGranularity = 4; + iSystemPointerCursors = new(ELeave) CArrayFixFlat<TWsCursorArrayItem> (systemPointerCursorGranularity); + iSystemPointerCursorListOwner=this; + } + +void CWsClient::FreeSystemPointerCursorList() + { + if(iSystemPointerCursorListOwner == this) + { + iSystemPointerCursorListOwner = NULL; + + while(iSystemPointerCursors->Count()>0) + DeleteSystemPointerListEntry(0); + + iDefaultSystemPointerCursor = NULL; + iDefaultSystemPointerCursorIndex = 0; + + delete iSystemPointerCursors; + iSystemPointerCursors = NULL; + } + } + +void CWsClient::SetDefaultSystemPointerCursor(TInt aIndex) + { + TInt arrayIndex; + if (iSystemPointerCursorListOwner != this) + PPanic(EWservPanicNotSystemPointerCursorListOwner); + + iDefaultSystemPointerCursorIndex = aIndex; + iDefaultSystemPointerCursor = NULL; + + if (aIndex != ENoDefaultSystemPointerCursor && + FindCursorArrayItem(iSystemPointerCursors, aIndex, arrayIndex)) + iDefaultSystemPointerCursor = PointerCursor (arrayIndex); + else + iDefaultSystemPointerCursor = NULL; + + TWsPointer::UpdatePointerCursor(); + } + +TBool CWsClient::FindCursorArrayItem(CArrayFixFlat<TWsCursorArrayItem>* aCursorArray, + TInt aIndex,TInt& aPosition) + { + if (!aCursorArray) + return EFalse; // No hit if the array isn't even allocated + + TWsCursorArrayItem entry; + entry.iIndex = aIndex; + return aCursorArray->FindIsq(entry, iCursorKey, aPosition)==KErrNone; + } + +void CWsClient::SetClientPriority() + { + if (iComputeMode!=RWsSession::EPriorityControlDisabled) + { + Client().SetProcessPriority( + iComputeMode==RWsSession::EPriorityControlComputeOn + || CWsTop::FocusWindowGroupOwner()!=this + ? EPriorityBackground + : EPriorityForeground); + } + } + +void CWsClient::SetComputeMode(RWsSession::TComputeMode aComputeMode) + { + if (aComputeMode!=RWsSession::EPriorityControlDisabled + && aComputeMode !=RWsSession::EPriorityControlComputeOn + && aComputeMode !=RWsSession::EPriorityControlComputeOff) + PPanic(EWservPanicSetComputeMode); + iComputeMode=aComputeMode; + SetClientPriority(); + } + +void CWsClient::CompleteMessage(const RMessage2& aMessage,TInt aReason) + { + WS_ASSERT_DEBUG(!aMessage.IsNull(),EWsPanicPanicFlagError); + if (iInternalFlags&EPanicClientAsSoonAsPossible) + { + aMessage.Panic(KWSERVSessionPanicCategory,iPanicReason); + iInternalFlags&=~EPanicClientAsSoonAsPossible; + } + else + { + if(!iResponseHandle) + aMessage.Complete(aReason); + else + { + aMessage.Complete(*iResponseHandle); + iResponseHandle=NULL; + } + } + } + +void CWsClient::ServiceError(const RMessage2& /*aMessage*/,TInt aError) + { + CompleteMessage(iClientMessage,aError); // (finish) + } + +void CWsClient::ServiceL(const RMessage2 &aMessage) // (step ##1) +// +// Handle messages for the window server server. +// + { + iClientMessage=aMessage; // from now on use always the message stored in the session + if (iInternalFlags&EPanicClientAsSoonAsPossible) + { + iClientMessage.Panic(KWSERVSessionPanicCategory,iPanicReason); + } + else + { + iPanicReason=KErrNone; + iReply=KErrNone; + TBool completeRequest=ETrue; + DoServiceL(iClientMessage, completeRequest); // (call #2) + if (completeRequest) + CompleteMessage(iClientMessage,iReply); // (finish) + } + } + +void CWsClient::SetResponseHandle(RHandleBase* aHandle) + { + iResponseHandle = aHandle; + } + +void CWsClient::DoServiceL(const RMessage2& aMessage, TBool& aCompleteRequest) // (step #2) + { + if (aMessage.IsNull()) + PPanic(EWservPanicNullMessageFromClient); + + WS_ASSERT_DEBUG(iInternalFlags&EFinishedProcessingCommands,EWsPanicCommandBufferStillBeingProcessed); + + const TInt function = aMessage.Function(); + switch (function) + { + case EWservMessInit: + StartInitializationL(iConnectionId++); + break; + case EWservMessSyncMsgBuf: + case EWservMessCommandBuffer: // Process command buffer containing draw ops + { + if (!IsInitialised()) + PPanic(EWservPanicUninitialisedClient); + + const TInt err = aMessage.Read(KBufferMessageSlot, iCmdBuf); + if (!err) + { + iReplyOffset=0; + iDestObj=NULL; + iNextCmd=iCmdBuf.Ptr(); + DoServiceCommandBuf(); // (call #3.1) + } + else if (err!=KErrDied) + PPanic(EWservPanicDescriptor); + + if(function == EWservMessCommandBuffer && CWsTop::FinishEveryFlush()) + Screen()->DoRedrawNow(); + else + aCompleteRequest=EFalse; + } + break; + case EWservMessShutdown: + { + if(!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for EWservMessShutdown message "))) + PPanic(EWservPanicPermissionDenied); + + if (aMessage.Int0() == EWservShutdownCheck) + CWsTop::Exit(); + else + PPanic(EWservPanicHandle); + } + break; + case EWservMessFinish: + Screen()->DoRedrawNow(); + break; + default: + if (function&EWservMessAsynchronousService) + { + TRAPD(err, ExecuteAsyncClientCommandL((function&~EWservMessAsynchronousService), aMessage)); // (call #3.2) + aCompleteRequest = (err!=KErrNone); + WS_ASSERT_DEBUG((!(iInternalFlags&EPanicClientAsSoonAsPossible))==(!aCompleteRequest), EWsPanicPanicFlagError); + } + else if (function&EWservMessAnimDllAsyncCommand) + { + CWsAnimDll* const animDll = static_cast<CWsAnimDll*>(HandleToObj(aMessage.Int0(), WS_HANDLE_ANIM_DLL)); + if (!animDll) + { + SessionPanic(EWservPanicHandle); + break; + } + + // it looks wrong to call CommandReply here (not AsyncCommandReply, or something, which doesn't exist), but basically, we can't add a virtual AsyncCommandReplyL to CAnim to correspond to RAnim::AsyncCommandReply as that would break binary and source compatibility for Anim plug-ins; instead asynchronous commands are done by the plug-in having to complete the RMessagePtr2 returned by iFunctions->Message() (or a copy of of that object) for asynchronous commands only + TRAPD(err, animDll->AnimObjectL(aMessage.Int1())->CommandReply(function&~EWservMessAnimDllAsyncCommand,NULL)); + aCompleteRequest=(err!=KErrNone); + WS_ASSERT_DEBUG((!(iInternalFlags&EPanicClientAsSoonAsPossible))==(!aCompleteRequest), EWsPanicPanicFlagError); + } + else + SetReply(KErrNotSupported); + } + } +void CWsClient::RemoteRead(TDes16& aDes, TInt aOffset) + { + if (iClientMessage.Read(KRemoteBufferMessageSlot,aDes,aOffset)!=KErrNone) + SessionPanic(EWservPanicDescriptor); + } + +void CWsClient::RemoteRead(TDes8& aDes, TInt aOffset) + { + if (iClientMessage.Read(KRemoteBufferMessageSlot,aDes,aOffset)!=KErrNone) + SessionPanic(EWservPanicDescriptor); + } + +void CWsClient::RemoteReadL(TDes16& aDes, TInt aOffset) + { + iClientMessage.ReadL(KRemoteBufferMessageSlot,aDes,aOffset); + } + +void CWsClient::RemoteReadL(TDes8& aDes, TInt aOffset) + { + iClientMessage.ReadL(KRemoteBufferMessageSlot,aDes,aOffset); + } + +void CWsClient::InitStaticsL() + { + } + +void CWsClient::DeleteStatics() + { + if (iTextCursorArray) + { + const TInt count = iTextCursorArray->Count(); + for (TInt index=0;index<count;index++) + delete iTextCursorArray->At(index).iCursor; + + delete iTextCursorArray; + iTextCursorArray = NULL; + } + + // coverity[extend_simple_error] + } + +/* CWsClient implementing MWsClient */ + +TBool CWsClient::HasCapability(TCapability aCapability) const + { + return iClient.HasCapability(aCapability); + } + +TSecureId CWsClient::SecureId() const + { + return iClient.SecureId(); + } + +TVendorId CWsClient::VendorId() const + { + return iClient.VendorId(); + } + +/** +Makes a new copy of the aData. so it could be deleted after this call. +*/ +TInt CWsClient::SendMessage(const CWsGraphicDrawer* aOnBehalfOf,const TDesC8& aData) + { + CWsGraphicMessageQueue::CMessage* msg = CWsGraphicMessageQueue::CMessage::New(aData); + if(msg) + return SendMessage(aOnBehalfOf, *msg); + + return KErrGeneral; + } + +/** adds a message to the message queue +@return a postive number to uniquely identify the message +*/ +TInt CWsClient::SendMessage(const CWsGraphicDrawer* aOnBehalfOf,CWsMessageData& aData) + { + WS_ASSERT_DEBUG(aData.Data().Size(), EWsPanicWsGraphic); + const CWsGraphicDrawerObject* obj = DrawerObject(aOnBehalfOf); + WS_ASSERT_DEBUG(obj, EWsPanicWsGraphic); + if(obj) + { + // assign message id + if(iMessageIdSeq == KMaxTInt) // Wrap if iMessageIdSeq has reached KMaxTInt + iMessageIdSeq = 0; + + iMessageIdSeq++; + // correct other handles + aData.iClientHandle = (obj->ClientHandle() | (EWsGraphMessageTypeUser & 0x03)); + aData.iDrawer = obj->Drawer(); + aData.iId = iMessageIdSeq; + iGraphicMessageQueue.Queue(&aData); + return iMessageIdSeq; + } + + return KErrGeneral; + } + + +CWsGraphicDrawerObject* CWsClient::DrawerObject(const CWsGraphicDrawer* aDrawer) + { + const TInt count = ObjectIndex()->Length(); + for(TInt i=0; i<count; i++) + { + CWsObject* obj = const_cast<CWsObject*>(ObjectIndex()->At(i)); + if(obj && (WS_HANDLE_GRAPHIC_DRAWER == obj->Type())) + { + CWsGraphicDrawerObject* candidate = static_cast<CWsGraphicDrawerObject*>(obj); + if(candidate->Drawer() == aDrawer) + return candidate; + } + } + + return NULL; + } + +const CWsGraphicDrawerObject* CWsClient::DrawerObject(const CWsGraphicDrawer* aDrawer) const + { + CWsObjectIx* objectIndex = const_cast<CWsClient*>(this)->ObjectIndex(); + const TInt count = objectIndex->Length(); + for(TInt i=0; i<count; i++) + { + CWsObject* obj = const_cast<CWsObject*>(objectIndex->At(i)); + if(obj && (WS_HANDLE_GRAPHIC_DRAWER == obj->Type())) + { + const CWsGraphicDrawerObject* candidate = static_cast<CWsGraphicDrawerObject*>(obj); + if(candidate->Drawer() == aDrawer) + return candidate; + } + } + + return NULL; + } + +TInt CWsClient::RegisterSurface(const TWsClCmdUnion& pData) + { + TInt screenNumber = pData.SurfaceRegister->screenNumber; + if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens()) + { + PPanic(EWservPanicScreenNumber); + } + if (pData.SurfaceRegister->surfaceId.Type() == TSurfaceId::EScreenSurface + || pData.SurfaceRegister->surfaceId.IsNull()) + { + PPanic(EWservPanicInvalidSurface); + } + + CRegisteredSurfaceMap* surfaceMap = CWsTop::Screen(screenNumber)->SurfaceMap(); + const TSurfaceId& surfaceId = pData.SurfaceRegister->surfaceId; + TInt err = surfaceMap->Add(*this,surfaceId); + + switch(err) + { + case KErrNone: + case KErrNoMemory: + case KErrInUse: + case KErrArgument: + break; + default: + PPanic(EWservPanicInvalidSurface); + } + return err; + } + +void CWsClient::UnregisterSurface(const TWsClCmdUnion& pData) + { + TInt screenNumber = pData.SurfaceRegister->screenNumber; + if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens()) + { + PPanic(EWservPanicScreenNumber); + } + TInt err = CWsTop::Screen(screenNumber)->SurfaceMap()->Remove(*this,pData.SurfaceRegister->surfaceId); + WS_ASSERT_DEBUG((err==KErrNone||err==KErrNotFound), EWsPanicSurfaceMapError); + } + +void CWsClient::CreateDrawableSourceL(const TWsClCmdCreateDrawableSource& aDrawableSourceData) + { + CWsDrawableSource* drawableSource = new(ELeave) CWsDrawableSource(this); + CleanupStack::PushL(drawableSource); + drawableSource->ConstructL(aDrawableSourceData); + CleanupStack::Pop(); + } + +void CWsClient::IndicateAppOrientation(TRenderOrientation aOrientation) + { + iIndicatedAppOrientation = aOrientation; + CWsTop::CheckRenderOrientation(); + } + +TInt CWsClient::GetIndicatedAppOrientation() + { + return iIndicatedAppOrientation; + } + +// +// class CWsCliObj +// + +CWsCliObj* CWsCliObj::NewL(CWsClient* aOwner) + { + CWsCliObj* self = new(ELeave) CWsCliObj(aOwner); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CWsCliObj::CWsCliObj(CWsClient *aOwner) : + CWsObject(aOwner, WS_HANDLE_CLIENT) + { + } + +void CWsCliObj::ConstructL() + { + NewObjL(); + } + +void CWsCliObj::CommandL(TInt aOpcode, const TAny* aCmdData) // (step #5) + { + iWsOwner->ExecuteCommandL(aOpcode,aCmdData); // (call #6) + } + +CWsObject* CWsClient::HandleToObjUntyped(TInt aHandle) + { + return iObjectIndex->HandleToObject(aHandle); + } + +const CWsObject* CWsClient::HandleToObjUntyped(TInt aHandle) const + { + return const_cast<CWsClient*>(this)->HandleToObjUntyped(aHandle); + } + +CWsObject* CWsClient::HandleToObj(TInt aHandle, WH_HANDLES aType) + { + CWsObject* object = HandleToObjUntyped(aHandle); + return (object && object->Type() == aType) ? object : NULL; + } + + +const CWsObject* CWsClient::HandleToObj(TInt aHandle, WH_HANDLES aType) const + { + return const_cast<CWsClient*>(this)->HandleToObj(aHandle, aType); + } + +void CWsClient::SetRetryFlag(TEventCode aEventCode) + { + switch(aEventCode) + { + //To be expanded + case EEventDisplayChanged: + { + iInternalFlags |= ERetryDisplayEvent; + } + break; + + } + } +TBool CWsClient::RetryEvent(TEventCode aEventCode) + { + switch(aEventCode) + {//To be expanded + case EEventDisplayChanged: + { + return (iInternalFlags & ERetryDisplayEvent); + } + } + return EFalse; + } + +void CWsClient::RemoveRetryFlag(TEventCode aEventCode) + { + switch(aEventCode) + {//To be expanded + case EEventDisplayChanged: + { + iInternalFlags &= ~ERetryDisplayEvent; + } + break; + } + } +