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(©Buf[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,©Buf[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 + }