windowing/windowserver/nga/SERVER/openwfc/GROUPWIN.CPP
changeset 0 5d03bc08d59c
child 19 bbf46f59e123
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Group window sub-class of CWsWindow
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <e32std.h>
       
    19 #include "W32STD.H"
       
    20 #include "W32CLICK.H"
       
    21 #include "server.h"
       
    22 #include "rootwin.h"
       
    23 #include "windowgroup.h"
       
    24 #include "walkwindowtree.h"
       
    25 #include "wstop.h"
       
    26 #include "EVENT.H"
       
    27 #include "KEYCLICK.H"
       
    28 #include "PRIKEY.H"
       
    29 #include "panics.h"
       
    30 #include "windowelementset.h"
       
    31 #include "pointer.h"
       
    32 
       
    33 GLREF_D TPtr nullDescriptor;
       
    34 GLREF_D CDebugLogBase* wsDebugLog;
       
    35 
       
    36 #if defined(_DEBUG)
       
    37 TInt CWsWindowGroup::iSkipCount=0;
       
    38 #endif
       
    39 
       
    40 TBool CWsWindowGroup::iEventQueueTest=EFalse;			// For stress testing the EventQueue code
       
    41 
       
    42 TInt CWsWindowGroup::iIdentifierCount=1;
       
    43 TBool CWsWindowGroup::iFocusGainPreProcess=EFalse;		//'REMOVEFADINGONFOCUSGAIN' flag in INI file
       
    44 RPointerArray< TDblQue<CWsWindowGroup> > CWsWindowGroup::iChains(3);
       
    45 static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_SwEvent,ECapabilitySwEvent);
       
    46 static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_WriteDeviceData,ECapabilityWriteDeviceData);
       
    47 const TInt KArrayMaxGranularity=0x10000000;
       
    48 
       
    49 CWsWindowGroup* CWsWindowGroup::NewL(CWsClient* aOwner, CScreen* aScreen, 
       
    50 	const TWsClCmdCreateWindowGroup& aCmd)
       
    51 	{
       
    52 	CWsWindowGroup* self = new(ELeave) CWsWindowGroup(aOwner, aScreen);
       
    53 	CleanupStack::PushL(self);
       
    54 	self->ConstructL(aCmd);
       
    55 	CleanupStack::Pop(self);
       
    56 	return self;
       
    57 	}
       
    58 
       
    59 CWsWindowGroup::CWsWindowGroup(CWsClient* aOwner, CScreen* aScreen) : CWsWindowBase(aOwner,WS_HANDLE_GROUP_WINDOW,aScreen)
       
    60 	{
       
    61 	__DECLARE_NAME(_S("CWsWindowGroup"));
       
    62 	iWinType=EWinTypeGroup;
       
    63 	}
       
    64 
       
    65 void CWsWindowGroup::PurgeCapturedKeys()
       
    66 	{
       
    67 	CWsObjectIx& objix=*WsOwner()->ObjectIndex();
       
    68 	const TWsObject* ptr=objix.FirstObject();
       
    69 	const TWsObject* end=ptr+objix.Length();
       
    70 	while(++ptr<end)		//Fisrt one should always have a NULL object
       
    71 		{
       
    72 		const CWsObject* obj=ptr->iObject;
       
    73 		if (obj 
       
    74 			&& ((obj->Type()==WS_HANDLE_CAPTURE_KEY && STATIC_CAST(const CWsCaptureKey*,obj)->WindowGroup()==this)
       
    75 				|| (obj->Type()==WS_HANDLE_CAPTURE_KEY_UPDOWNS && STATIC_CAST(const CWsCaptureKeyUpsAndDowns*,obj)->WindowGroup()==this)
       
    76 				|| (obj->Type()==WS_HANDLE_CAPTURE_LONG_KEY && STATIC_CAST(const CWsCaptureLongKey*,obj)->WindowGroup()==this)))
       
    77 			{
       
    78 			objix.Remove(ptr);
       
    79 			delete obj;
       
    80 			}
       
    81 		}
       
    82 	objix.Tidy();
       
    83 	CKeyboardRepeat::CancelRepeat(this);
       
    84 	}
       
    85 
       
    86 void CWsWindowGroup::SwitchToOwningWindow(CWsWindowGroup *aClosingWindow)
       
    87 	{
       
    88 	if (this==CWsTop::FocusWindowGroup())
       
    89 		{
       
    90 		CWsWindowGroup *winGroup=NULL;
       
    91 //
       
    92 // First try for an 'owning' window
       
    93 //
       
    94 		if (iOwningWindowGroup)
       
    95 			{
       
    96 			for(winGroup=RootWindow()->Child();winGroup;winGroup=winGroup->NextSibling())
       
    97 				if (winGroup->Identifier()==iOwningWindowGroup && winGroup->iOrdinalPriority==iOrdinalPriority)
       
    98 					goto gotIt;
       
    99 			}
       
   100 //
       
   101 // If that failed look for the frontmost window belonging to the owner of dying window
       
   102 //
       
   103 		for(winGroup=RootWindow()->Child();winGroup;winGroup=winGroup->NextSibling())
       
   104 			if (winGroup!=this && winGroup->WsOwner()==WsOwner() && winGroup->iOrdinalPriority==iOrdinalPriority)
       
   105 				goto gotIt;
       
   106 //
       
   107 // Next try for the nominated default owning window group
       
   108 //
       
   109 		winGroup=iScreen->DefaultOwningWindowGroup();
       
   110 		if (winGroup && winGroup->iOrdinalPriority==iOrdinalPriority)
       
   111 			{
       
   112 gotIt:		winGroup->SetOrdinalPosition(0,this);
       
   113 			return;
       
   114 			}
       
   115 		}
       
   116 	ResetFocus(aClosingWindow);
       
   117 	}
       
   118 
       
   119 CWsWindowGroup::~CWsWindowGroup()
       
   120 	{
       
   121 	MWsWindowTreeObserver* windowTreeObserver = NULL;
       
   122 	if (Screen()&& iBaseWinFlags&EBaseWinNodeCreated)
       
   123 		{
       
   124 		windowTreeObserver = Screen()->WindowTreeObserver();
       
   125 		if (windowTreeObserver)
       
   126 			{
       
   127 			if( iQueue && (iQueue->Last()!=this) )
       
   128 				{
       
   129 				//This node is part of chain, send notification unless this is the last node in the chain
       
   130 				windowTreeObserver->WindowGroupChainBrokenAfter(*this);
       
   131 				}
       
   132 			windowTreeObserver->NodeReleased(*this);
       
   133 			iBaseWinFlags &= ~EBaseWinNodeCreated;
       
   134 			}
       
   135 		}
       
   136 	DisconnectFloatingSprites();
       
   137 	
       
   138 	if (wsDebugLog)
       
   139 		{
       
   140 		TLogMessageText buf;
       
   141 		_LIT(KWSERVDebugLogGroupWindowId,"Destroying: RWindowGroup[0x%x,%d],Id=%d");
       
   142 		buf.Format(KWSERVDebugLogGroupWindowId,iClientHandle,LogHandle(),iIdentifier);
       
   143 		wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, buf);
       
   144 		}
       
   145 	if (CClick::IsHandler())
       
   146 		CClick::OtherEvent(EEventGroupWindowClose,reinterpret_cast<TAny*>(iIdentifier));
       
   147 	if (iQueue)
       
   148 		{
       
   149 		if (iQueue->Last()!=this)
       
   150 			{		//Unlink all the children of the window that is being deleted
       
   151 			TDblQueIter<CWsWindowGroup> iter(*iQueue);
       
   152 			CWsWindowGroup* groupWin;
       
   153 			iter.SetToLast();
       
   154 			while ((groupWin=iter--)!=this)
       
   155 				{
       
   156 				WS_ASSERT_DEBUG(groupWin!=NULL && groupWin->iQueue==iQueue,EWsPanicGroupWindowChainError);
       
   157 				if ( windowTreeObserver && (iQueue->Last()!=groupWin) )
       
   158 					{
       
   159 					//Send notification unless groupWin is the last node in the chain
       
   160 					windowTreeObserver->WindowGroupChainBrokenAfter(*groupWin);
       
   161 					}
       
   162 				groupWin->iChainLink.Deque();
       
   163 				// coverity[extend_simple_error]
       
   164 				groupWin->iQueue=NULL;
       
   165 				}
       
   166 			}
       
   167 		WS_ASSERT_DEBUG(iQueue->Last()==this,EWsPanicGroupWindowChainError);
       
   168 		if(windowTreeObserver && !iQueue->IsEmpty())
       
   169 			{
       
   170 			//If there are chained nodes before this one, notify "chain broken" immediately before this node 
       
   171 			TDblQueIter<CWsWindowGroup> iter(*iQueue);
       
   172 			iter.SetToLast(); 	//i.e. set to this (see assert above)
       
   173 			iter--;				//i.e. set to parent
       
   174 			CWsWindowGroup* parent = iter;
       
   175 			if(parent)
       
   176 				{
       
   177 				windowTreeObserver->WindowGroupChainBrokenAfter(*parent);
       
   178 				}
       
   179 			}
       
   180 		TDblQueLinkBase* parentLink=iChainLink.iPrev;
       
   181 		iChainLink.Deque();
       
   182 		if (parentLink->iNext==parentLink->iPrev)		//Check to see chain no longer required
       
   183 			{
       
   184 			if (!iQueue->IsEmpty())
       
   185 				{				//Only the parent is left in queue
       
   186 				CWsWindowGroup* parent=iQueue->First();
       
   187 				static_cast<TDblQueLink*>(parentLink)->Deque();
       
   188 				WS_ASSERT_DEBUG(parent->iQueue==iQueue,EWsPanicGroupWindowChainError);
       
   189 				// coverity[extend_simple_error]
       
   190 				parent->iQueue=NULL;
       
   191 				}
       
   192 			DeleteQueue(iQueue);
       
   193 			}
       
   194 		}
       
   195 	RemoveAllPriorityKeys();
       
   196 	PurgeCapturedKeys();
       
   197 	iTextCursor.Close();
       
   198 	SetPointerCursor(NULL);
       
   199 	for(CWsTopClientWindow *win=Child();win;win=win->NextSiblingTop())
       
   200 		win->SetInactive();
       
   201 	if (iScreen)
       
   202 		{
       
   203 		iScreen->RemoveFromDefaultOwningList(this);
       
   204 		}
       
   205 	CWsWindowBase::Shutdown();
       
   206 	TWindowServerEvent::SendGroupChangedEvents();
       
   207 	// coverity[extend_simple_error]
       
   208 	iClientHandle=0;	// To block focus lost events being sent
       
   209 // Decide which window to give focus to if WServ isn't shutting down
       
   210 	if (iScreen && !CWsTop::ShuttingDown())
       
   211 		SwitchToOwningWindow(this);
       
   212 	delete iGroupName;
       
   213 	delete iMessageArray;
       
   214 	}
       
   215 
       
   216 void CWsWindowGroup::DisconnectFloatingSprites()
       
   217 	{
       
   218 	CWsSpriteBase * current = iSpriteList;
       
   219 	while (current)
       
   220 		{
       
   221 		CWsSpriteBase * next = current->Next();
       
   222 		current->Deactivate();
       
   223 		current->DisconnectGroupWin();
       
   224 		current = next;
       
   225 		}
       
   226 	}
       
   227 
       
   228 void CWsWindowGroup::DeleteQueue(TDblQue<CWsWindowGroup>* aQueue)
       
   229 	{
       
   230 	iChains.Remove(iChains.Find(aQueue));
       
   231 	delete aQueue;
       
   232 	if (iChains.Count()==0)
       
   233 		{
       
   234 		iChains.Compress();
       
   235 		}
       
   236 	}
       
   237 
       
   238 void CWsWindowGroup::AdvanceIdentifierCount()
       
   239 	{
       
   240 	if (++iIdentifierCount>EMaxIdentifierCount)
       
   241 		iIdentifierCount=1;		// so limit it to low value
       
   242 	}
       
   243 
       
   244 void CWsWindowGroup::ConstructL(const TWsClCmdCreateWindowGroup &aCmd)
       
   245 	{
       
   246 #if defined(_DEBUG)
       
   247 	if (IsClientHandleInUse(aCmd.clientHandle))
       
   248 		{
       
   249 		OwnerPanic(EWservPanicDuplicateHandle);
       
   250 		}
       
   251 #endif
       
   252 	NewObjL();
       
   253 	iFlags=EGroupFlagAutoForeground|EGroupFlagMsgQueueNew;
       
   254 	if (aCmd.focus)
       
   255 		{
       
   256 		iFlags|=EGroupFlagReceivesFocus;
       
   257 		}
       
   258 	iTextCursor.ConstructL(this);
       
   259 	iClientHandle=aCmd.clientHandle;
       
   260 
       
   261 	if(aCmd.screenDeviceHandle <= 0)
       
   262 		{
       
   263 		//Use primary screen. Client should make sure PrimaryScreenDevice is correct set up immediately after establishing session.
       
   264 		iScreenDevice=iWsOwner->PrimaryScreenDevice();
       
   265 		}
       
   266 	else
       
   267 		{
       
   268 		//Use the specified screen
       
   269 		iScreenDevice=STATIC_CAST(DWsScreenDevice*,iWsOwner->HandleToObj(aCmd.screenDeviceHandle,WS_HANDLE_SCREEN_DEVICE));
       
   270 		}
       
   271 
       
   272 	iScreen = (iScreenDevice) ? iScreenDevice->Screen() : CWsTop::Screen(); //if no screen device use screen 0
       
   273 
       
   274 	CWsWindowGroup* parent=NULL;
       
   275 	if (aCmd.parentId>0)
       
   276 		{
       
   277 		parent=CWsWindowGroup::WindowGroupFromIdentifier(aCmd.parentId);
       
   278 		if (!parent)
       
   279 			{
       
   280 			OwnerPanic(EWservPanicWindow);
       
   281 			}
       
   282 		
       
   283  		if(parent->Screen() != iScreen)
       
   284  			{
       
   285  			OwnerPanic(EWservPanicWrongScreen);
       
   286  			}
       
   287 		
       
   288 		if (parent->iOrdinalPriorityAdjust>0)
       
   289 			{
       
   290 			WS_ASSERT_DEBUG(parent->iQueue==NULL,EWsPanicGroupWindowChainError);
       
   291 			parent->iOrdinalPriorityAdjust=0;
       
   292 			parent->UpdateOrdinalPriority(ETrue);
       
   293 			}
       
   294 		iOrdinalPriorityBase=parent->iOrdinalPriorityBase;
       
   295 		iOrdinalPriority=iOrdinalPriorityBase;
       
   296 		}
       
   297 
       
   298 	do
       
   299 		{
       
   300 		AdvanceIdentifierCount();	// Always advance by at least one to stop re-using last id
       
   301 		} while (WindowGroupFromIdentifier(iIdentifierCount)); // If current count is in use try again
       
   302 	iIdentifier=iIdentifierCount;
       
   303 
       
   304 	CWsWindowBase::ConstructL(RootWindow());
       
   305 	iScreen->ResetFocus(NULL);
       
   306 	
       
   307 	if (parent)
       
   308 		{
       
   309 		TDblQue<CWsWindowGroup>* queue=parent->iQueue;
       
   310 		if (queue && queue->Last()!=parent)
       
   311 			User::Leave(KErrInUse);
       
   312 		if (parent->iWsOwner!=iWsOwner)
       
   313 			{
       
   314 			_LIT_SECURITY_POLICY_S0(securityPolicy,parent->iChildSID);
       
   315 			if (!securityPolicy().CheckPolicy(iWsOwner->ClientMessage()))
       
   316 				User::Leave(KErrPermissionDenied);
       
   317 			}
       
   318 		if (!queue)
       
   319 			{
       
   320 			queue=new(ELeave) TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
       
   321 			CleanupStack::PushL(queue);
       
   322 			User::LeaveIfError(iChains.Append(queue));
       
   323 			CleanupStack::Pop(queue);
       
   324 			queue->AddFirst(*parent);
       
   325 			parent->iQueue=queue;			
       
   326 			}
       
   327 		iQueue=queue;		//Shouldn't set the queue until after it can leave
       
   328 		iChainLink.Enque(&parent->iChainLink);
       
   329 		
       
   330 		MWsWindowTreeObserver* const windowTreeObserver = Screen()->WindowTreeObserver();						
       
   331 		if (windowTreeObserver)
       
   332 			{
       
   333 			windowTreeObserver->WindowGroupChained(*parent, *this);
       
   334 			}			
       
   335 		}
       
   336 	iMessageArray=new(ELeave) CArrayVarSeg<TWsMessage>(1);
       
   337 	if (CClick::IsHandler())
       
   338 		{
       
   339 		TGroupWindowOpenData params;
       
   340 		params.iIdentifier=iIdentifier;
       
   341 		params.iClient=iWsOwner->ConnectionHandle();
       
   342 		params.iNumClientWindowGroups=NumClientWindowGroups()-1;	//Don't include this one
       
   343 		CClick::OtherEvent(EEventGroupWindowOpen,&params);
       
   344 		}
       
   345 	if (wsDebugLog)
       
   346 		{
       
   347 		TLogMessageText buf;
       
   348 		_LIT(KWSERVDebugLogGroupWindowId,"Creating: RWindowGroup[0x%x,%d],Id=%d");
       
   349 		buf.Format(KWSERVDebugLogGroupWindowId,iClientHandle,LogHandle(),iIdentifier);
       
   350 		wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, buf);
       
   351 		}
       
   352 	}
       
   353 
       
   354 void CWsWindowGroup::UpdateOrdinalPriority(TBool aDoAdjust)
       
   355 	{
       
   356 	TInt newPri;
       
   357 	newPri=iOrdinalPriorityBase;
       
   358 	if (iWsOwner==CWsTop::FocusWindowGroupOwner())
       
   359 		newPri+=iOrdinalPriorityAdjust;
       
   360 	CheckCapability(newPri);
       
   361 	if (newPri!=iOrdinalPriority)
       
   362 		{
       
   363 		iOrdinalPriority=newPri;
       
   364 		if (aDoAdjust)
       
   365 			SetOrdinalPosition(0);
       
   366 		}
       
   367 	}
       
   368 
       
   369 void CWsWindowGroup::SetOrdinalPriority(TInt aPos,TInt aPriority)
       
   370 	{
       
   371 	if (!iQueue)
       
   372 		{
       
   373 		iOrdinalPriorityBase=aPriority;
       
   374 		UpdateOrdinalPriority(EFalse);
       
   375 		}
       
   376 	else
       
   377 		{
       
   378 		TDblQueIter<CWsWindowGroup> iter(*iQueue);
       
   379 		CWsWindowGroup* group;
       
   380 		while ((group=iter++)!=NULL)
       
   381 			{
       
   382 			group->iOrdinalPriorityBase=aPriority;
       
   383 			group->iOrdinalPriority=aPriority;
       
   384 			}
       
   385 		}
       
   386 	SetOrdinalPosition(aPos);
       
   387 	}
       
   388 
       
   389 void CWsWindowGroup::CommandL(TInt aOpcode, const TAny *aCmdData)
       
   390 	{
       
   391 #ifdef _DEBUG
       
   392 	// Save root window for performing CheckTree at the end of this func.
       
   393 	// When aOpcode is EWsWinOpFree, this object would've been destroyed
       
   394 	// and a call to RootWindow() in that case would be impossible
       
   395 	CWsRootWindow* rootWindow=RootWindow();
       
   396 
       
   397 	// For certain opcodes, check for the 'screen device deleted' condition. If it
       
   398 	// has occured for the screen device associated with this group window then
       
   399 	// those op-codes are not valid, and the client is panicked.
       
   400 	switch (aOpcode)
       
   401 		{
       
   402 		case EWsWinOpEnableScreenChangeEvents:
       
   403 		case EWsWinOpAllowChildWindowGroup:
       
   404 		case EWsWinOpReceiveFocus:
       
   405 		case EWsWinOpAutoForeground:
       
   406 		case EWsWinOpSetOrdinalPositionPri:
       
   407 		case EWsWinOpSetOrdinalPriorityAdjust:
       
   408 		case EWsWinOpCaptureKey:
       
   409 		case EWsWinOpCaptureKeyUpsAndDowns:
       
   410 		case EWsWinOpCaptureLongKey:
       
   411 		case EWsWinOpAddPriorityKey:
       
   412 		case EWsWinOpSetTextCursor:
       
   413 		case EWsWinOpSetTextCursorClipped:
       
   414 		case EWsWinOpSetOwningWindowGroup:
       
   415 		case EWsWinOpDefaultOwningWindow:
       
   416 		case EWsWinOpSetName:
       
   417 		case EWsWinOpDisableKeyClick:
       
   418 		case EWsWinOpSendPointerEvent:
       
   419 		case EWsWinOpSendAdvancedPointerEvent:
       
   420 			{
       
   421 			if (ScreenDeviceDeleted())
       
   422 				OwnerPanic(EWservPanicGroupWinScreenDeviceDeleted);
       
   423 			break;				
       
   424 			};
       
   425 		}
       
   426 #endif
       
   427 
       
   428 	TWsWinCmdUnion pData;
       
   429 	pData.any=aCmdData;
       
   430 	if (CWsWindowBase::CommandL(aOpcode,pData)==EFalse)
       
   431 		{
       
   432 		switch(aOpcode)
       
   433 			{
       
   434 			case EWsWinOpAllowChildWindowGroup:
       
   435 				iChildSID=*pData.UInt;
       
   436 				break;
       
   437 			case EWsWinOpEnableScreenChangeEvents:
       
   438 				SetScreenChangeEventStateL(ETrue);
       
   439 				break;
       
   440 			case EWsWinOpDisableScreenChangeEvents:
       
   441 				SetScreenChangeEventStateL(EFalse);
       
   442 				break;
       
   443 			case EWsWinOpReceiveFocus:
       
   444 				if (*pData.Bool!=(iFlags&EGroupFlagReceivesFocus))
       
   445 					{
       
   446 					iFlags&=~EGroupFlagReceivesFocus;
       
   447 					if (*pData.Bool)
       
   448 						iFlags|=EGroupFlagReceivesFocus;
       
   449 					iScreen->ResetFocus(NULL);
       
   450 					}
       
   451 				break;
       
   452 			case EWsWinOpAutoForeground:
       
   453 				iFlags&=~EGroupFlagAutoForeground;
       
   454 				if (*pData.Bool)
       
   455 					iFlags|=EGroupFlagAutoForeground;
       
   456 				break;
       
   457 			case EWsWinOpSetOrdinalPositionPri:
       
   458 			case EWsWinOpSetOrdinalPositionErr:
       
   459 				{
       
   460 				TInt priority=pData.OrdinalPos->ordinalPriority;
       
   461 				TBool hascap = CheckCapability(priority);
       
   462 				SetOrdinalPriority(pData.OrdinalPos->pos, priority);
       
   463 				if (aOpcode == EWsWinOpSetOrdinalPositionErr)
       
   464 					{
       
   465 					SetReply(hascap?KErrNone:KErrPermissionDenied);
       
   466 					}
       
   467 				}
       
   468 				break;
       
   469 			case EWsWinOpSetOrdinalPriorityAdjust:
       
   470 				if (!iQueue)
       
   471 					{
       
   472 					iOrdinalPriorityAdjust=*pData.Int;
       
   473 					UpdateOrdinalPriority(ETrue);
       
   474 					}
       
   475 				break;
       
   476 			case EWsWinOpCaptureKey:
       
   477 				{
       
   478 				if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureKey API")))
       
   479 					{
       
   480 					User::Leave(KErrPermissionDenied);
       
   481 					}
       
   482 				CWsCaptureKey *cKey=new(ELeave) CWsCaptureKey(this);
       
   483 				CleanupStack::PushL(cKey);
       
   484 				cKey->ConstructL(*pData.CaptureKey);
       
   485 				CleanupStack::Pop();
       
   486 				}
       
   487 				break;
       
   488 			case EWsWinOpCaptureKeyUpsAndDowns:
       
   489 				{
       
   490 				if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureKeyUpsAndDowns API")))
       
   491 					{
       
   492 					User::Leave(KErrPermissionDenied);
       
   493 					}
       
   494 				CWsCaptureKeyUpsAndDowns *cKey=new(ELeave) CWsCaptureKeyUpsAndDowns(this);
       
   495 				CleanupStack::PushL(cKey);
       
   496 				cKey->ConstructL(*pData.CaptureKey);
       
   497 				CleanupStack::Pop();
       
   498 				}
       
   499 				break;
       
   500 			case EWsWinOpCaptureLongKey:
       
   501 				{
       
   502 				if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureLongKey API")))
       
   503 					{
       
   504 					User::Leave(KErrPermissionDenied);
       
   505 					}
       
   506 				CWsCaptureLongKey *cKey=new(ELeave) CWsCaptureLongKey(this);
       
   507 				CleanupStack::PushL(cKey);
       
   508 				cKey->ConstructL(*pData.CaptureLongKey);
       
   509 				CleanupStack::Pop();
       
   510 				}
       
   511 				break;
       
   512 			case EWsWinOpCancelCaptureKey:
       
   513 				if (*pData.UInt!=0)	// Ignore null handle
       
   514 					{
       
   515 					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt, WS_HANDLE_CAPTURE_KEY);
       
   516 					if (destroyObj)
       
   517 						{
       
   518 						//Cancel any repeat that is underway for this key
       
   519 						const TWsWinCmdCaptureKey& capKey(*pData.CaptureKey);
       
   520 						CKeyboardRepeat::CancelRepeat(this,capKey.key,EFalse,capKey.modifierMask);
       
   521 						delete destroyObj;
       
   522 						}
       
   523 					else
       
   524 						{
       
   525 #ifdef _DEBUG
       
   526 						// Attempt to cancel key capture with an incorrect handle
       
   527 						OwnerPanic(EWservPanicDestroy);  
       
   528 #endif // _DEBUG
       
   529 						}					
       
   530 					}
       
   531 				break;
       
   532 			case EWsWinOpCancelCaptureKeyUpsAndDowns:
       
   533 				if (*pData.UInt!=0)	// Ignore null handle
       
   534 					{
       
   535 					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt, WS_HANDLE_CAPTURE_KEY_UPDOWNS);
       
   536 					if (destroyObj)
       
   537 						{
       
   538 						//Cancel any repeat that is underway for this key
       
   539 						const TWsWinCmdCaptureKey& capKey(*pData.CaptureKey);
       
   540 						CKeyboardRepeat::CancelRepeat(this,capKey.key,EFalse,capKey.modifierMask);
       
   541 						delete destroyObj;
       
   542 						}
       
   543 					else
       
   544 						{
       
   545 #ifdef _DEBUG						
       
   546 						// Attempt to cancel ups and downs key capture with an incorrect handle
       
   547 						OwnerPanic(EWservPanicDestroy);
       
   548 #endif // _DEBUG
       
   549 						}					
       
   550 					}
       
   551 				break;
       
   552 			case EWsWinOpCancelCaptureLongKey:
       
   553 				if (*pData.UInt!=0)	// Ignore null handle
       
   554 					{
       
   555 					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt, WS_HANDLE_CAPTURE_LONG_KEY);
       
   556 					if (destroyObj)
       
   557 						{
       
   558 						//Cancel any repeat that is underway for this key
       
   559 						const TWsWinCmdCaptureLongKey& capKey(*pData.CaptureLongKey);
       
   560 						CKeyboardRepeat::CancelRepeat(this,capKey.inputKey,ETrue,capKey.modifierMask);
       
   561 						delete destroyObj;
       
   562 						} 
       
   563 					else
       
   564 						{
       
   565 #ifdef _DEBUG						
       
   566 						// Attempt to cancel long key capture with an incorrect handle
       
   567 						OwnerPanic(EWservPanicDestroy);
       
   568 #endif // _DEBUG
       
   569 						}					
       
   570 					}
       
   571 				break;
       
   572 			case EWsWinOpAddPriorityKey:
       
   573 				AddPriorityKeyL(pData.PriorityKey->keycode, pData.PriorityKey->modifierMask, pData.PriorityKey->modifiers);
       
   574 				break;
       
   575 			case EWsWinOpRemovePriorityKey:
       
   576 				RemovePriorityKey(pData.PriorityKey->keycode, pData.PriorityKey->modifierMask, pData.PriorityKey->modifiers);
       
   577 				break;
       
   578 			case EWsWinOpSetTextCursor:
       
   579 				iTextCursor.SetL(*pData.SetTextCursor, EFalse);
       
   580 				break;
       
   581 			case EWsWinOpSetTextCursorClipped:
       
   582 				iTextCursor.SetL(*pData.SetTextCursor, ETrue);
       
   583 				break;
       
   584 			case EWsWinOpCancelTextCursor:
       
   585 				iTextCursor.Cancel();
       
   586 				break;
       
   587 			case EWsWinOpSetOwningWindowGroup:
       
   588 				iOwningWindowGroup=*pData.Int;
       
   589 				break;
       
   590 			case EWsWinOpDefaultOwningWindow:
       
   591 				{
       
   592 				if(KSecurityPolicy_WriteDeviceData().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::DefaultOwningWindow API")))
       
   593 					{
       
   594 					iScreen->SetDefaultOwningWindow(this);
       
   595 					}
       
   596 				}
       
   597 				break;
       
   598 			case EWsWinOpName:
       
   599 				iWsOwner->ReplyGroupName(iGroupName,*pData.Int);
       
   600 				break;
       
   601 			case EWsWinOpSetName:
       
   602 				{
       
   603 				HBufC *newName=NULL;
       
   604 				const TInt size=*pData.Int;
       
   605 				if (size>0)
       
   606 					{
       
   607 					newName=HBufC::NewLC(size);
       
   608 					TPtr ptr(newName->Des());
       
   609 					iWsOwner->RemoteReadL(ptr,0);
       
   610 					CleanupStack::Pop(newName);
       
   611 					}
       
   612 				//Window Group Name is unchanged
       
   613 				if (iGroupName && newName && *iGroupName == *newName)
       
   614 					{
       
   615 					delete newName;
       
   616 					} 
       
   617 				else  //Window Group Name is changed
       
   618 					{  
       
   619 					delete iGroupName;
       
   620 					iGroupName=newName;
       
   621 					TWindowServerEvent::SendGroupChangedEvents();
       
   622 					if (iScreen && iScreen->ChangeTracking())
       
   623 					    {
       
   624 				        MWsWindowTreeObserver* const windowTreeObserver = iScreen->WindowTreeObserver();
       
   625 				        if (windowTreeObserver)
       
   626 				            windowTreeObserver->AttributeChanged(*this, MWsWindowTreeObserver::EWindowGroupName);
       
   627 					    }
       
   628 					}
       
   629 				}
       
   630 				break;
       
   631 			case EWsWinOpIdentifier:
       
   632 				SetReply(Identifier());
       
   633 				break;
       
   634 			case EWsWinOpDisableKeyClick:
       
   635 				if (*pData.Bool)
       
   636 					iFlags|=EGroupFlagDisableKeyClick;
       
   637 				else
       
   638 					iFlags&=~EGroupFlagDisableKeyClick;
       
   639 				if (this==CWsTop::FocusWindowGroup())
       
   640 					UpdateKeyClickState();
       
   641 				break;
       
   642 			case EWsWinOpSendAdvancedPointerEvent:
       
   643 			case EWsWinOpSendPointerEvent:
       
   644 				{
       
   645 				TRawEvent eventCopy = *pData.RawEvent;
       
   646 				if (TWsPointer::PreProcessClientEvent(eventCopy, aOpcode == EWsWinOpSendAdvancedPointerEvent))
       
   647 					{
       
   648 					if (!TWindowServerEvent::MousePress(eventCopy,this))
       
   649 						{
       
   650 						OwnerPanic(EWservPanicEventType);
       
   651 						}
       
   652 					}
       
   653 				}
       
   654 				break;
       
   655 			case EWsWinOpClearChildGroup:
       
   656 				if(iQueue)
       
   657 					{
       
   658 					TBool fBefore=EFalse; 
       
   659 					TBool fAfter=EFalse; 
       
   660 					// If there is nothing to clear, return KErrArgument
       
   661 					if(iQueue->Last()==this)
       
   662 						{
       
   663 						SetReply(KErrArgument);
       
   664 						break;
       
   665 						}
       
   666 					// fBefore is True if there is AT LEAST one window group queued before the current one
       
   667 					else if(iQueue->First()!=this)
       
   668 						{
       
   669 						fBefore=ETrue;
       
   670 						}
       
   671 					// fAfter is True if there is MORE THAN one window group queued after the current one
       
   672 					TDblQueIter<CWsWindowGroup> iter(*iQueue);
       
   673 					iter.SetToLast();
       
   674 					if(iter--!=this && iter!=this)
       
   675 						{
       
   676 						fAfter=ETrue;
       
   677 						}
       
   678 					TDblQue<CWsWindowGroup>* queue=NULL;
       
   679 					// if fBefore and fAfter are True, create a new queue and copy all window groups after the current one into that queue
       
   680 					if(fBefore && fAfter)
       
   681 						{
       
   682 						TInt ret=KErrNoMemory;
       
   683 						queue=new TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
       
   684 						if(queue)
       
   685 							{
       
   686 							ret=iChains.Append(queue);	
       
   687 							if(ret!=KErrNone)
       
   688 								{
       
   689 								delete queue;
       
   690 								queue=NULL; 
       
   691 								}
       
   692 							}
       
   693 						// Check that the queue creation and appending worked (we deque all the child groups even if it didn't) 
       
   694 						if(ret!=KErrNone)
       
   695 							{
       
   696 							SetReply(ret);
       
   697 							}
       
   698 						}
       
   699 					// If we've got zero or one window groups after, don't need to queue them
       
   700 					if(!fAfter || fBefore)
       
   701 						{
       
   702 						iter.SetToLast();
       
   703 						CWsWindowGroup* groupWin;
       
   704 						while((groupWin=iter--)!=this)
       
   705 							{
       
   706 							groupWin->iChainLink.Deque();
       
   707 							groupWin->iQueue=queue;
       
   708 							if(queue)
       
   709 								queue->AddFirst(*groupWin);
       
   710 							}
       
   711 						}
       
   712 					// if we've got no window groups before, don't need to have a queue for this anymore
       
   713 					if(!fBefore)
       
   714 						{
       
   715 						iChainLink.Deque();
       
   716 						if (!fAfter)
       
   717 							{
       
   718 							DeleteQueue(iQueue);
       
   719 							}
       
   720 						iQueue=NULL;						
       
   721 						}
       
   722 					if (Screen())
       
   723 						{
       
   724 					MWsWindowTreeObserver* const windowTreeObserver = Screen()->WindowTreeObserver();
       
   725 					if (windowTreeObserver)
       
   726 						{
       
   727 						windowTreeObserver->WindowGroupChainBrokenAfter(*this);
       
   728 							}
       
   729 						}					
       
   730 					}
       
   731 				else // if this window group isn't queued, we can't clear any children
       
   732 					{
       
   733 					SetReply(KErrArgument);
       
   734 					}
       
   735 				break;
       
   736 			case EWsWinOpSetChildGroup:
       
   737 				{
       
   738 				CWsWindowGroup* childWinGroup = CWsWindowGroup::WindowGroupFromIdentifier(*pData.Int);
       
   739 				if(!childWinGroup																	//(no child to append)
       
   740 					|| (iQueue && (!iQueue->IsLast(this) || (childWinGroup->iQueue==iQueue)))		//(GpWin has a child) || (GpWin and childGpWin in the same queue)
       
   741 					|| (childWinGroup->iQueue && !childWinGroup->iQueue->IsFirst(childWinGroup))	//(childGpWin has a parent)
       
   742 					|| (childWinGroup == this))														//(childGpWin == GpWin)
       
   743 					{
       
   744 					SetReply(KErrArgument);
       
   745 					break;
       
   746 					}
       
   747 				if(iQueue)
       
   748 				// If we have a chain, we're prepending ourselves to the child window group
       
   749 				// So we take the childs chain and prepend each of the window groups in our own chain
       
   750 				// beginning with the current window group and working backward
       
   751 					{
       
   752 					TDblQueIter<CWsWindowGroup> iter(*iQueue);
       
   753 					iter.SetToLast();
       
   754 					CWsWindowGroup* groupWin;
       
   755 					if(childWinGroup->iQueue)
       
   756 						{
       
   757 						TDblQue<CWsWindowGroup>* oldQueue=iQueue;
       
   758 						while((groupWin=iter--)!=NULL)
       
   759 							{
       
   760 							groupWin->iChainLink.Deque();
       
   761 							childWinGroup->iQueue->AddFirst(*groupWin);
       
   762 							groupWin->iQueue=childWinGroup->iQueue;
       
   763 							}
       
   764 						DeleteQueue(oldQueue);
       
   765 						}
       
   766 					else
       
   767 						{
       
   768 						iQueue->AddLast(*childWinGroup);
       
   769 						childWinGroup->iQueue=iQueue;							
       
   770 						}
       
   771 					}
       
   772 				else
       
   773 				// 1. If we don't have a chain, and if the child has a chain, we can simply prepend this wg to the child
       
   774 				// wg chain
       
   775 				// 2. If we don't have a chain, and if the child does not have a chain, need to create a chain with the child
       
   776 				//    as the owning member, and prepend our window group
       
   777 					{
       
   778 					if(childWinGroup->iQueue)
       
   779 						{
       
   780 						childWinGroup->iQueue->AddFirst(*this);
       
   781 						iQueue=childWinGroup->iQueue;
       
   782 						}
       
   783 					else
       
   784 						{
       
   785 						TDblQue<CWsWindowGroup>* queue=new TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
       
   786 						TInt ret=KErrNoMemory;
       
   787 						if (queue)
       
   788 							{
       
   789 							ret=iChains.Append(queue);
       
   790 							if(ret!=KErrNone)
       
   791 								{
       
   792 								delete queue;
       
   793 								}
       
   794 							}
       
   795 						if(ret!=KErrNone)
       
   796 							{
       
   797 							SetReply(ret);
       
   798 							break;
       
   799 							}
       
   800 						queue->AddFirst(*childWinGroup);
       
   801 						childWinGroup->iQueue=queue;
       
   802 						queue->AddFirst(*this);
       
   803 						iQueue=queue;						
       
   804 						}						
       
   805 					}
       
   806 				if (Screen())
       
   807 					{
       
   808 				MWsWindowTreeObserver* const windowTreeObserver = Screen()->WindowTreeObserver();						
       
   809 				if (windowTreeObserver)
       
   810 					{
       
   811 					windowTreeObserver->WindowGroupChained(*this, *childWinGroup);
       
   812 						}
       
   813 					}
       
   814 				}
       
   815 				break;
       
   816 			default:						// All other window commands disallowed
       
   817 				OwnerPanic(EWservPanicOpcode);
       
   818 			}
       
   819 		}
       
   820 #if defined(_DEBUG)
       
   821 	rootWindow->CheckTree();
       
   822 #endif
       
   823 	}
       
   824 	
       
   825 TPoint CWsWindowGroup::Origin() const
       
   826 	{
       
   827 	return TPoint(0,0);
       
   828 	}
       
   829 	
       
   830 TRect CWsWindowGroup::AbsRect() const
       
   831 	{
       
   832 	return (TRect(RootWindow()->Abs().iTl,RootWindow()->Size()));
       
   833 	}
       
   834 
       
   835 TSize CWsWindowGroup::Size() const
       
   836 	{
       
   837 	return RootWindow()->Size();
       
   838 	}
       
   839 
       
   840 void CWsWindowGroup::SendState(MWsWindowTreeObserver& aWindowTreeObserver) const
       
   841 	{	
       
   842 	aWindowTreeObserver.NodeCreated(*this, ParentNode());
       
   843 	}
       
   844 
       
   845 void CWsWindowGroup::SendStateWindowGroupChain(MWsWindowTreeObserver& aWindowTreeObserver) const
       
   846 	{
       
   847 	if ( iQueue && (!iQueue->IsEmpty()) && (iQueue->First()==this) )
       
   848 		{
       
   849 		TDblQueIter<CWsWindowGroup> iter(*iQueue);
       
   850 		CWsWindowGroup* groupParent;
       
   851 		CWsWindowGroup* groupChild;
       
   852 		
       
   853 		while ( (groupParent=iter++)!=NULL && (groupChild=iter)!=NULL )
       
   854 			{
       
   855 			aWindowTreeObserver.WindowGroupChained(*groupParent, *groupChild);
       
   856 			}
       
   857 		}
       
   858 	}
       
   859 
       
   860 TInt CWsWindowGroup::Identifier() const
       
   861 	{
       
   862 	return iIdentifier;
       
   863 	}
       
   864 
       
   865 TPtrC CWsWindowGroup::Name() const
       
   866 	{
       
   867 	return (iGroupName) ? *iGroupName : KNullDesC();
       
   868 	}
       
   869 
       
   870 TBool CWsWindowGroup::IsFocusable() const
       
   871 	{
       
   872 	return ReceivesFocus();
       
   873 	}
       
   874 
       
   875 TInt CWsWindowGroup::OrdinalPriority() const
       
   876 	{
       
   877 	return iOrdinalPriorityBase;
       
   878 	}
       
   879 
       
   880 const MWsClient * CWsWindowGroup::Client() const
       
   881     {
       
   882     return static_cast<const MWsClient*>(WsOwner());
       
   883     }
       
   884 
       
   885 
       
   886 void CWsWindowGroup::UpdateKeyClickState()
       
   887 	{
       
   888 	CClick::SetKeyClickOveride(iFlags&EGroupFlagDisableKeyClick);
       
   889 	}
       
   890 
       
   891 void CWsWindowGroup::AreaCovered(TRegion &aRegion)
       
   892 	{
       
   893 	aRegion.Clear();
       
   894 	for(CWsClientWindow *win=Child();win;win=win->NextSibling())
       
   895 		aRegion.Union(*win->BaseArea());
       
   896 	}
       
   897 
       
   898 void CWsWindowGroup::SetOrdinalPosition(TInt aPos)
       
   899 	{
       
   900 	if (aPos==(TInt)KOrdinalPositionSwitchToOwningWindow)
       
   901 		SwitchToOwningWindow(NULL);
       
   902 	else
       
   903 		SetOrdinalPosition(aPos,NULL);
       
   904 	}
       
   905 
       
   906 TBool CWsWindowGroup::SetOrdinalPosition(TInt aPos,CWsWindowGroup* aClosingWindow)
       
   907 	{
       
   908 	TBool ret=ETrue;
       
   909 	if (!iQueue)
       
   910 		ret=DoSetOrdinalPosition1(aPos,aClosingWindow);
       
   911 	else
       
   912 		{
       
   913 		TDblQueIter<CWsWindowGroup> iter(*iQueue);
       
   914 		CWsWindowGroup* group;
       
   915 		iter.SetToLast();
       
   916 		TInt after=0;
       
   917 		TInt before=0;
       
   918 		TInt* inc=&before;
       
   919 		while ((group=iter--)!=NULL)
       
   920 			{
       
   921 			if (group==this)
       
   922 				inc=&after;
       
   923 			++(*inc);
       
   924 			}
       
   925 		TInt lastWinGpPos=NumWindowGroupsOnMyScreen(OrdinalPriority())-after;
       
   926 		if (aPos<0)
       
   927 			aPos=lastWinGpPos;
       
   928 		else
       
   929 			aPos=Min(aPos,lastWinGpPos);
       
   930 		aPos-=before;
       
   931 		aPos=Max(aPos,0);
       
   932 		iter.SetToLast();
       
   933 		CWsWindowGroup* firstForward=iter--;
       
   934 		while (firstForward && firstForward->OrdinalPosition(EFalse)<aPos)
       
   935 			{
       
   936 			firstForward=iter--;
       
   937 			++aPos;
       
   938 			}
       
   939 		if (!firstForward)
       
   940 			iter.SetToFirst();
       
   941 		else
       
   942 			{
       
   943 			iter.Set(*firstForward);
       
   944 			MoveChainedWindows(iter,ETrue,aPos,aClosingWindow);
       
   945 			iter.Set(*firstForward);
       
   946 			iter++;
       
   947 			}
       
   948 		MoveChainedWindows(iter,EFalse,--aPos,aClosingWindow);
       
   949 #if defined(_DEBUG)
       
   950 		iter.SetToLast();
       
   951 		TInt pos1=-1;
       
   952 		TInt pos2;
       
   953 		TBool ok=ETrue;
       
   954 		while ((group=iter--)!=this)
       
   955 			{
       
   956 			pos2=group->OrdinalPosition(EFalse);
       
   957 			if (pos2<=pos1)
       
   958 				ok=EFalse;
       
   959 			pos1=pos2;
       
   960 			}
       
   961 		WS_ASSERT_DEBUG(ok, EWsPanicGroupWindowChainError);
       
   962 #endif
       
   963 		}
       
   964 
       
   965 	return ret;
       
   966 	}
       
   967 
       
   968 
       
   969 void CWsWindowGroup::MoveChainedWindows(TDblQueIter<CWsWindowGroup>& aIter,TBool aForward,TInt aPos,CWsWindowGroup* aClosingWindow)
       
   970 	{
       
   971 	CWsWindowGroup* groupWindow;
       
   972 	while ((groupWindow=(aForward ? aIter-- : aIter++))!=NULL)
       
   973 		{
       
   974 		groupWindow->DoSetOrdinalPosition1(aPos,aClosingWindow);
       
   975 		(aForward ? ++aPos : --aPos);
       
   976 		}
       
   977 	}
       
   978 
       
   979 TBool CWsWindowGroup::DoSetOrdinalPosition1(TInt aPos,CWsWindowGroup* aClosingWindow)
       
   980 	{
       
   981 	TBool ret=EFalse;
       
   982 	if (CheckOrdinalPositionChange(aPos))
       
   983 		{
       
   984 		if (Child())	// A group window with no children can not affect shadows
       
   985 			{
       
   986 			ret=ETrue;
       
   987 			}
       
   988 		DoSetOrdinalPosition2(aPos,aClosingWindow);
       
   989 		}
       
   990 	else if (aClosingWindow)    // do not reset focus if current groupwindow did not change its ordinal position
       
   991 		iScreen->ResetFocus(aClosingWindow);
       
   992 	return ret;
       
   993 	}
       
   994 
       
   995 void CWsWindowGroup::DoSetOrdinalPosition2(TInt aPos, CWsWindowGroup *aClosingWindow)
       
   996 	{
       
   997 	ChangeWindowPosition(aPos,iParent);
       
   998 	ResetFocus(aClosingWindow);
       
   999 	}
       
  1000 
       
  1001 void CWsWindowGroup::LostFocus()
       
  1002 	{
       
  1003 	iTextCursor.LostFocus();
       
  1004 	iWsOwner->UpdateWindowOrdinalPrioritys();
       
  1005 	if (iClientHandle!=0)
       
  1006 		QueueEvent(EEventFocusLost);
       
  1007 	TWalkWindowTreeFocusChanged wwt(EFalse);
       
  1008 	WalkWindowTree(wwt,EWalkChildren);
       
  1009 	iWsOwner->SetClientPriority();
       
  1010 	}
       
  1011 
       
  1012 void CWsWindowGroup::ReceivedFocus()
       
  1013 	{
       
  1014 	iWsOwner->UpdateWindowOrdinalPrioritys();
       
  1015 	iTextCursor.ReceivedFocus();
       
  1016 	// Used for event queue testing
       
  1017 	// Calling MoveToFront sets the queue of the focused window to first place, 
       
  1018 	// not doing so puts the queues in unusual situation thus stress testing the queue code. 
       
  1019 	// One such situation is where the focus queue is first but there is a gap before it (iEventPtr>iGlobalEventPtr)" 
       
  1020 #if defined(_DEBUG)
       
  1021 	if ((iEventQueueTest) && (++iSkipCount==5))
       
  1022 		{
       
  1023 		iSkipCount=0;
       
  1024 		}
       
  1025 	else
       
  1026 		{
       
  1027 		WsOwner()->EventQueue()->MoveToFront();
       
  1028 		}
       
  1029 #else
       
  1030 	WsOwner()->EventQueue()->MoveToFront();
       
  1031 #endif
       
  1032 
       
  1033 	QueueEvent(EEventFocusGained);
       
  1034 	TWalkWindowTreeFocusChanged wwt(ETrue);
       
  1035 	WalkWindowTree(wwt,EWalkChildren);
       
  1036 	iWsOwner->SetClientPriority();
       
  1037 	UpdateKeyClickState();
       
  1038 	}
       
  1039 
       
  1040 TInt CWsWindowGroup::NumWindowGroups(TBool aAllPriorities, TInt aPriority)
       
  1041 	{
       
  1042 	TInt count=0;
       
  1043 	TInt screenNo;
       
  1044 	for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
       
  1045 		{
       
  1046 		count+=CWsWindowGroup::NumWindowGroupsOnScreen(CWsTop::Screen(screenNo)->RootWindow()->Child(),aAllPriorities,aPriority);
       
  1047 		}
       
  1048 	return(count);
       
  1049 	}
       
  1050 
       
  1051 TInt CWsWindowGroup::NumWindowGroupsOnScreen(const CWsWindowGroup* aGroupWin,TBool aAllPriorities,TInt aPriority)
       
  1052 	{
       
  1053 	TInt count=0;
       
  1054 	while (aGroupWin)
       
  1055 		{
       
  1056 		if (aAllPriorities || aGroupWin->iOrdinalPriority==aPriority)
       
  1057 			++count;
       
  1058 		aGroupWin=aGroupWin->NextSibling();
       
  1059 		}
       
  1060 	return count;
       
  1061 	}
       
  1062 
       
  1063 inline TInt CWsWindowGroup::NumWindowGroupsOnMyScreen(TInt aPriority)
       
  1064 	{
       
  1065 	return(CWsWindowGroup::NumWindowGroupsOnScreen(Parent()->Child(),EFalse,aPriority));
       
  1066 	}
       
  1067 
       
  1068 void CWsWindowGroup::GetFocusWindowGroupL(TInt aScreenNumber)
       
  1069 	{
       
  1070 	CWsWindowGroup *groupWin=(aScreenNumber==KDummyScreenNumber)?CWsTop::FocusWindowGroup():CWsTop::Screen(aScreenNumber)->FocusWindowGroup();	
       
  1071 	if (!groupWin)
       
  1072 		User::Leave(KErrGeneral);
       
  1073 	CWsClient::SetReply(groupWin->Identifier());
       
  1074 	}
       
  1075 
       
  1076 TInt CWsWindowGroup::GetWindowGroupListL(TInt aScreenNo,TBool aAllPriorities,TInt aPriority,TInt aCount,CArrayFixFlat<TInt>* aList)
       
  1077 	{
       
  1078 	TInt count=aList->Count();
       
  1079 	CWsWindowGroup* groupWin=CWsTop::Screen(aScreenNo)->RootWindow()->Child();
       
  1080 	while(!aAllPriorities && groupWin && groupWin->iOrdinalPriority!=aPriority)
       
  1081 		groupWin=groupWin->NextSibling();
       
  1082 	while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==aPriority) && count<aCount)
       
  1083 		{
       
  1084 		aList->AppendL(groupWin->Identifier());
       
  1085 		++count;
       
  1086 		groupWin=groupWin->NextSibling();
       
  1087 		}
       
  1088 	return count;
       
  1089 	}
       
  1090 	
       
  1091 TInt CWsWindowGroup::SendWindowGroupListL(TInt aScreenNumber, TBool aAllPriorities, TInt aPriority, TInt aCount)
       
  1092 	{
       
  1093 	if ((aCount<1) || (aCount>(KArrayMaxGranularity/sizeof(TInt))))
       
  1094 		User::Leave(KErrArgument);
       
  1095 	CArrayFixFlat<TInt>* list=new(ELeave) CArrayFixFlat<TInt>(aCount);
       
  1096 	CleanupStack::PushL(list);
       
  1097 	TInt count(0);
       
  1098 	TInt requestedScreen=aScreenNumber;	
       
  1099 	if(requestedScreen==KDummyScreenNumber)
       
  1100 		{
       
  1101 		// get list from current focus screen first
       
  1102 		TInt focusScreenNo=CWsTop::CurrentFocusScreen()->ScreenNumber();
       
  1103 		count=GetWindowGroupListL(focusScreenNo, aAllPriorities, aPriority, aCount, list);
       
  1104 		if(count<aCount)
       
  1105 			{
       
  1106 			// now get from the remaining screen
       
  1107 			TInt screenNo;
       
  1108 			for(screenNo=0;screenNo<CWsTop::NumberOfScreens() && count<aCount;++screenNo)
       
  1109 				{
       
  1110 				// skip focus screen
       
  1111 				if (screenNo==focusScreenNo)
       
  1112 					continue;
       
  1113 				// count hold total number of window groups collected so far
       
  1114 				count=GetWindowGroupListL(screenNo, aAllPriorities, aPriority, aCount, list);
       
  1115 				}			
       
  1116 			}
       
  1117 		}
       
  1118 	else
       
  1119 		{
       
  1120 		count=GetWindowGroupListL(requestedScreen, aAllPriorities, aPriority, aCount, list);	
       
  1121 		}
       
  1122 	if (list->Count() > 0)	
       
  1123 		CWsClient::ReplyBuf(&list->At(0),count*sizeof(TInt));
       
  1124 	CleanupStack::PopAndDestroy(list);
       
  1125 	return(count);	// How many actually returned, may be less than asked for, but not more
       
  1126 	}
       
  1127 
       
  1128 void CWsWindowGroup::GetWindowGroupListAndChainL(TInt aScreen,TBool aAllPriorities,TInt aPriority
       
  1129 																,RArray<RWsSession::TWindowGroupChainInfo>& list,TInt& aCountLeft)
       
  1130 	{
       
  1131 	CWsWindowGroup *groupWin=CWsTop::Screen(aScreen)->RootWindow()->Child();
       
  1132 	while(!aAllPriorities && groupWin && groupWin->iOrdinalPriority!=aPriority)
       
  1133 		groupWin=groupWin->NextSibling();
       
  1134 	while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==aPriority) && aCountLeft>0)
       
  1135 		{
       
  1136 		RWsSession::TWindowGroupChainInfo windowId;
       
  1137 		windowId.iId=groupWin->Identifier();
       
  1138 		if(!groupWin->IsChained(windowId.iParentId))
       
  1139 			windowId.iParentId=-1;	//Unchained window group
       
  1140 		list.AppendL(windowId);
       
  1141 		--aCountLeft;
       
  1142 		groupWin=groupWin->NextSibling();
       
  1143 		}
       
  1144 	}
       
  1145 
       
  1146 TInt CWsWindowGroup::SendWindowGroupListAndChainL(TBool aAllPriorities, TInt aPriority, TInt aCount)
       
  1147 	{
       
  1148 	if ((aCount<1) || (aCount>(KArrayMaxGranularity/sizeof(RWsSession::TWindowGroupChainInfo))))
       
  1149 		User::Leave(KErrArgument);
       
  1150 	RArray<RWsSession::TWindowGroupChainInfo> list(aCount);
       
  1151 	CleanupClosePushL(list);
       
  1152 	TInt count=aCount;
       
  1153 	TInt focusScreenNo=CWsTop::CurrentFocusScreen()->ScreenNumber();
       
  1154 	GetWindowGroupListAndChainL(focusScreenNo,aAllPriorities,aPriority,list,count);
       
  1155 	TInt screenNo;
       
  1156 	for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
       
  1157 		{
       
  1158 		if (screenNo!=focusScreenNo)
       
  1159 			GetWindowGroupListAndChainL(screenNo,aAllPriorities,aPriority,list,count);
       
  1160 		}
       
  1161 	if (list.Count()>0)
       
  1162 		CWsClient::ReplyBuf(&list[0],aCount*sizeof(RWsSession::TWindowGroupChainInfo));
       
  1163 	CleanupStack::PopAndDestroy(&list);
       
  1164 	return(aCount-count);	// How many actually returned, may be less than asked for, but not more
       
  1165 	}
       
  1166 
       
  1167 TBool CWsWindowGroup::SendEventToAllGroups(TBool aAllPriorities,TBool aOnePerClient,const TWsClCmdSendEventToWindowGroup& aData)
       
  1168 	{
       
  1169 	TWsEvent event=aData.event;
       
  1170 	if (event.Type()==EEventKey && event.Key()->iRepeats!=0)
       
  1171 		CKeyboardRepeat::CancelRepeat(NULL);		//Otherwise we will trip an invarient
       
  1172 	TInt priority=aData.parameter;
       
  1173 	TBool sentToAll=ETrue;
       
  1174 	TInt screenNo;
       
  1175 	for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
       
  1176 		{
       
  1177 		CWsWindowGroup *groupWin=CWsTop::Screen(screenNo)->RootWindow()->Child();
       
  1178 		if (!aAllPriorities)
       
  1179 			{
       
  1180 			while(groupWin && groupWin->iOrdinalPriority!=priority)
       
  1181 				groupWin=groupWin->NextSibling();
       
  1182 			}
       
  1183 		CWsWindowGroup* firstGroupWin=groupWin;
       
  1184 		CWsClient* lastOwner=NULL;
       
  1185 		CWsWindowGroup* groupWin2;
       
  1186 		while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==priority))
       
  1187 			{
       
  1188 			if (aOnePerClient)
       
  1189 				{
       
  1190 				if (lastOwner==groupWin->iWsOwner)
       
  1191 					goto ContinueLoop;
       
  1192 				lastOwner=groupWin->iWsOwner;
       
  1193 				for(groupWin2=firstGroupWin;groupWin2!=groupWin;groupWin2=groupWin2->NextSibling())
       
  1194 					{
       
  1195 					if (groupWin2->iWsOwner==groupWin->iWsOwner)
       
  1196 						break;
       
  1197 					}
       
  1198 				if (groupWin2->iWsOwner==groupWin->iWsOwner && groupWin2!=groupWin)
       
  1199 					goto ContinueLoop;
       
  1200 				}
       
  1201 			event.SetHandle(groupWin->ClientHandle());
       
  1202 			if (!groupWin->EventQueue()->QueueEvent(event))
       
  1203 				sentToAll=EFalse;
       
  1204 		ContinueLoop:
       
  1205 			groupWin=groupWin->NextSibling();
       
  1206 			}
       
  1207 		}
       
  1208 	return sentToAll;
       
  1209 	}
       
  1210 
       
  1211 void CWsWindowGroup::ReleasePendedMessagesToAllGroups(CWsClient * aClient)
       
  1212 	{
       
  1213 	TInt screenNo;
       
  1214 	for (screenNo = 0; screenNo < CWsTop::NumberOfScreens(); ++screenNo)
       
  1215 		{
       
  1216 		CWsWindowGroup* groupWin = CWsTop::Screen(screenNo)->RootWindow()->Child();
       
  1217 		while (groupWin)
       
  1218 			{
       
  1219 			if (groupWin->WsOwner() == aClient)
       
  1220 				{
       
  1221 				groupWin->ReleasePendedMessage();
       
  1222 				}
       
  1223 			groupWin = groupWin->NextSibling();
       
  1224 			}
       
  1225 		}
       
  1226 	}
       
  1227 
       
  1228 void CWsWindowGroup::ReleasePendedMessage()
       
  1229     {
       
  1230     if (iMessageArray->Count() > 0 && !(iFlags & EGroupFlagMessageSignalled))
       
  1231         {
       
  1232         if (!SignalMessageReady())
       
  1233 			{
       
  1234 			//The event queue is overflow
       
  1235 			// Cannot send a message notification event. 
       
  1236 			WsOwner()->WgMsgQueueOverflow(); // Set flag for client about having pended message(s)
       
  1237 			}
       
  1238         }
       
  1239     }
       
  1240 
       
  1241 void CWsWindowGroup::SendMessageToAllGroupsL(CWsClient& aSender,TBool aAllPriorities,const TWsClCmdSendMessageToWindowGroup& aData)
       
  1242 	{
       
  1243 	TInt screenNo;
       
  1244 	for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
       
  1245 		{
       
  1246 		CWsWindowGroup* groupWin=CWsTop::Screen(screenNo)->RootWindow()->Child();		
       
  1247 		if (!aAllPriorities)
       
  1248 			{
       
  1249 			while(groupWin && groupWin->iOrdinalPriority!=aData.identifierOrPriority)
       
  1250 				groupWin=groupWin->NextSibling();
       
  1251 			}
       
  1252 		while(groupWin && (aAllPriorities || (groupWin->iOrdinalPriority==aData.identifierOrPriority)))
       
  1253 			{
       
  1254 			groupWin->QueueMessageL(aData.uid, aData.dataLength, aSender);
       
  1255 			groupWin=groupWin->NextSibling();
       
  1256 			}
       
  1257 		}
       
  1258 	}
       
  1259 
       
  1260 CWsWindowGroup *CWsWindowGroup::WindowGroupFromIdentifier(TInt aIdentifier)
       
  1261 	{
       
  1262 	// apply to all screens
       
  1263 	TInt screenNo;
       
  1264 	for (screenNo=0; screenNo<CWsTop::NumberOfScreens(); ++screenNo)
       
  1265 		{
       
  1266 		CWsWindowGroup* group;
       
  1267 		for(group=CWsTop::Screen(screenNo)->RootWindow()->Child(); group; group=group->NextSibling())
       
  1268 			{
       
  1269 			if (group->Identifier() == aIdentifier)
       
  1270 				return group;
       
  1271 			}
       
  1272 			
       
  1273 		}
       
  1274 		
       
  1275 	return NULL;
       
  1276 	}
       
  1277 
       
  1278 CWsWindowGroup *CWsWindowGroup::WindowGroupFromIdentifierL(TInt aIdentifier)
       
  1279 	{
       
  1280 	CWsWindowGroup *group=WindowGroupFromIdentifier(aIdentifier);
       
  1281 	if (!group)
       
  1282 		User::Leave(KErrNotFound);
       
  1283 	return(group);
       
  1284 	}
       
  1285 
       
  1286 CWsWindowGroup *CWsWindowGroup::FindWindowGroupL(CWsClient* aClient, TInt aIdentifier,TInt aOffset,const TPtrC *aMatch,const TThreadId *aThreadId)
       
  1287 	{
       
  1288 	CWsWindowGroup *group;
       
  1289 	if (aIdentifier)
       
  1290 		{
       
  1291 		group=WindowGroupFromIdentifier(aIdentifier);
       
  1292 		if (group)	// NULL group will cause KErrNotFound to be returned
       
  1293 			group=group->NextSibling();
       
  1294 		}
       
  1295 	else
       
  1296 		{
       
  1297 		// get window group for this session
       
  1298 		//
       
  1299 		group = aClient->Screen()->RootWindow()->Child();
       
  1300 		}
       
  1301 
       
  1302 	for(;group;group=group->NextSibling())
       
  1303 		{
       
  1304 		if (aThreadId)
       
  1305 			{
       
  1306 			if (group->WsOwner()->Client().Id()==*aThreadId)
       
  1307 				break;	// Found one
       
  1308 			}
       
  1309 		else
       
  1310 			{
       
  1311 			const TDesC *groupName=&nullDescriptor;
       
  1312 			if (group->GroupName())
       
  1313 				groupName=group->GroupName();
       
  1314 			if (groupName->Length()>=aOffset && groupName->Mid(aOffset).MatchF(*aMatch)>=0)
       
  1315 				break;	// Found one
       
  1316 			}
       
  1317 		}
       
  1318 	if (!group)
       
  1319 		User::Leave(KErrNotFound);
       
  1320 	return(group);
       
  1321 	}
       
  1322 
       
  1323 void CWsWindowGroup::AddPriorityKeyL(TUint aKeycode, TUint aModifierMask, TUint aModifiers)
       
  1324 	{
       
  1325 	iPriorityKeys=new(ELeave) TPriorityKey(aKeycode,aModifierMask,aModifiers,iPriorityKeys);
       
  1326 	}
       
  1327 
       
  1328 void CWsWindowGroup::RemovePriorityKey(TUint aKeycode, TUint aModifierMask, TUint aModifiers)
       
  1329 	{
       
  1330 	for(TPriorityKey **ppk=&iPriorityKeys;*ppk;ppk=&((*ppk)->iNext))
       
  1331 		if ((*ppk)->Equals(aKeycode, aModifierMask, aModifiers))
       
  1332 			{
       
  1333 			TPriorityKey *next=(*ppk)->iNext;
       
  1334 			delete *ppk;
       
  1335 			*ppk=next;
       
  1336 			break;
       
  1337 			}
       
  1338 	}
       
  1339 
       
  1340 void CWsWindowGroup::RemoveAllPriorityKeys()
       
  1341 	{
       
  1342 	TPriorityKey *pk=iPriorityKeys;
       
  1343 	while(pk)
       
  1344 		{
       
  1345 		TPriorityKey *next=pk->iNext;
       
  1346 		delete pk;
       
  1347 		pk=next;
       
  1348 		}
       
  1349 	}
       
  1350 
       
  1351 TBool CWsWindowGroup::CheckForPriorityKey(const TKeyData &aKey, TInt aScanCode)
       
  1352 	{
       
  1353 	for(TPriorityKey *pk=iPriorityKeys;pk;pk=pk->iNext)
       
  1354 		{
       
  1355 		if (pk->KeyMatches(aKey))
       
  1356 			{	
       
  1357 			WsOwner()->PriorityKeyPressed(ClientHandle(),aKey, aScanCode);
       
  1358 			return(ETrue);
       
  1359 			}
       
  1360 		}
       
  1361 	return(EFalse);
       
  1362 	}
       
  1363 
       
  1364 void CWsWindowGroup::StatusDump(TDes &aBuf)
       
  1365 	{
       
  1366 	_LIT(KWSERVStatusDumpWindowGroupInfo,"CWsWindowGroup[0x%x]RWindowGroup[0x%x,%d],Pri=%d,Id=%d,SizeMode=%d");
       
  1367 	aBuf.AppendFormat(KWSERVStatusDumpWindowGroupInfo,this,iClientHandle,LogHandle(),iOrdinalPriority,iIdentifier,iScreenDevice?iScreenDevice->AppMode():0);
       
  1368 	}
       
  1369 
       
  1370 TBool CWsWindowGroup::SignalMessageReady()
       
  1371 	{
       
  1372 	TWsEvent event;
       
  1373 	event.SetType(EEventMessageReady);
       
  1374 	event.SetHandle(ClientHandle());
       
  1375 	event.SetTimeNow();
       
  1376 	SEventMessageReady& eventMessageReady=*(SEventMessageReady*)event.EventData();
       
  1377 	eventMessageReady.iWindowGroupIdentifier=Identifier();
       
  1378 	eventMessageReady.iMessageUid=(*iMessageArray)[0].iUid;
       
  1379 	eventMessageReady.iMessageParametersSize=iMessageArray->Length(0)-sizeof(TUid);
       
  1380 	TBool result = WsOwner()->EventQueue()->QueueEvent(event, EEventPriorityHigh);
       
  1381 	if (result)
       
  1382 		{
       
  1383 		iFlags |= EGroupFlagMessageSignalled;
       
  1384 		}
       
  1385 	return result;
       
  1386 	}
       
  1387 
       
  1388 void CWsWindowGroup::QueueMessageL(TUid aUid, TInt aDataLength, CWsClient& aSender)
       
  1389 	{
       
  1390 	WS_ASSERT_DEBUG(iFlags&(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew) || iMessageArray->Count()>=1,EWsPanicMsgQueueError);
       
  1391 	if (!(iFlags&(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew)) && iMessageArray->Count()>=KMaxNumberOfMsgsInInactiveQueue)
       
  1392 		{
       
  1393 		WS_ASSERT_DEBUG(iMessageArray->Count()<=KMaxNumberOfMsgsInInactiveQueue,EWsPanicMsgQueueError);
       
  1394 		iMessageArray->Delete(1,iMessageArray->Count()-1);
       
  1395 		}
       
  1396 	TWsMessage* message=NULL;
       
  1397 	TRAPD(err,message=&iMessageArray->ExtendL(aDataLength+sizeof(aUid)));
       
  1398 	if ((err || (iFlags&EGroupFlagMsgQueueNew)) && iMessageArray->Count()>KMaxNumberOfMsgsInQueue)
       
  1399 		{
       
  1400 		iFlags&=~(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew);
       
  1401 		iMessageArray->Delete(1,iMessageArray->Count()-(err?1:2));
       
  1402 		iMessageArray->Compress();
       
  1403 		}
       
  1404 	User::LeaveIfError(err);
       
  1405 	if (message)
       
  1406 		{
       
  1407 		message->iUid=aUid;
       
  1408 		TPtr8 ptr(&message->iTheRest[0],aDataLength);
       
  1409 		TRAP(err,aSender.RemoteReadL(ptr,0));
       
  1410 		if (err)
       
  1411 			{
       
  1412 			iMessageArray->Delete(iMessageArray->Count()-1);
       
  1413 			User::Leave(err);
       
  1414 			}
       
  1415 		if (!(iFlags & EGroupFlagMessageSignalled))
       
  1416 			{
       
  1417 			if (!SignalMessageReady())
       
  1418 				{
       
  1419 				//The event queue is overflow
       
  1420 				// Cannot send a message notification event. 
       
  1421 				WsOwner()->WgMsgQueueOverflow(); // Set flag for client about having pended message(s)
       
  1422 				}
       
  1423 			}
       
  1424 		}
       
  1425 	}
       
  1426 
       
  1427 void CWsWindowGroup::FetchMessageL()
       
  1428 	{
       
  1429 	if (!(iFlags & EGroupFlagMessageSignalled))
       
  1430 		{
       
  1431 		OwnerPanic(EWservPanicFetchMessage);
       
  1432 		}
       
  1433 	CWsClient::ReplyBuf(&((*iMessageArray)[0].iTheRest[0]), (TInt) iMessageArray->Length(0) - sizeof(TUid));
       
  1434 	iMessageArray->Delete(0);
       
  1435 	iFlags |= EGroupFlagMsgQueueActive;
       
  1436 	iFlags &= ~(EGroupFlagMessageSignalled | EGroupFlagMsgQueueNew);
       
  1437 	if (iMessageArray->Count() > 0)
       
  1438 		{
       
  1439 		if (!SignalMessageReady())
       
  1440 			{
       
  1441 			//The event queue is overflow
       
  1442 			// Cannot send a message notification event. 
       
  1443 			WsOwner()->WgMsgQueueOverflow(); // Set flag for client about having pended message(s)
       
  1444 			}
       
  1445 		}
       
  1446 	}
       
  1447 
       
  1448 TBool CWsWindowGroup::ScreenDeviceValid() const
       
  1449 	{
       
  1450 	return(iScreenDevice?iScreenDevice->ScreenDeviceValidState():(iScreen->ScreenSizeMode()==0));
       
  1451 	}
       
  1452 
       
  1453 TBool CWsWindowGroup::CanReceiveFocus() const
       
  1454 	{
       
  1455 	return(ReceivesFocus() && iWsOwner->NotClosing() && (ScreenDeviceValid() || iFlags&EGroupFlagHandlesDeviceChange));
       
  1456 	}
       
  1457 
       
  1458 void CWsWindowGroup::SetScreenChangeEventStateL(TBool aEnabled)
       
  1459 	{
       
  1460 	iFlags&=~EGroupFlagHandlesDeviceChange;
       
  1461 	if (aEnabled)
       
  1462 		{
       
  1463 		iFlags|=EGroupFlagHandlesDeviceChange;
       
  1464 		TWindowServerEvent::AddToScreenDeviceChangeEventListL(*this);
       
  1465 		if (iScreen->ScreenSizeMode()!=0)
       
  1466 			TWindowServerEvent::SendScreenDeviceChangedEvent(this);
       
  1467 		}
       
  1468 	else
       
  1469 		TWindowServerEvent::RemoveFromScreenDeviceChangeEventList(*this);
       
  1470 	iScreen->ResetFocus(NULL);
       
  1471 	}
       
  1472 
       
  1473 void CWsWindowGroup::SetScreenDeviceValidState(const DWsScreenDevice *aDevice)
       
  1474 	{
       
  1475 	if (iScreenDevice==aDevice)
       
  1476 		{
       
  1477 		TBool state=ScreenDeviceValid();
       
  1478 		for(CWsTopClientWindow *win=Child();win;win=win->NextSiblingTop())
       
  1479 			{
       
  1480 			win->SetScreenDeviceValidState(state);
       
  1481 			}
       
  1482 		}
       
  1483 	}
       
  1484 
       
  1485 void CWsWindowGroup::SetScreenDeviceValidStates(const DWsScreenDevice *aDevice)
       
  1486 	{
       
  1487 	for(CWsWindowGroup *groupWin=aDevice->RootWindow()->Child();groupWin;groupWin=groupWin->NextSibling())
       
  1488 		groupWin->SetScreenDeviceValidState(aDevice);
       
  1489 	}
       
  1490 
       
  1491 void CWsWindowGroup::SetScreenDeviceValidStates(CScreen* aScreen)
       
  1492 	{
       
  1493 	CWsRootWindow* rootWindow = aScreen->RootWindow();
       
  1494 
       
  1495 	CWsWindowGroup* groupWin;
       
  1496 	CWsTopClientWindow* win;
       
  1497 	for(groupWin=rootWindow->Child();groupWin;groupWin=groupWin->NextSibling())
       
  1498 		{
       
  1499 		TBool state=groupWin->ScreenDeviceValid();
       
  1500 		for(win=groupWin->Child();win;win=win->NextSiblingTop())
       
  1501 			{
       
  1502 			win->SetScreenDeviceValidStateFlag(state);
       
  1503 			win->ResetHiddenFlagsInParentAndChildren();
       
  1504 			}
       
  1505 		}
       
  1506 	}
       
  1507 
       
  1508 void CWsWindowGroup::SetScreenDevice(DWsScreenDevice *aDevice)
       
  1509 	{
       
  1510 	iScreenDevice=aDevice;	
       
  1511 	}
       
  1512 
       
  1513 void CWsWindowGroup::NewOrientation(TInt aMode,CFbsBitGc::TGraphicsOrientation aRotation, CWsRootWindow* aRootWindow)
       
  1514 	{
       
  1515 	for(CWsWindowGroup *groupWin=aRootWindow->Child();groupWin;groupWin=groupWin->NextSibling())
       
  1516 		{
       
  1517 		DWsScreenDevice *device=groupWin->Device();
       
  1518 		if (device)
       
  1519 			device->NewOrientation(aMode,aRotation);
       
  1520 		}
       
  1521 	}
       
  1522 
       
  1523 void CWsWindowGroup::ResetFocus(CWsWindowGroup *aClosingWindow)
       
  1524 	{
       
  1525 	if (iScreen)
       
  1526 		{
       
  1527 		iScreen->ResetFocus(aClosingWindow);
       
  1528 		}
       
  1529 	}
       
  1530 
       
  1531 TBool CWsWindowGroup::IsChained(TInt& aParentId)
       
  1532 	{
       
  1533 	if (!iQueue)
       
  1534 		return EFalse;
       
  1535 	if (iQueue->First()==this)
       
  1536 		aParentId=0;
       
  1537 	else
       
  1538 		aParentId=BeforeInChain()->Identifier();
       
  1539 	return ETrue;
       
  1540 	}
       
  1541 
       
  1542 inline CWsWindowGroup* CWsWindowGroup::BeforeInChain()
       
  1543 	{		//You should only call this function if you know the window has a parent
       
  1544 	return reinterpret_cast<CWsWindowGroup*>(PtrSub(iChainLink.iPrev,_FOFF(CWsWindowGroup,iChainLink)));
       
  1545 	}
       
  1546 
       
  1547 TBool CWsWindowGroup::CheckCapability(TInt& aOrdinalPriority)
       
  1548 	{
       
  1549 	if(aOrdinalPriority>=KPasswordWindowGroupPriority)
       
  1550 		{
       
  1551 		if(!KSecurityPolicy_SwEvent().CheckPolicy(WsOwner()->Client(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed")))
       
  1552 			{
       
  1553 			aOrdinalPriority=KPasswordWindowGroupPriority-1;
       
  1554 			return EFalse;
       
  1555 			}
       
  1556 		}
       
  1557  	return ETrue;
       
  1558 	}
       
  1559 	
       
  1560 TBool CWsWindowGroup::HasVisibleTranslucentChild()
       
  1561 	{
       
  1562 	CWsWindowBase * child = iChild;
       
  1563 	while (child)
       
  1564 		{
       
  1565 		if (child->WinType() == EWinTypeClient)
       
  1566 			{
       
  1567 			CWsClientWindow * cliwin = static_cast<CWsClientWindow *>(child);
       
  1568 			if (cliwin->IsTranslucent() && cliwin->IsVisible())
       
  1569 				return ETrue;
       
  1570 			}
       
  1571 		else if (static_cast<CWsWindowGroup*>(child)->HasVisibleTranslucentChild())
       
  1572 			{
       
  1573 			return ETrue;
       
  1574 			}
       
  1575 		child = child->NextSibling();
       
  1576 		}
       
  1577 	return EFalse;
       
  1578 	}
       
  1579 
       
  1580 
       
  1581 TInt CWsWindowGroup::NumClientWindowGroups()
       
  1582 	{
       
  1583 	CWsObjectIx& objix=*WsOwner()->ObjectIndex();
       
  1584 	const TWsObject* ptr=objix.FirstObject();
       
  1585 	const TWsObject* end=ptr+objix.Length();
       
  1586 	TInt count=0;
       
  1587 	while(++ptr<end)		//First one should always have a NULL object
       
  1588 		{
       
  1589 		const CWsObject* obj=ptr->iObject;
       
  1590 		if (obj && obj->Type()==WS_HANDLE_GROUP_WINDOW)
       
  1591 			++count;
       
  1592 		}
       
  1593 	return count;
       
  1594 	}
       
  1595 	
       
  1596 void CWsWindowGroup::SetEventQueueTestState(TBool aEventQueState)
       
  1597 	{
       
  1598 	iEventQueueTest = aEventQueState;
       
  1599 	}