windowing/windowserver/nonnga/SERVER/GRAPHICDRAWER.CPP
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nonnga/SERVER/GRAPHICDRAWER.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,434 @@
+// Copyright (c) 1995-2009 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 "server.h"
+#include "WSGRAPHICDRAWERFACTORY.H"
+#include "panics.h"
+#include <s32mem.h>
+#include "wstop.h"
+
+TInt CWsGraphicDrawerObject::TransientSequence=1;
+TBool CWsGraphicDrawerObject::RollOver=EFalse;
+
+CWsGraphicDrawerObject* CWsGraphicDrawerObject::NewL(CWsClient* aClient,const TWsClCmdUnion &aParams)
+	{
+	if(!aClient)
+		{
+		WS_PANIC_DEBUG(EWsPanicWsGraphic);
+		User::Leave(KErrGeneral);
+		}
+	TGraphicDrawerId id;
+	id.iId = aParams.CreateGraphic->iId;
+	id.iIsUid = !(EWsGraphicIdTransient & aParams.CreateGraphic->iFlags);
+	// check for collision
+	const CWsGraphicDrawer* dup = aClient->WindowServer().ResolveGraphic(id);
+	// request-specific checks
+	if(dup)
+		{
+		// must be exact same session
+		if(&(dup->Owner()) != aClient)
+			{
+			/*	Someone is squatting on someone else's uid, or trying to,
+				but there is no good way to know which. */
+			__DEBUG_ONLY(aClient->PPanic(EWservPanicPermissionDenied);)
+			User::Leave(KErrAlreadyExists);
+			}
+		// dupping or otherwise must be explicitly intended by the client
+		if(!(EWsGraphicReplace & aParams.CreateGraphic->iFlags))
+			{
+			aClient->PPanic(EWservPanicPermissionDenied);
+			}
+		}
+	else
+		{
+		// dupping or otherwise must be explicitly intended by the client
+		if(EWsGraphicReplace & aParams.CreateGraphic->iFlags)
+			{
+			aClient->PPanic(EWservPanicPermissionDenied);
+			}
+		if(id.iIsUid)
+			{
+			// police creation of artwork with UIDs
+			_LIT_SECURITY_POLICY_C1(KSecurityPolicyCreateWithUid,ECapabilityProtServ);
+			if(!KSecurityPolicyCreateWithUid.CheckPolicy(aClient->Client()))
+				{
+				__DEBUG_ONLY(aClient->PPanic(EWservPanicPermissionDenied);)
+				User::Leave(KErrPermissionDenied);
+				}
+			}
+		else
+			{
+			// allocate a new transient id
+			// assumption: that there are more values of a TInt than there are possibly Transient objects
+			do
+				{
+				id.iId = TransientSequence++;
+				RollOver |= !TransientSequence;
+				}
+			while(RollOver && aClient->WindowServer().ResolveGraphic(id)); // until no collision
+			}
+		}
+	// create the drawer object
+	TPtrC8 data;
+	HBufC8* dataBuf = NULL;
+	if(aParams.CreateGraphic->iRemoteReadData)
+		{
+		const TInt len = aParams.CreateGraphic->iDataLen;
+		if ((len >= KMaxTInt/4) || (len < 0))
+			aClient->PPanic(EWservPanicBuffer);
+		dataBuf = HBufC8::NewLC(len);
+		TPtr8 des = dataBuf->Des();
+		aClient->RemoteRead(des,0);
+		if(des.Size() != len)
+			{
+			aClient->PPanic(EWservPanicBuffer);
+			}
+		data.Set(des);
+		}
+	else
+		{
+		data.Set(CWsClient::BufferTPtr8((TText8*)(aParams.CreateGraphic+1),aParams.CreateGraphic->iDataLen));
+		}
+
+	CWsGraphicDrawerObject* drawer = new(ELeave) CWsGraphicDrawerObject(aClient);
+	CleanupStack::PushL(drawer);
+	drawer->ConstructL(aParams.CreateGraphic->iType,aClient->WindowServer(),id,data,aParams.CreateGraphic->iClientHandle);
+	if(!dup)
+		{
+		User::LeaveIfError(aClient->WindowServer().AddGraphicDrawer(drawer->Drawer()));
+		}
+	else
+		{
+		User::LeaveIfError(aClient->WindowServer().SwapGraphicDrawer(drawer->Drawer()));
+		}
+	// take off cleanup stack
+	CleanupStack::Pop(drawer);
+	if(dataBuf)
+		{
+		CleanupStack::PopAndDestroy(dataBuf);
+		}
+	// delete dup, which means resolving the object that encapsulates it
+	if(dup)
+		{
+		CWsGraphicDrawerObject* obj = aClient->DrawerObject(dup);
+		WS_ASSERT_DEBUG(obj, EWsPanicWsGraphic);
+		if(obj)
+			{
+			obj->CloseObject();
+			}
+		}
+	// trigger redraws if anyone is drawing this graphic before it exists
+	if(id.iIsUid)
+		{
+		aClient->WindowServer().Invalidate(id);
+		}
+	// done
+	return drawer;
+	}
+
+CWsGraphicDrawerObject::CWsGraphicDrawerObject(CWsClient* aOwner):
+	CWsObject(aOwner,WS_HANDLE_GRAPHIC_DRAWER)
+	{
+	}
+
+CWsGraphicDrawerObject::~CWsGraphicDrawerObject()
+	{
+	delete iDrawer;
+	}
+
+void CWsGraphicDrawerObject::ConstructL(TUid aType,MWsGraphicDrawerEnvironment& aEnv,const TGraphicDrawerId& aId,const TDesC8& aData,TInt aClientHandle)
+	{
+	CWsGraphicDrawer* drawer = WsGraphicDrawer::CreateLC(aType,aEnv,aId,*WsOwner(),aData);
+	NewObjL();
+	iClientHandle = aClientHandle;
+	iDrawer=drawer;
+	CleanupStack::Pop(iDrawer);
+	}
+
+void CWsGraphicDrawerObject::CommandL(TInt aOpcode, const TAny *aCmdData)
+	{
+	WS_ASSERT_DEBUG(iDrawer, EWsPanicWsGraphic);
+	
+	if(iDrawer)
+		{
+		TWsClCmdUnion pData;
+		pData.any = aCmdData;
+		switch(aOpcode)
+			{
+			case EWsGdOpFree:
+				WsOwner()->WindowServer().RemoveGraphicDrawer(iDrawer->Id());
+				CloseObject();
+				return;
+			case EWsGdOpSendMsg:
+			case EWsGdOpSendSynchronMsg:
+				{
+				const TWsClCmdGdSendMessage& cmd = *pData.GraphicSendMessage;
+				__ASSERT_DEBUG(cmd.iDataLen,WsOwner()->PPanic(EWservPanicPermissionDenied));
+				if(cmd.iDataLen)
+					{
+					if(cmd.iRemoteReadData)
+						{
+						HBufC8* wsAlloc = NULL;
+						TUint8* drawerAlloc = NULL;
+						TPtr8 des(NULL,0);
+						// try to get the drawer to allocate for us
+						MWsGraphicDrawerMessageAlloc* drawerAllocator = iDrawer->ObjectInterface<MWsGraphicDrawerMessageAlloc>();
+						if(drawerAllocator)
+							{
+							drawerAlloc = reinterpret_cast<TUint8*>(drawerAllocator->Alloc(cmd.iDataLen));
+							if(drawerAlloc)
+								des.Set(drawerAlloc,0,cmd.iDataLen);
+							}
+						// else use the normal WSERV default heap
+						if(!drawerAlloc)
+							{
+							wsAlloc = HBufC8::NewLC(cmd.iDataLen);
+							des.Set(wsAlloc->Des());
+							}
+						// fetch
+   						WsOwner()->RemoteRead(des,0);
+						TBool receivedOk = (des.Size() == cmd.iDataLen);
+						// dispatch
+						if(receivedOk)
+							{
+							if(aOpcode == EWsGdOpSendMsg)
+								{
+								iDrawer->HandleMessage(des);
+								}
+							else
+								{
+								MWsGraphicHandleSynchronMessage* obj = iDrawer->ObjectInterface<MWsGraphicHandleSynchronMessage>();
+
+								if(obj)
+									SetReply(obj->HandleSynchronMessage(des));
+								else
+									SetReply(KErrNotSupported);
+								}
+							}
+
+						// dealloc
+						if(drawerAlloc)
+							{
+							drawerAllocator->Free(drawerAlloc);
+							}
+						else
+							{
+							CleanupStack::PopAndDestroy(wsAlloc);
+							}
+						// defer panic until after dealloc
+						if(!receivedOk)
+							{
+							WsOwner()->PPanic(EWservPanicBuffer);
+							}
+						}
+					else
+						{
+						const TPtrC8 data = CWsClient::BufferTPtr8((TText8*)(pData.GraphicSendMessage+1),cmd.iDataLen);
+						if(aOpcode == EWsGdOpSendMsg)
+							{
+							iDrawer->HandleMessage(data);
+							}
+						else
+							{
+							MWsGraphicHandleSynchronMessage* obj = iDrawer->ObjectInterface<MWsGraphicHandleSynchronMessage>();
+							if(obj)
+								SetReply(obj->HandleSynchronMessage(data));
+							else
+								SetReply(KErrNotSupported);
+							}
+						}
+					}
+				}
+				break;
+			case EWsGdOpGetGraphicId:
+				{
+				__ASSERT_COMPILE(sizeof(TWsClCmdGdGetId) == sizeof(TGraphicDrawerId));
+				const TGraphicDrawerId id = iDrawer->Id();
+				CWsClient::ReplyBuf(&id,sizeof(id));
+				}
+				break;
+			case EWsGdOpShareGlobally:
+				SetReply(iDrawer->ShareGlobally());
+				break;
+			case EWsGdOpUnShareGlobally:
+				SetReply(iDrawer->UnShareGlobally());
+				break;
+			case EWsGdOpShare:
+				{
+				const TSecureId& secid = *reinterpret_cast<const TSecureId*>(aCmdData);
+				SetReply(iDrawer->Share(secid));
+				break;
+				}
+			case EWsGdOpUnShare:
+				{
+				const TSecureId& secid = *reinterpret_cast<const TSecureId*>(aCmdData);
+				SetReply(iDrawer->UnShare(secid));
+				break;
+				}
+			default:
+				WsOwner()->PPanic(EWservPanicOpcode);
+			}
+		}
+	}
+
+CWsGraphicDrawer* CWsGraphicDrawerObject::Drawer()
+	{
+	return iDrawer;
+	}
+
+const CWsGraphicDrawer* CWsGraphicDrawerObject::Drawer() const
+	{
+	return iDrawer;
+	}
+
+// CWsGraphicMessageQueue \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
+
+CWsGraphicMessageQueue::CMessage* CWsGraphicMessageQueue::CMessage::New(const TDesC8& aData)
+   	{
+	return new(aData.Size()) CMessage(aData);
+   	}
+
+CWsGraphicMessageQueue::CMessage::CMessage(const TDesC8& aData):
+	iData((reinterpret_cast<TUint8*>(this)+sizeof(*this)),aData.Size())
+   	{
+	iData = aData;
+   	}
+
+TPtrC8 CWsGraphicMessageQueue::CMessage::Data() const
+	{
+	return iData;
+   	}
+
+void CWsGraphicMessageQueue::CMessage::Release()
+	{
+	delete this;
+   	}
+
+CWsGraphicMessageQueue::CMessage::~CMessage()
+   	{
+   	}
+
+CWsGraphicMessageQueue::CWsGraphicMessageQueue(CWsClient *aOwner):
+	CEventBase(aOwner)
+	{
+	}
+
+CWsGraphicMessageQueue::~CWsGraphicMessageQueue()
+	{
+	while(iHead)
+		{
+		CWsMessageData* msg = iHead;
+		iHead = iHead->iNext;
+		msg->Release();
+		}
+	}
+
+TInt CWsGraphicMessageQueue::TopClientHandle() const
+	{
+	if(iHead)
+		return iHead->iClientHandle;
+	else
+		return KErrNotFound;
+	}
+
+/** 
+same functionality as CEventBase::GetData, but this one also inserts the integer header in the reply.
+*/
+void CWsGraphicMessageQueue::GetDataWithHeader(TUint aHeader, const TDesC8& aData, TInt aDataLen)
+	{
+	TPckgBuf<TUint> hdr = aHeader | (EWsGraphMessageTypeUser & 0x03);
+	CWsClient::ReplyBuf(hdr.Ptr(), sizeof(TUint));
+	GetData((void*)aData.Ptr(), aDataLen);
+	}
+
+void CWsGraphicMessageQueue::GetGraphicMessage()
+	{
+	CWsMessageData* top = Pop();
+	WS_ASSERT_DEBUG(top && top->Data().Length(), EWsPanicWsGraphic);
+	if(top)
+		{
+		GetDataWithHeader(top->iClientHandle, top->Data(), top->Data().Size());
+		CWsGraphicDrawerObject* obj = iWsOwner->DrawerObject(top->iDrawer);
+		if(obj)
+			{
+			MWsGraphicMessageCallback* messageCallback = obj->Drawer()->ObjectInterface<MWsGraphicMessageCallback>();
+			if(messageCallback)
+				{
+				messageCallback->HandleMessageDelivery(top->iId, KErrNone);
+				}
+			}
+
+		top->Release();
+		}
+	}
+
+void CWsGraphicMessageQueue::AbortMessage(TInt aError)
+	{
+	CWsMessageData* top = Pop();
+	WS_ASSERT_DEBUG(top, EWsPanicWsGraphic);
+	if(top)
+		{
+		CWsGraphicDrawerObject* obj = iWsOwner->DrawerObject(top->iDrawer);
+		if(obj)
+			{
+			MWsGraphicMessageCallback* messageCallback = obj->Drawer()->ObjectInterface<MWsGraphicMessageCallback>();
+			if(messageCallback)
+				{
+				messageCallback->HandleMessageDelivery(top->iId, aError);
+				}
+			}
+		top->Release();
+		}
+	}
+
+void CWsGraphicMessageQueue::EventReady(const RMessagePtr2& aEventMsg)
+	{
+	CEventBase::EventReady(aEventMsg);
+	if(iHead)
+		{
+		SignalEvent(sizeof(TInt) + iHead->Data().Size());
+		}
+	}
+
+
+void CWsGraphicMessageQueue::Queue(CWsMessageData* aMessage)
+	{
+	WS_ASSERT_DEBUG(aMessage && !aMessage->iNext, EWsPanicWsGraphic);
+	if(aMessage)
+		{
+		if(iHead)
+			{
+			iTail->iNext = aMessage;
+			iTail = aMessage;
+			}
+		else
+			{
+			iHead = iTail = aMessage;
+			if(!iEventMsg.IsNull())
+				SignalEvent(sizeof(TInt) + iHead->Data().Size());
+			}
+		}
+	}
+
+CWsMessageData* CWsGraphicMessageQueue::Pop()
+	{
+	CWsMessageData* ret = NULL;
+	if(iHead)
+		{
+		ret = iHead;
+		iHead = iHead->iNext;
+		}
+	return ret;
+	}