os/graphics/windowing/windowserver/nonnga/SERVER/EVQUEUE.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/windowing/windowserver/nonnga/SERVER/EVQUEUE.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,947 @@
     1.4 +// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +// Window server event queue handling
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include "EVQUEUE.H"
    1.22 +
    1.23 +#include "server.h"
    1.24 +#include "wstop.h"
    1.25 +#include "panics.h"
    1.26 +#include "pointer.h"
    1.27 +#include "wstraces.h"
    1.28 +
    1.29 +GLREF_D CDebugLogBase *wsDebugLog;
    1.30 +
    1.31 +#if defined(_DEBUG)
    1.32 +#define __CHECK_QUEUE() CheckQueue()
    1.33 +#define __ZAP_EVENTS(pointer,len) ZapEvents(pointer,len)
    1.34 +#define __ZAP_EVENT(pointer) ZapEvent(pointer)
    1.35 +#else
    1.36 +#define __CHECK_QUEUE()
    1.37 +#define __ZAP_EVENTS(pointer,len)
    1.38 +#define __ZAP_EVENT(pointer)
    1.39 +#endif
    1.40 +
    1.41 +const TInt ECopyBufSize=4;
    1.42 +
    1.43 +TDblQue<CEventQueue> CEventQueue::iQueueList(_FOFF(CEventQueue,iLink));
    1.44 +TWsEvent *CEventQueue::iGlobalEventQueue=NULL;
    1.45 +TInt CEventQueue::iGlobalEventQueueSize=0;
    1.46 +TInt CEventQueue::iNumConnections=0;
    1.47 +RMutex CEventQueue::iMutex;
    1.48 +TWsEvent CEventQueue::iNullEvent;
    1.49 +
    1.50 +// CEventBase
    1.51 +
    1.52 +CEventBase::~CEventBase()
    1.53 +	{
    1.54 +	if (!iEventMsg.IsNull() && CWsTop::ShuttingDown())
    1.55 +		{
    1.56 +		iEventMsg.Complete(KErrServerTerminated);
    1.57 +		}
    1.58 +	}
    1.59 +
    1.60 +CEventBase::CEventBase(CWsClient *aOwner) : iWsOwner(aOwner)
    1.61 +	{
    1.62 +	}
    1.63 +
    1.64 +void CEventBase::SignalEvent(TInt aCode)
    1.65 +	{
    1.66 +	if (wsDebugLog)
    1.67 +		wsDebugLog->SignalEvent(iWsOwner->ConnectionHandle());
    1.68 +	iEventMsg.Complete(aCode);
    1.69 +	iEventSignalledState|=EEventFlagSignalled;
    1.70 +	}
    1.71 +
    1.72 +inline TBool CEventBase::IsEventCancelled()
    1.73 +	{
    1.74 +	return (iEventSignalledState & EEventFlagCancelled);
    1.75 +	}
    1.76 +
    1.77 +void CEventBase::CancelRead()
    1.78 +//
    1.79 +// If there is an outstanding read cancel it.
    1.80 +//
    1.81 +	{
    1.82 +	if (!iEventMsg.IsNull())
    1.83 +		{
    1.84 +		iEventMsg.Complete(KErrCancel);
    1.85 +		}
    1.86 +	iEventSignalledState|=EEventFlagCancelled;
    1.87 +	}
    1.88 +
    1.89 +void CEventBase::GetData(TAny *aData, TInt aLen)
    1.90 +	{
    1.91 +	if (!(iEventSignalledState&EEventFlagSignalled))
    1.92 +		{
    1.93 +		iWsOwner->PPanic(EWservPanicUnsignalledEventData);
    1.94 +		}
    1.95 +	iEventSignalledState&=~EEventFlagSignalled;
    1.96 +	CWsClient::ReplyBuf(aData,aLen);
    1.97 +	}
    1.98 +
    1.99 +void CEventBase::EventReadyCheck()
   1.100 +//
   1.101 +// Queue a read of an event notification
   1.102 +//
   1.103 +	{
   1.104 +	if ((iEventSignalledState&EEventFlagSignalled && !(iEventSignalledState&EEventFlagCancelled)) || !iEventMsg.IsNull())
   1.105 +		{
   1.106 +		iWsOwner->PPanic(EWservPanicReadOutstanding);
   1.107 +		}
   1.108 +	}
   1.109 +
   1.110 +void CEventBase::EventReady(const RMessagePtr2& aEventMsg)
   1.111 +	{
   1.112 +	EventReadyCheck();
   1.113 +	iEventMsg=aEventMsg;
   1.114 +	}
   1.115 +
   1.116 +// CEventQueue - Queue organisation functions
   1.117 +
   1.118 +#if defined(_DEBUG)
   1.119 +void CEventQueue::CheckQueue()
   1.120 +	{
   1.121 +	TDblQueIter<CEventQueue> iter(iQueueList);
   1.122 +	CEventQueue *qptr;
   1.123 +	iter.SetToFirst();
   1.124 +	while((qptr=iter++)!=NULL)
   1.125 +		{
   1.126 +		WS_ASSERT_DEBUG(qptr->iQueueSize>=0 && qptr->iQueueSize<=iGlobalEventQueueSize, EWsPanicCheckEventQueue);
   1.127 +		WS_ASSERT_DEBUG(qptr->iQueueSize==0 || qptr->iHead<qptr->iQueueSize, EWsPanicCheckEventQueue);
   1.128 +		WS_ASSERT_DEBUG(qptr->iCount<=qptr->iQueueSize, EWsPanicCheckEventQueue);
   1.129 +		WS_ASSERT_DEBUG(qptr->iEventPtr>=iGlobalEventQueue && qptr->iEventPtr<=(iGlobalEventQueue+iGlobalEventQueueSize), EWsPanicCheckEventQueue);
   1.130 +		}
   1.131 +	for(TInt index=0;index<iCount;index++)
   1.132 +		{
   1.133 +		TWsEvent *ev=EventPtr(index);
   1.134 +		WS_ASSERT_DEBUG(ev->Type()!=EEventMarkInvalid, EWsPanicCheckEventQueue);
   1.135 +		}
   1.136 +	}
   1.137 +
   1.138 +void CEventQueue::ZapEvent(TWsEvent *aTarget)
   1.139 +	{
   1.140 +	aTarget->SetType(EEventMarkInvalid);
   1.141 +	aTarget->SetHandle(555);
   1.142 +	}
   1.143 +
   1.144 +void CEventQueue::ZapEvents(TWsEvent *aTarget, TInt aLen)
   1.145 +	{
   1.146 +	for(TInt index=0;index<aLen;index++)
   1.147 +		ZapEvent(aTarget+index);
   1.148 +	}
   1.149 +
   1.150 +#endif
   1.151 +
   1.152 +void CEventQueue::EventCopy(TWsEvent *aTarget, TWsEvent *aSource, TInt aNumEvents)
   1.153 +	{
   1.154 +	WS_ASSERT_DEBUG(aTarget>=iGlobalEventQueue, EWsPanicEventQueueCopy);
   1.155 +	WS_ASSERT_DEBUG((aTarget+aNumEvents)<=(iGlobalEventQueue+iGlobalEventQueueSize), EWsPanicEventQueueCopy);
   1.156 +	Mem::Copy(aTarget,aSource,aNumEvents*sizeof(TWsEvent));
   1.157 +	}
   1.158 +
   1.159 +TInt CEventQueue::RequiredQueueSize(TInt aNumConnections)
   1.160 +	{
   1.161 +	return(aNumConnections*EMinQueueSize+EMaxQueueSize+EExtraQueueSize);
   1.162 +	}
   1.163 +
   1.164 +/**
   1.165 +Adjust the Global Queue Size.
   1.166 +@param aNewSize the size for event queue. 
   1.167 +*/
   1.168 +void CEventQueue::AdjustQueueSizeL(TInt aNewSize)
   1.169 +	{
   1.170 +	TWsEvent* oldQ=iGlobalEventQueue;
   1.171 +	if (aNewSize < iGlobalEventQueueSize)
   1.172 +		{
   1.173 +		// Re-alloc wont move the cell down to a lower address, this means once this cell is
   1.174 +		// high up in memory it may never move down again, thus wasting loads of global heap space.
   1.175 +		const CEventQueue* last=iQueueList.Last();
   1.176 +		if ((last->iEventPtr + last->iQueueSize) >= (iGlobalEventQueue + aNewSize))
   1.177 +			{
   1.178 +			return;
   1.179 +			}
   1.180 +		TInt allocSize = aNewSize * sizeof(TWsEvent);
   1.181 +		iGlobalEventQueue=static_cast<TWsEvent*>(User::AllocL(allocSize));
   1.182 +		Mem::Copy(iGlobalEventQueue,oldQ,allocSize);
   1.183 +		User::Free(oldQ);
   1.184 +		}
   1.185 +	else
   1.186 +		{
   1.187 +		iGlobalEventQueue = static_cast<TWsEvent*>(User::ReAllocL(iGlobalEventQueue, aNewSize * sizeof(TWsEvent)));
   1.188 +		}
   1.189 +	__ZAP_EVENTS(iGlobalEventQueue + iGlobalEventQueueSize, aNewSize - iGlobalEventQueueSize); 
   1.190 +	iGlobalEventQueueSize = aNewSize; 
   1.191 +	// coverity[use_after_free]
   1.192 +	TInt diff=(reinterpret_cast<TInt8*>(iGlobalEventQueue)-reinterpret_cast<TInt8*>(oldQ));
   1.193 +	if (diff)
   1.194 +		{
   1.195 +		TDblQueIter<CEventQueue> iter(iQueueList);
   1.196 +		CEventQueue* qptr;
   1.197 +		while((qptr=iter++)!=NULL)
   1.198 +			{
   1.199 +			qptr->iEventPtr=reinterpret_cast<TWsEvent*>(reinterpret_cast<TInt8*>(qptr->iEventPtr)+diff);
   1.200 +			}
   1.201 +		}
   1.202 +	}
   1.203 +
   1.204 +void CEventQueue::AddQueueL()
   1.205 +	{
   1.206 +	Wait();
   1.207 +	if ((iNumConnections%EQueueGranularity)==0)
   1.208 +		{
   1.209 +		const TInt newSize = RequiredQueueSize(iNumConnections + EQueueGranularity);
   1.210 +		TRAPD(err,AdjustQueueSizeL(newSize));
   1.211 +		if (err!=KErrNone)
   1.212 +			{
   1.213 +			__CHECK_QUEUE();
   1.214 +			Signal();
   1.215 +			User::Leave(err);
   1.216 +			}
   1.217 +		}
   1.218 +	iNumConnections++;
   1.219 +	if (iQueueList.IsEmpty())
   1.220 +		iEventPtr=iGlobalEventQueue;
   1.221 +	else
   1.222 +		{
   1.223 +		CEventQueue *qptr=iQueueList.Last();
   1.224 +		iEventPtr=qptr->iEventPtr+qptr->iQueueSize;
   1.225 +		}
   1.226 +	iQueueList.AddLast(*this);
   1.227 +	
   1.228 +	//Initialize the queue size to at least EMinQueueSize
   1.229 +	//Check the queue by doing standard queue compression.
   1.230 +	TBool isExpanded = ETrue;
   1.231 +	do {isExpanded = Expand(EEventPriorityLow);} while ((iQueueSize < EMinQueueSize) && isExpanded);
   1.232 +	while (iQueueSize < EMinQueueSize)
   1.233 +		{
   1.234 +		//Cannot get enough spaces by doing standard queue compression,
   1.235 +		//try to grow the global queue.
   1.236 +		TInt sizeRequired = EMinQueueSize - iQueueSize;
   1.237 +		const TInt newSize = iGlobalEventQueueSize + sizeRequired;
   1.238 +		TRAPD(err, AdjustQueueSizeL(newSize));
   1.239 +		if (err != KErrNone)
   1.240 +			{
   1.241 +			//Cannot get enough spaces by growing global queue.
   1.242 +			//try to purge the oldest events from inactive clients.				
   1.243 +			TInt numEventCleared = PurgeInactiveEvents(sizeRequired);
   1.244 +			if (numEventCleared == 0)
   1.245 +				{
   1.246 +				__CHECK_QUEUE();
   1.247 +				Signal();
   1.248 +				User::Leave(err);
   1.249 +				}
   1.250 +			}
   1.251 +		while (doExpand(ECompressNoPurge)) {};
   1.252 +		}
   1.253 +	__CHECK_QUEUE();
   1.254 +	Signal();
   1.255 +	}
   1.256 +
   1.257 +void CEventQueue::RemoveQueue()
   1.258 +	{
   1.259 +	Wait();
   1.260 +	if (iEventPtr)	// If this is still NULL this class hasn't been linked into the Q list
   1.261 +		{
   1.262 +		__ZAP_EVENTS(iEventPtr, iQueueSize);
   1.263 +		iLink.Deque();
   1.264 +		if (--iNumConnections==0)
   1.265 +			{
   1.266 +			User::Free(iGlobalEventQueue);
   1.267 +			iGlobalEventQueue=NULL;
   1.268 +			iGlobalEventQueueSize=0;
   1.269 +			}
   1.270 +		else if ((iNumConnections%EQueueGranularity)==0)
   1.271 +			{
   1.272 +			TDblQueIter<CEventQueue> iter(iQueueList);
   1.273 +			CEventQueue* qptr=iter++;
   1.274 +			qptr->Compress(ECompressNoPurge);
   1.275 +			while((qptr=iter++)!=NULL)
   1.276 +				{
   1.277 +				qptr->SqueezeDown();
   1.278 +				}
   1.279 +			const TInt newSize = RequiredQueueSize(iNumConnections);
   1.280 +			TRAP_IGNORE(AdjustQueueSizeL(newSize));
   1.281 +			// Can easily leave as we need to allocate the new smaller queue before freeing
   1.282 +			// the old queue. But if it does it doesn't matter as we'll simply be left with
   1.283 +			// a larger than necessary buffer until the next realloc
   1.284 +			}
   1.285 +		iCount=0;
   1.286 +		}
   1.287 +	__CHECK_QUEUE();
   1.288 +	Signal();
   1.289 +	}
   1.290 +
   1.291 +void CEventQueue::IncreaseQueueSize(TInt aNumSpaces)
   1.292 +	{
   1.293 +	if ((iQueueSize+aNumSpaces)>EMaxQueueSize)
   1.294 +		aNumSpaces=EMaxQueueSize-iQueueSize;
   1.295 +	EventCopy(iEventPtr+iHead+aNumSpaces, iEventPtr+iHead, iQueueSize-iHead);
   1.296 +	__ZAP_EVENTS(iEventPtr+iHead, aNumSpaces);
   1.297 +	iQueueSize+=aNumSpaces;
   1.298 +	iHead=(iHead+aNumSpaces)%iQueueSize;
   1.299 +	}
   1.300 +
   1.301 +TBool CEventQueue::Expand(TWservEventPriorities aPriority)
   1.302 +	{
   1.303 +	if (iQueueSize==EMaxQueueSize)
   1.304 +		{
   1.305 +		if (aPriority==EEventPriorityHigh)
   1.306 +			{
   1.307 +			Purge();
   1.308 +			if (iCount<iQueueSize)
   1.309 +				return(ETrue);	// Success!
   1.310 +			}
   1.311 +		}
   1.312 +	else if (doExpand(ECompressNoPurge) ||
   1.313 +			  doExpand(ECompressPurge1) ||
   1.314 +			   (aPriority==EEventPriorityHigh && doExpand(ECompressPurge2)))
   1.315 +		return(ETrue);
   1.316 +	return(EFalse);				// Failure
   1.317 +	}
   1.318 +
   1.319 +TBool CEventQueue::doExpand(TCompressMode aCompressMode)
   1.320 +	{
   1.321 +	TDblQueIter<CEventQueue> iter(iQueueList);
   1.322 +	iter.SetToLast();
   1.323 +	CEventQueue* qptr=NULL;
   1.324 +	TInt spare=0;
   1.325 +	
   1.326 +	// while loop from last queue till current queue, moving all queues up 
   1.327 +	// to get all the space from between them
   1.328 +	while((qptr=iter)!=this)
   1.329 +		{
   1.330 +		spare=qptr->SqueezeUp();
   1.331 +		if (spare==0)
   1.332 +			qptr->Compress(aCompressMode);
   1.333 +		iter--;
   1.334 +		}
   1.335 +
   1.336 +	// current queue, if we have space then expand the same and return
   1.337 +	spare=FollowingGap();
   1.338 +	if (spare>0)
   1.339 +		{
   1.340 +		IncreaseQueueSize(spare);
   1.341 +		__CHECK_QUEUE();
   1.342 +		return(ETrue);
   1.343 +		}
   1.344 +
   1.345 +	// while loop from current queue till first queue, looking for a gap 
   1.346 +	// between queues and using the first one it finds
   1.347 +	iter--;
   1.348 +	TInt expanded=0;
   1.349 +	while((qptr=iter)!=NULL)
   1.350 +		{
   1.351 +		expanded=qptr->SqueezeUp();
   1.352 +		if (expanded>0)
   1.353 +			{
   1.354 +			return MoveDownAndExpand(iter, expanded);
   1.355 +			}
   1.356 +		else
   1.357 +			qptr->Compress(aCompressMode);
   1.358 +		iter--;
   1.359 +		}
   1.360 +
   1.361 +	// Even by doing all the above if we did not find space then check if first 
   1.362 +	// queue has some space before it. If so then make use of it and movedown all the 
   1.363 +	// queue till the current queue and then use the space for expansion
   1.364 +	iter.SetToFirst();
   1.365 +	qptr=iter;
   1.366 +	if (qptr->iEventPtr>iGlobalEventQueue)
   1.367 +		{
   1.368 +		return MoveDownAndExpand(iter, qptr->iEventPtr-iGlobalEventQueue);
   1.369 +		}
   1.370 +
   1.371 +	__CHECK_QUEUE();
   1.372 +	return(EFalse);	// Failed to expand enough room
   1.373 +	}
   1.374 +
   1.375 +// This function moves the queue down by given amount and repeats this until
   1.376 +// the current queue and then expand the same
   1.377 +TBool CEventQueue::MoveDownAndExpand(TDblQueIter<CEventQueue> &aIter, TInt aExpand)
   1.378 +	{
   1.379 +	CEventQueue* qptr=NULL;
   1.380 +	FOREVER
   1.381 +		{
   1.382 +		qptr=aIter++;
   1.383 +		qptr->MoveDown(aExpand);
   1.384 +		if (qptr==this)
   1.385 +			{
   1.386 +			IncreaseQueueSize(aExpand);
   1.387 +			__CHECK_QUEUE();
   1.388 +			break;
   1.389 +			}
   1.390 +		}
   1.391 +	return ETrue;
   1.392 +	}
   1.393 +
   1.394 +void CEventQueue::MoveDown(TInt aMove)
   1.395 +	{
   1.396 +	if (!aMove)
   1.397 +		{
   1.398 +		return;
   1.399 +		}
   1.400 +	EventCopy(iEventPtr-aMove,iEventPtr,iQueueSize);
   1.401 +	iEventPtr-=aMove;
   1.402 +	}
   1.403 +
   1.404 +/*void CEventQueue::LogUpDownEvents(TChar aChar)
   1.405 +	{
   1.406 +	TWsEvent *event;
   1.407 +	TBuf<128> buf;
   1.408 +	buf.Zero();
   1.409 +	buf.Append(aChar);
   1.410 +	buf.Append('#');
   1.411 +	buf.Append('#');
   1.412 +	TBool some=EFalse;
   1.413 +	TInt index;
   1.414 +
   1.415 +	for (index=0;index<iCount;index++)
   1.416 +		{
   1.417 +		event=EventPtr(index);
   1.418 +		if (event->Type()==EEventPointer)
   1.419 +			{
   1.420 +			if (event->Pointer()->iType==TPointerEvent::EButton1Down
   1.421 +										|| event->Pointer()->iType==TPointerEvent::EButton1Up)
   1.422 +				{
   1.423 +				some=ETrue;
   1.424 +				if (event->Pointer()->iType==TPointerEvent::EButton1Down)
   1.425 +					buf.Append('D');
   1.426 +				else
   1.427 +					buf.Append('U');
   1.428 +				buf.AppendNum(index);
   1.429 +				}
   1.430 +			}
   1.431 +		}
   1.432 +	if (wsDebugLog)
   1.433 +		wsDebugLog->MiscMessage(ELogImportant,buf);
   1.434 +	}*/
   1.435 +
   1.436 +void CEventQueue::Purge()
   1.437 +	{
   1.438 +// Purgable events are:
   1.439 +//	Pointer Up/Down pairs
   1.440 +//  Pointer moves & drags
   1.441 +//  Key messages
   1.442 +//  Key Up/Down pairs
   1.443 +//  Key Ups if not foreground connection
   1.444 +//  Focus lost/gained pairs
   1.445 +//
   1.446 +// Events that must no be purged
   1.447 +//  Key ups for foreground connections queue
   1.448 +//  Lone pointer ups, must be delivered to match preceeding pointer down
   1.449 +//  Lone focus lost/gained messages
   1.450 +//	
   1.451 +	TWsEvent *event;
   1.452 +	TWsEvent *event2;
   1.453 +	TInt index2;
   1.454 +	TInt index=iCount;
   1.455 +	while(index>0)
   1.456 +		{
   1.457 +		event=EventPtr(--index);
   1.458 +		switch(event->Type())
   1.459 +			{
   1.460 +			case EEventPassword:
   1.461 +				break;
   1.462 +			case EEventMarkInvalid:
   1.463 +#if defined(_DEBUG)
   1.464 +				WS_PANIC_DEBUG(EWsPanicCheckEventQueue);
   1.465 +#endif
   1.466 +			case EEventNull:
   1.467 +			case EEventKey:
   1.468 +			case EEventPointerEnter:
   1.469 +			case EEventPointerExit:
   1.470 +			case EEventDragDrop:
   1.471 +breakLoopAndRemoveEvent:
   1.472 +				RemoveEvent(index);
   1.473 +				return;
   1.474 +			case EEventKeyUp:
   1.475 +				if (iQueueList.First()!=this)
   1.476 +					goto breakLoopAndRemoveEvent;
   1.477 +				break;
   1.478 +			case EEventKeyDown:
   1.479 +				if (iQueueList.First()!=this)
   1.480 +					goto breakLoopAndRemoveEvent;
   1.481 +				for (index2=index+1;index2<iCount;index2++)
   1.482 +					{
   1.483 +					event2=EventPtr(index2);
   1.484 +					if (event2->Type()==EEventKeyUp && event2->Key()->iScanCode==event->Key()->iScanCode)
   1.485 +						{
   1.486 +						*event2=iNullEvent;
   1.487 +						goto breakLoopAndRemoveEvent;
   1.488 +						}
   1.489 +					}
   1.490 +				break;
   1.491 +			case EEventModifiersChanged:
   1.492 +				for (index2=index;index2>0;)
   1.493 +					{
   1.494 +					event2=EventPtr(--index2);
   1.495 +					if (event2->Type()==EEventModifiersChanged)
   1.496 +						{
   1.497 +						event->ModifiersChanged()->iChangedModifiers|=event2->ModifiersChanged()->iChangedModifiers;
   1.498 +						index=index2;
   1.499 +						goto breakLoopAndRemoveEvent;
   1.500 +						}
   1.501 +					}
   1.502 +				break;
   1.503 +			case EEventPointerBufferReady:
   1.504 +				CWsPointerBuffer::DiscardPointerMoveBuffer(event->Handle());
   1.505 +				goto breakLoopAndRemoveEvent;
   1.506 +			case EEventFocusLost:
   1.507 +			case EEventFocusGained:
   1.508 +				if ((index+1)<iCount)
   1.509 +					{
   1.510 +					event2=EventPtr(index+1);
   1.511 +					if (event2->Type()==EEventFocusLost || event2->Type()==EEventFocusGained)
   1.512 +						{
   1.513 +						*event2=iNullEvent;
   1.514 +						goto breakLoopAndRemoveEvent;
   1.515 +						}
   1.516 +					}
   1.517 +				break;
   1.518 +			case EEventSwitchOn:
   1.519 +				if ((index+1)<iCount && EventPtr(index+1)->Type()==EEventSwitchOn)
   1.520 +					goto breakLoopAndRemoveEvent;
   1.521 +				break;
   1.522 +			case EEventPointer:
   1.523 +				{
   1.524 +				TPointerEvent::TType upType;
   1.525 +				switch(event->Pointer()->iType)
   1.526 +					{
   1.527 +					case TPointerEvent::EDrag:
   1.528 +					case TPointerEvent::EMove:
   1.529 +					case TPointerEvent::EButtonRepeat:
   1.530 +					case TPointerEvent::ESwitchOn:
   1.531 +						goto breakLoopAndRemoveEvent;
   1.532 +					case TPointerEvent::EButton1Down:
   1.533 +						upType=TPointerEvent::EButton1Up;
   1.534 +						goto purgeDownUp;
   1.535 +					case TPointerEvent::EButton2Down:
   1.536 +						upType=TPointerEvent::EButton2Up;
   1.537 +						goto purgeDownUp;
   1.538 +					case TPointerEvent::EButton3Down:
   1.539 +						upType=TPointerEvent::EButton3Up;
   1.540 +purgeDownUp:			for (index2=index+1;index2<iCount;index2++)
   1.541 +							{
   1.542 +							event2=EventPtr(index2);
   1.543 +							if (event2->Type()==EEventPointer && event2->Handle()==event->Handle() && event2->Pointer()->iType==upType)
   1.544 +								{
   1.545 +								*event2=iNullEvent;
   1.546 +								goto breakLoopAndRemoveEvent;
   1.547 +								}
   1.548 +							}
   1.549 +						WsPointer::UnmatchedDownPurged(upType, event->Handle());
   1.550 +						goto breakLoopAndRemoveEvent;
   1.551 +					case TPointerEvent::EButton1Up:
   1.552 +					case TPointerEvent::EButton2Up:
   1.553 +					case TPointerEvent::EButton3Up:
   1.554 +						break;
   1.555 +					}
   1.556 +				}
   1.557 +				break;
   1.558 +			}
   1.559 +		}
   1.560 +	}
   1.561 +
   1.562 +void CEventQueue::PurgePointerEvents()
   1.563 +	{
   1.564 +	TWsEvent *event;
   1.565 +	TWsEvent *event2;
   1.566 +	TInt index2;
   1.567 +	TInt index=iCount;
   1.568 +	while(index>0)
   1.569 +		{
   1.570 +		event=EventPtr(--index);
   1.571 +		switch(event->Type())
   1.572 +			{
   1.573 +			case EEventPointerBufferReady:
   1.574 +				CWsPointerBuffer::DiscardPointerMoveBuffer(event->Handle());
   1.575 +				RemoveEvent(index);
   1.576 +				break;
   1.577 +			case EEventPointer:
   1.578 +				{
   1.579 +				TPointerEvent::TType upType;
   1.580 +				switch(event->Pointer()->iType)
   1.581 +					{
   1.582 +					case TPointerEvent::EDrag:
   1.583 +					case TPointerEvent::EMove:
   1.584 +					case TPointerEvent::EButtonRepeat:
   1.585 +					case TPointerEvent::ESwitchOn:
   1.586 +						RemoveEvent(index);
   1.587 +						break;
   1.588 +					case TPointerEvent::EButton1Down:
   1.589 +						upType=TPointerEvent::EButton1Up;
   1.590 +						goto purgeDownUp2;
   1.591 +					case TPointerEvent::EButton2Down:
   1.592 +						upType=TPointerEvent::EButton2Up;
   1.593 +						goto purgeDownUp2;
   1.594 +					case TPointerEvent::EButton3Down:
   1.595 +						upType=TPointerEvent::EButton3Up;
   1.596 +purgeDownUp2:			for (index2=index+1;index2<iCount;index2++)
   1.597 +							{
   1.598 +							event2=EventPtr(index2);
   1.599 +							if (event2->Type()==EEventPointer && event2->Handle()==event->Handle() && event2->Pointer()->iType==upType)
   1.600 +								{
   1.601 +								*event2=iNullEvent;
   1.602 +								goto purgedUp;
   1.603 +								}
   1.604 +							}
   1.605 +						WsPointer::UnmatchedDownPurged(upType, event->Handle());
   1.606 +purgedUp:				RemoveEvent(index);
   1.607 +						break;
   1.608 +					case TPointerEvent::EButton1Up:
   1.609 +					case TPointerEvent::EButton2Up:
   1.610 +					case TPointerEvent::EButton3Up:
   1.611 +						break;
   1.612 +					}
   1.613 +				}
   1.614 +				break;
   1.615 +			}
   1.616 +		}
   1.617 +	}
   1.618 +
   1.619 +/**
   1.620 +Purge requested number of oldest events from inactive event queue.
   1.621 +@param aSizeRequired the total events required to be cleared. 
   1.622 +@return The number of events cleared.
   1.623 +*/
   1.624 +TInt CEventQueue::PurgeInactiveEvents(const TInt& aSizeRequired)
   1.625 +	{
   1.626 +	TInt numEventsCleared = 0;
   1.627 +	CEventQueue* qptr;
   1.628 +	TBool isRemoved;
   1.629 +	do	{
   1.630 +		TDblQueIter<CEventQueue> iter(iQueueList);
   1.631 +		isRemoved = EFalse;
   1.632 +		while ((qptr = iter++) != NULL && (aSizeRequired > numEventsCleared))
   1.633 +			{
   1.634 +			if ((qptr->IsEventCancelled() || (qptr->iEventMsg.IsNull() && !qptr->iEventSignalledState)) &&
   1.635 +				(qptr->iQueueSize > EMinQueueSize))
   1.636 +				{
   1.637 +				// we have a client that is not listening with a size larger than min queue size.
   1.638 +				// so lets remove it's oldest event until the number of removed events meet the requirement.
   1.639 +				qptr->RemoveEvent(0);
   1.640 +				numEventsCleared++;
   1.641 +				isRemoved = ETrue;
   1.642 +				}
   1.643 +			}
   1.644 +		} while ((aSizeRequired > numEventsCleared) && isRemoved);
   1.645 +	return numEventsCleared;
   1.646 +	}
   1.647 +
   1.648 +void CEventQueue::Compress(TCompressMode aCompressMode)
   1.649 +	{
   1.650 +//
   1.651 +// The different purge modes are
   1.652 +//
   1.653 +// ECompressNoPurge,	// Don't purge anything
   1.654 +// ECompressPurge1,		// Don't purge foreground queue
   1.655 +// ECompressPurge2,		// Purge all queues
   1.656 +//
   1.657 +	if (aCompressMode==ECompressPurge2 ||
   1.658 +		(this!=iQueueList.First() && aCompressMode==ECompressPurge1))
   1.659 +		Purge();
   1.660 +	TInt compress=iQueueSize-(iCount>EMinQueueSize?iCount:EMinQueueSize);
   1.661 +	if (compress>0)
   1.662 +		{
   1.663 +		compress=(compress+1)/2;	// Compress half the free space in the queue
   1.664 +		TWsEvent *head=EventPtr(0);
   1.665 +		TWsEvent *tail=EventPtr(iCount);
   1.666 +		if (head>tail)
   1.667 +			{
   1.668 +			EventCopy(iEventPtr+compress,iEventPtr,tail-iEventPtr);
   1.669 +			iHead-=compress;
   1.670 +			}
   1.671 +		else
   1.672 +			{
   1.673 +			EventCopy(iEventPtr+compress,head,iCount);
   1.674 +			iHead=0;
   1.675 +			}
   1.676 +		iEventPtr+=compress;
   1.677 +		iQueueSize-=compress;
   1.678 +		}
   1.679 +	}
   1.680 +
   1.681 +void CEventQueue::MoveUp(TInt aNumEvents)
   1.682 +	{
   1.683 +	if (!aNumEvents)
   1.684 +		{
   1.685 +		return;
   1.686 +		}
   1.687 +	EventCopy(iEventPtr+aNumEvents,iEventPtr,iQueueSize);
   1.688 +	iEventPtr+=aNumEvents;
   1.689 +	}
   1.690 +
   1.691 +TInt CEventQueue::FollowingGap() const
   1.692 +	{
   1.693 +	TDblQueIter<CEventQueue> iter(iQueueList);
   1.694 +	CEventQueue *qptr;
   1.695 +	iter.Set(*(CEventQueue *)this);
   1.696 +	iter++;
   1.697 +	TWsEvent *end;
   1.698 +	if ((qptr=iter)!=NULL)
   1.699 +		end=qptr->iEventPtr;
   1.700 +	else
   1.701 +		end=iGlobalEventQueue+iGlobalEventQueueSize;
   1.702 +	return(end-(iEventPtr+iQueueSize));
   1.703 +	}
   1.704 +
   1.705 +TInt CEventQueue::SqueezeUp()
   1.706 +	{
   1.707 +	TInt gap=FollowingGap();
   1.708 +	MoveUp(gap);
   1.709 +	return(gap);
   1.710 +	}
   1.711 +
   1.712 +void CEventQueue::SqueezeDown()
   1.713 +	{
   1.714 +	TDblQueIter<CEventQueue> iter(iQueueList);
   1.715 +	iter.Set(*this);
   1.716 +	iter--;
   1.717 +	CEventQueue *qptr=iter;
   1.718 +	if (qptr!=NULL)
   1.719 +		{
   1.720 +		Compress(ECompressNoPurge);
   1.721 +		TInt gap=qptr->FollowingGap();
   1.722 +		MoveDown(gap);
   1.723 +		}
   1.724 +	}
   1.725 +
   1.726 +void CEventQueue::MoveToFront()
   1.727 +	{
   1.728 +	if (this==iQueueList.First())
   1.729 +		return;
   1.730 +	Wait();
   1.731 +	CEventQueue *qptr;
   1.732 +	TInt gap=0;
   1.733 +	TDblQueIter<CEventQueue> iter(iQueueList);
   1.734 +	iter.SetToLast();
   1.735 +	while((qptr=iter--)!=NULL)
   1.736 +		{
   1.737 +		if (gap<iQueueSize)
   1.738 +			qptr->Compress(ECompressNoPurge);
   1.739 +		gap=qptr->SqueezeUp();
   1.740 +		}
   1.741 +	if (gap>=iQueueSize)
   1.742 +		EventCopy(iGlobalEventQueue,iEventPtr,iQueueSize);
   1.743 +	else
   1.744 +		{
   1.745 +		EventCopy(iGlobalEventQueue,iEventPtr,gap);
   1.746 +		iEventPtr+=gap;
   1.747 +		TWsEvent copyBuf[ECopyBufSize];	// temp buffer, can copy upto ECopyBufSize events at a time
   1.748 +		TInt eventsToGo=iQueueSize-gap;
   1.749 +		iQueueSize=gap;
   1.750 +		do
   1.751 +			{
   1.752 +			TInt copy=Min(eventsToGo,ECopyBufSize);
   1.753 +			Mem::Copy(&copyBuf[0],iEventPtr,copy*sizeof(TWsEvent));
   1.754 +			iter.Set(*this);
   1.755 +			iter--;
   1.756 +			while((qptr=iter--)!=NULL)
   1.757 +				qptr->MoveUp(copy);
   1.758 +			EventCopy(iGlobalEventQueue+iQueueSize,&copyBuf[0],copy);
   1.759 +			iQueueSize+=copy;
   1.760 +			eventsToGo-=copy;
   1.761 +			iEventPtr+=copy;
   1.762 +			} while(eventsToGo>0);
   1.763 +		}
   1.764 +	iEventPtr=iGlobalEventQueue;
   1.765 +	this->iLink.Deque();
   1.766 +	iQueueList.AddFirst(*this);
   1.767 +	__CHECK_QUEUE();
   1.768 +	Signal();
   1.769 +	}
   1.770 +
   1.771 +// CEventQueue
   1.772 +
   1.773 +CEventQueue::CEventQueue(CWsClient *aOwner) : CEventBase(aOwner)
   1.774 +	{
   1.775 +	__DECLARE_NAME(_S("CEventQueue"));
   1.776 +	}
   1.777 +
   1.778 +CEventQueue::~CEventQueue()
   1.779 +	{
   1.780 +	RemoveQueue();
   1.781 +	}
   1.782 +
   1.783 +void CEventQueue::InitStaticsL()
   1.784 +	{
   1.785 +	User::LeaveIfError(iMutex.CreateLocal());
   1.786 +	}
   1.787 +
   1.788 +void CEventQueue::DeleteStaticsL()
   1.789 +	{
   1.790 +	iMutex.Close();
   1.791 +	}
   1.792 +
   1.793 +void CEventQueue::ConstructL()
   1.794 +	{
   1.795 +	AddQueueL();
   1.796 +	Mem::FillZ(&iNullEvent,sizeof(iNullEvent));
   1.797 +	}
   1.798 +
   1.799 +TWsEvent *CEventQueue::EventPtr(TInt index)	
   1.800 +	{
   1.801 +	return(iEventPtr+((iHead+index)%iQueueSize));
   1.802 +	}
   1.803 +
   1.804 +TBool CEventQueue::QueueEvent(const TWsEvent &event)
   1.805 +	{
   1.806 +	TWservEventPriorities priority=EEventPriorityLow;
   1.807 +#ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP
   1.808 +	if (event.Type()==EEventPassword || event.Type()==EEventSwitchOff || 
   1.809 +		event.Type()==EEventKeySwitchOff || event.Type()==EEventRestartSystem)
   1.810 +#else
   1.811 +	if (event.Type()==EEventPassword || event.Type()==EEventSwitchOff || event.Type()==EEventKeySwitchOff)
   1.812 +#endif
   1.813 +		{
   1.814 +		priority=EEventPriorityHigh;
   1.815 +		}
   1.816 +	return(QueueEvent(event,priority));
   1.817 +	}
   1.818 +
   1.819 +TBool CEventQueue::CheckRoom()
   1.820 +//
   1.821 +// If the queue is full and room is created return ETrue
   1.822 +//
   1.823 +	{
   1.824 +	TBool ret=EFalse;
   1.825 +	Wait();
   1.826 +	if (iCount==iQueueSize && Expand(EEventPriorityHigh))
   1.827 +		ret=ETrue;
   1.828 +	Signal();
   1.829 +	return(ret);
   1.830 +	}
   1.831 +
   1.832 +TBool CEventQueue::QueueEvent(const TWsEvent &event, TWservEventPriorities aPriority)
   1.833 +//
   1.834 +// Queue an event, returns ETrue if queued or delivered, EFalse if the queue was full.
   1.835 +//
   1.836 +	{
   1.837 +	WS_TRACE_SERVER_QUEUEEVENT();
   1.838 +	TBool ret=ETrue;
   1.839 +	Wait();
   1.840 +	if (iCount==iQueueSize && !Expand(aPriority))
   1.841 +		ret=EFalse;
   1.842 +	else
   1.843 +		{
   1.844 +		if (!iEventMsg.IsNull())
   1.845 +			{
   1.846 +			SignalEvent();
   1.847 +			}
   1.848 +		*EventPtr(iCount++)=event;
   1.849 +		}
   1.850 +	Signal();
   1.851 +	return(ret);
   1.852 +	}
   1.853 +
   1.854 +TBool CEventQueue::QueueEvent(TUint32 aTarget, TInt aEvent)
   1.855 +	{
   1.856 +	TWsEvent event;
   1.857 +	event.SetType(aEvent);
   1.858 +	event.SetHandle(aTarget);
   1.859 +	event.SetTimeNow();
   1.860 +	return(QueueEvent(event));
   1.861 +	}
   1.862 +
   1.863 +void CEventQueue::UpdateLastEvent(const TWsEvent &event)
   1.864 +	{
   1.865 +	WS_ASSERT_DEBUG(iCount>0, EWsPanicQueueUpdateCount);
   1.866 +	Mem::Copy(EventPtr(iCount-1)->EventData(),event.EventData(),TWsEvent::EWsEventDataSize);
   1.867 +	Signal();
   1.868 +	}
   1.869 +
   1.870 +void CEventQueue::GetData()
   1.871 +//
   1.872 +// If there is an outstanding event in the queue, reply with it's data and remove it from the Q
   1.873 +//
   1.874 +	{
   1.875 +	if (iCount>0)
   1.876 +		{
   1.877 +		WS_ASSERT_DEBUG((iEventPtr+iHead)->Type()!=EEventMarkInvalid, EWsPanicCheckEventQueue);
   1.878 +		CEventBase::GetData(iEventPtr+iHead,sizeof(*iEventPtr));
   1.879 +		__ZAP_EVENT(iEventPtr+iHead);
   1.880 +		iHead=(iHead+1)%iQueueSize;
   1.881 +		iCount--;
   1.882 +		}
   1.883 +	else
   1.884 +		CEventBase::GetData(&iNullEvent,sizeof(iNullEvent));
   1.885 +	}
   1.886 +
   1.887 +void CEventQueue::EventReady(const RMessagePtr2& aEventMsg)
   1.888 +//
   1.889 +// Queue a read of an event notification
   1.890 +//
   1.891 +	{
   1.892 +	EventReadyCheck();
   1.893 +	Wait();
   1.894 +	iEventMsg=aEventMsg;
   1.895 +	if (iCount>0)
   1.896 +		SignalEvent();
   1.897 +	Signal();
   1.898 +	}
   1.899 +
   1.900 +void CEventQueue::RemoveEvent(TInt index)
   1.901 +//
   1.902 +// Remove event 'index' in the queue, this event MUST exist in the queue
   1.903 +//
   1.904 +	{
   1.905 +	WS_ASSERT_DEBUG(index < iCount, EWsPanicCheckEventQueue);
   1.906 +	iCount--;
   1.907 +	for(;index<iCount;index++)
   1.908 +		*EventPtr(index)= *EventPtr(index+1);
   1.909 +	__ZAP_EVENT(EventPtr(iCount));
   1.910 +	}
   1.911 +
   1.912 +const TWsEvent *CEventQueue::PeekLastEvent()
   1.913 +//
   1.914 +// Return a read only pointer to the last event in the queue (or NULL if no event)
   1.915 +//
   1.916 +	{
   1.917 +	if (iCount==0)
   1.918 +		return(NULL);
   1.919 +	return(EventPtr(iCount-1));
   1.920 +	}
   1.921 +
   1.922 +void CEventQueue::Wait()
   1.923 +	{
   1.924 +	iMutex.Wait();
   1.925 +	}
   1.926 +
   1.927 +void CEventQueue::Signal()
   1.928 +	{
   1.929 +	iMutex.Signal();
   1.930 +	}
   1.931 +
   1.932 +void CEventQueue::WalkEventQueue(EventQueueWalk aFunc, TAny *aFuncParam)
   1.933 +	{
   1.934 +	Wait();
   1.935 +restart:
   1.936 +	for (TInt index=0;index<iCount;index++)
   1.937 +		{
   1.938 +		TWsEvent *event=EventPtr(index);
   1.939 +		switch((aFunc)(aFuncParam,event))
   1.940 +			{
   1.941 +			case EEventQueueWalkDeleteEvent:
   1.942 +				RemoveEvent(index--);
   1.943 +			case EEventQueueWalkOk:
   1.944 +				break;
   1.945 +			case EEventQueueWalkRestart:
   1.946 +				goto restart;
   1.947 +			}
   1.948 +		}
   1.949 +	Signal();
   1.950 +	}