os/graphics/windowing/windowserver/nonnga/SERVER/GROUPWIN.CPP
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/windowing/windowserver/nonnga/SERVER/GROUPWIN.CPP	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,1418 @@
     1.4 +// Copyright (c) 1995-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 +// Group window sub-class of CWsWindow
    1.18 +// 
    1.19 +//
    1.20 +
    1.21 +#include <e32std.h>
    1.22 +#include "W32STD.H"
    1.23 +#include "W32CLICK.H"
    1.24 +#include "server.h"
    1.25 +#include "rootwin.h"
    1.26 +#include "windowgroup.h"
    1.27 +#include "walkwindowtree.h"
    1.28 +#include "wstop.h"
    1.29 +#include "EVENT.H"
    1.30 +#include "KEYCLICK.H"
    1.31 +#include "PRIKEY.H"
    1.32 +#include "panics.h"
    1.33 +
    1.34 +GLREF_D TPtr nullDescriptor;
    1.35 +GLREF_D CDebugLogBase* wsDebugLog;
    1.36 +
    1.37 +#if defined(_DEBUG)
    1.38 +TInt CWsWindowGroup::iSkipCount=0;
    1.39 +#endif
    1.40 +
    1.41 +TInt CWsWindowGroup::iIdentifierCount=1;
    1.42 +TBool CWsWindowGroup::iFocusGainPreProcess=EFalse;		//'REMOVEFADINGONFOCUSGAIN' flag in INI file
    1.43 +RPointerArray< TDblQue<CWsWindowGroup> > CWsWindowGroup::iChains(3);
    1.44 +static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_SwEvent,ECapabilitySwEvent);
    1.45 +static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_WriteDeviceData,ECapabilityWriteDeviceData);
    1.46 +const TInt KArrayMaxGranularity=0x10000000;
    1.47 +
    1.48 +CWsWindowGroup* CWsWindowGroup::NewL(CWsClient* aOwner, CScreen* aScreen, 
    1.49 +	const TWsClCmdCreateWindowGroup& aCmd)
    1.50 +	{
    1.51 +	CWsWindowGroup* self = new(ELeave) CWsWindowGroup(aOwner, aScreen);
    1.52 +	CleanupStack::PushL(self);
    1.53 +	self->ConstructL(aCmd);
    1.54 +	CleanupStack::Pop(self);
    1.55 +	return self;
    1.56 +	}
    1.57 +
    1.58 +CWsWindowGroup::CWsWindowGroup(CWsClient* aOwner, CScreen* aScreen) : CWsWindowBase(aOwner,WS_HANDLE_GROUP_WINDOW,aScreen)
    1.59 +	{
    1.60 +	__DECLARE_NAME(_S("CWsWindowGroup"));
    1.61 +	iWinType=EWinTypeGroup;
    1.62 +	}
    1.63 +
    1.64 +void CWsWindowGroup::PurgeCapturedKeys()
    1.65 +	{
    1.66 +	CWsObjectIx& objix=*WsOwner()->ObjectIndex();
    1.67 +	const TWsObject* ptr=objix.FirstObject();
    1.68 +	const TWsObject* end=ptr+objix.Length();
    1.69 +	while(++ptr<end)		//Fisrt one should always have a NULL object
    1.70 +		{
    1.71 +		const CWsObject* obj=ptr->iObject;
    1.72 +		if (obj 
    1.73 +			&& ((obj->Type()==WS_HANDLE_CAPTURE_KEY && STATIC_CAST(const CWsCaptureKey*,obj)->WindowGroup()==this)
    1.74 +				|| (obj->Type()==WS_HANDLE_CAPTURE_KEY_UPDOWNS && STATIC_CAST(const CWsCaptureKeyUpsAndDowns*,obj)->WindowGroup()==this)
    1.75 +				|| (obj->Type()==WS_HANDLE_CAPTURE_LONG_KEY && STATIC_CAST(const CWsCaptureLongKey*,obj)->WindowGroup()==this)))
    1.76 +			{
    1.77 +			objix.Remove(ptr);
    1.78 +			delete obj;
    1.79 +			}
    1.80 +		}
    1.81 +	objix.Tidy();
    1.82 +	CKeyboardRepeat::CancelRepeat(this);
    1.83 +	}
    1.84 +
    1.85 +void CWsWindowGroup::SwitchToOwningWindow(CWsWindowGroup *aClosingWindow)
    1.86 +	{
    1.87 +	if (this==CWsTop::FocusWindowGroup())
    1.88 +		{
    1.89 +		CWsWindowGroup *winGroup=NULL;
    1.90 +//
    1.91 +// First try for an 'owning' window
    1.92 +//
    1.93 +		if (iOwningWindowGroup)
    1.94 +			{
    1.95 +			for(winGroup=RootWindow()->Child();winGroup;winGroup=winGroup->NextSibling())
    1.96 +				if (winGroup->Identifier()==iOwningWindowGroup && winGroup->iOrdinalPriority==iOrdinalPriority)
    1.97 +					goto gotIt;
    1.98 +			}
    1.99 +//
   1.100 +// If that failed look for the frontmost window belonging to the owner of dying window
   1.101 +//
   1.102 +		for(winGroup=RootWindow()->Child();winGroup;winGroup=winGroup->NextSibling())
   1.103 +			if (winGroup!=this && winGroup->WsOwner()==WsOwner() && winGroup->iOrdinalPriority==iOrdinalPriority)
   1.104 +				goto gotIt;
   1.105 +//
   1.106 +// Next try for the nominated default owning window group
   1.107 +//
   1.108 +		winGroup=iScreen->DefaultOwningWindowGroup();
   1.109 +		if (winGroup && winGroup->iOrdinalPriority==iOrdinalPriority)
   1.110 +			{
   1.111 +gotIt:		winGroup->SetOrdinalPosition(0,this);
   1.112 +			return;
   1.113 +			}
   1.114 +		}
   1.115 +	ResetFocus(aClosingWindow);
   1.116 +	}
   1.117 +
   1.118 +CWsWindowGroup::~CWsWindowGroup()
   1.119 +	{
   1.120 +	if (wsDebugLog)
   1.121 +		{
   1.122 +		TLogMessageText buf;
   1.123 +		_LIT(KWSERVDebugLogGroupWindowId,"Destroying: RWindowGroup[0x%x,%d],Id=%d");
   1.124 +		buf.Format(KWSERVDebugLogGroupWindowId,iClientHandle,LogHandle(),iIdentifier);
   1.125 +		wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, buf);
   1.126 +		}
   1.127 +	if (CClick::IsHandler())
   1.128 +		{
   1.129 +		CClick::OtherEvent(EEventGroupWindowClose,reinterpret_cast<TAny*>(iIdentifier));
   1.130 +		}
   1.131 +	if (iQueue)
   1.132 +		{
   1.133 +		if (iQueue->Last()!=this)
   1.134 +			{		//Unlink all the children of the window that is being deleted
   1.135 +			TDblQueIter<CWsWindowGroup> iter(*iQueue);
   1.136 +			CWsWindowGroup* groupWin;
   1.137 +			iter.SetToLast();
   1.138 +			while ((groupWin=iter--)!=this)
   1.139 +				{
   1.140 +				WS_ASSERT_DEBUG(groupWin!=NULL && groupWin->iQueue==iQueue,EWsPanicGroupWindowChainError);
   1.141 +				groupWin->iChainLink.Deque();
   1.142 +				groupWin->iQueue=NULL;
   1.143 +				}
   1.144 +			}
   1.145 +		WS_ASSERT_DEBUG(iQueue->Last()==this,EWsPanicGroupWindowChainError);
   1.146 +		TDblQueLinkBase* parentLink=iChainLink.iPrev;
   1.147 +		iChainLink.Deque();
   1.148 +		if (parentLink->iNext==parentLink->iPrev)		//Check to see chain no longer required
   1.149 +			{
   1.150 +			if (!iQueue->IsEmpty())
   1.151 +				{				//Only the parent is left in queue
   1.152 +				CWsWindowGroup* parent=iQueue->First();
   1.153 +				static_cast<TDblQueLink*>(parentLink)->Deque();
   1.154 +				WS_ASSERT_DEBUG(parent->iQueue==iQueue,EWsPanicGroupWindowChainError);
   1.155 +				parent->iQueue=NULL;
   1.156 +				}
   1.157 +			DeleteQueue(iQueue);
   1.158 +			}
   1.159 +		iQueue=NULL;
   1.160 +		}
   1.161 +	RemoveAllPriorityKeys();
   1.162 +	PurgeCapturedKeys();
   1.163 +	iTextCursor.Close();
   1.164 +	SetPointerCursor(NULL);
   1.165 +	for(CWsClientWindow *win=Child();win;win=win->NextSibling())
   1.166 +		win->SetInactive();
   1.167 +	if (iScreen)
   1.168 +		{
   1.169 +		iScreen->RemoveFromDefaultOwningList(this);
   1.170 +		}
   1.171 +	CWsWindowBase::Shutdown();
   1.172 +	TWindowServerEvent::SendGroupChangedEvents();
   1.173 +	iClientHandle=0;	// To block focus lost events being sent
   1.174 +// Decide which window to give focus to if WServ isn't shutting down
   1.175 +	if (iScreen && !CWsTop::ShuttingDown())
   1.176 +		SwitchToOwningWindow(this);
   1.177 +	delete iGroupName;
   1.178 +	delete iMessageArray;
   1.179 +	}
   1.180 +
   1.181 +void CWsWindowGroup::DeleteQueue(TDblQue<CWsWindowGroup>* aQueue)
   1.182 +	{
   1.183 +	iChains.Remove(iChains.Find(aQueue));
   1.184 +	delete aQueue;
   1.185 +	if (iChains.Count()==0)
   1.186 +		{
   1.187 +		iChains.Compress();
   1.188 +		}
   1.189 +	}
   1.190 +
   1.191 +void CWsWindowGroup::AdvanceIdentifierCount()
   1.192 +	{
   1.193 +	if (++iIdentifierCount>EMaxIdentifierCount)
   1.194 +		iIdentifierCount=1;		// so limit it to low value
   1.195 +	}
   1.196 +
   1.197 +void CWsWindowGroup::ConstructL(const TWsClCmdCreateWindowGroup &aCmd)
   1.198 +	{
   1.199 +#if defined(_DEBUG)
   1.200 +	if (IsClientHandleInUse(aCmd.clientHandle))
   1.201 +		{
   1.202 +		OwnerPanic(EWservPanicDuplicateHandle);
   1.203 +		}
   1.204 +#endif
   1.205 +	NewObjL();
   1.206 +	iFlags=EGroupFlagAutoForeground|EGroupFlagMsgQueueNew;
   1.207 +	if (aCmd.focus)
   1.208 +		{
   1.209 +		iFlags|=EGroupFlagReceivesFocus;
   1.210 +		}
   1.211 +	iTextCursor.ConstructL(this);
   1.212 +	iClientHandle=aCmd.clientHandle;
   1.213 +	
   1.214 +	if(aCmd.screenDeviceHandle <= 0)
   1.215 +		{
   1.216 +		//Use primary screen. Client should make sure PrimaryScreenDevice is correct set up immediately after establishing session.
   1.217 +		iScreenDevice=iWsOwner->PrimaryScreenDevice();
   1.218 +		}
   1.219 +	else
   1.220 +		{
   1.221 +		//Use the specified screen
   1.222 +		iScreenDevice=STATIC_CAST(DWsScreenDevice*,iWsOwner->HandleToObj(aCmd.screenDeviceHandle,WS_HANDLE_SCREEN_DEVICE));
   1.223 +		}
   1.224 +
   1.225 +	iScreen = (iScreenDevice) ? iScreenDevice->Screen() : CWsTop::Screen(); //if no screen device use screen 0
   1.226 +	
   1.227 +	CWsWindowGroup* parent=NULL;
   1.228 +	if (aCmd.parentId>0)
   1.229 +		{
   1.230 +		parent=CWsWindowGroup::WindowGroupFromIdentifier(aCmd.parentId);
   1.231 +		if (!parent)
   1.232 +			{
   1.233 +			OwnerPanic(EWservPanicWindow);
   1.234 +			}
   1.235 +		
   1.236 +		if(parent->Screen() != iScreen)
   1.237 +			{
   1.238 +			OwnerPanic(EWservPanicWrongScreen);
   1.239 +			}
   1.240 +		
   1.241 +		if (parent->iOrdinalPriorityAdjust>0)
   1.242 +			{
   1.243 +			WS_ASSERT_DEBUG(parent->iQueue==NULL,EWsPanicGroupWindowChainError);
   1.244 +			parent->iOrdinalPriorityAdjust=0;
   1.245 +			parent->UpdateOrdinalPriority(ETrue);
   1.246 +			}
   1.247 +		iOrdinalPriorityBase=parent->iOrdinalPriorityBase;
   1.248 +		iOrdinalPriority=iOrdinalPriorityBase;
   1.249 +		}
   1.250 +	
   1.251 +	CWsWindowBase::ConstructL(RootWindow());
   1.252 +	
   1.253 +	if (parent)
   1.254 +		{
   1.255 +		TDblQue<CWsWindowGroup>* queue=parent->iQueue;
   1.256 +		if (queue && queue->Last()!=parent)
   1.257 +			User::Leave(KErrInUse);
   1.258 +		if (parent->iWsOwner!=iWsOwner)
   1.259 +			{
   1.260 +			_LIT_SECURITY_POLICY_S0(securityPolicy,parent->iChildSID);
   1.261 +			if (!securityPolicy().CheckPolicy(iWsOwner->ClientMessage()))
   1.262 +				User::Leave(KErrPermissionDenied);
   1.263 +			}
   1.264 +		if (!queue)
   1.265 +			{
   1.266 +			queue=new(ELeave) TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
   1.267 +			CleanupStack::PushL(queue);
   1.268 +			User::LeaveIfError(iChains.Append(queue));
   1.269 +			CleanupStack::Pop(queue);
   1.270 +			queue->AddFirst(*parent);
   1.271 +			parent->iQueue=queue;
   1.272 +			}
   1.273 +		iQueue=queue;		//Shouldn't set the queue until after it can leave
   1.274 +		iChainLink.Enque(&parent->iChainLink);
   1.275 +		}
   1.276 +	do
   1.277 +		{
   1.278 +		AdvanceIdentifierCount();	// Always advance by at least one to stop re-using last id
   1.279 +		} while (WindowGroupFromIdentifier(iIdentifierCount)); // If current count is in use try again
   1.280 +	
   1.281 +	iIdentifier=iIdentifierCount;
   1.282 +	iMessageArray=new(ELeave) CArrayVarSeg<TWsMessage>(1);
   1.283 +	if (CClick::IsHandler())
   1.284 +		{
   1.285 +		TGroupWindowOpenData params;
   1.286 +		params.iIdentifier=iIdentifier;
   1.287 +		params.iClient=iWsOwner->ConnectionHandle();
   1.288 +		params.iNumClientWindowGroups=NumClientWindowGroups()-1;	//Don't include this one
   1.289 +		CClick::OtherEvent(EEventGroupWindowOpen,&params);
   1.290 +		}
   1.291 +	if (wsDebugLog)
   1.292 +		{
   1.293 +		TLogMessageText buf;
   1.294 +		_LIT(KWSERVDebugLogGroupWindowId,"Creating: RWindowGroup[0x%x,%d],Id=%d");
   1.295 +		buf.Format(KWSERVDebugLogGroupWindowId,iClientHandle,LogHandle(),iIdentifier);
   1.296 +		wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, buf);
   1.297 +		}
   1.298 +	}
   1.299 +
   1.300 +void CWsWindowGroup::UpdateOrdinalPriority(TBool aDoAdjust)
   1.301 +	{
   1.302 +	TInt newPri;
   1.303 +	newPri=iOrdinalPriorityBase;
   1.304 +	if (iWsOwner==CWsTop::FocusWindowGroupOwner())
   1.305 +		newPri+=iOrdinalPriorityAdjust;
   1.306 +	CheckCapability(newPri);
   1.307 +	if (newPri!=iOrdinalPriority)
   1.308 +		{
   1.309 +		iOrdinalPriority=newPri;
   1.310 +		if (aDoAdjust)
   1.311 +			SetOrdinalPosition(0);
   1.312 +		}
   1.313 +	}
   1.314 +
   1.315 +void CWsWindowGroup::SetOrdinalPriority(TInt aPos,TInt aPriority)
   1.316 +	{
   1.317 +	if (!iQueue)
   1.318 +		{
   1.319 +		iOrdinalPriorityBase=aPriority;
   1.320 +		UpdateOrdinalPriority(EFalse);
   1.321 +		}
   1.322 +	else
   1.323 +		{
   1.324 +		TDblQueIter<CWsWindowGroup> iter(*iQueue);
   1.325 +		CWsWindowGroup* group;
   1.326 +		while ((group=iter++)!=NULL)
   1.327 +			{
   1.328 +			group->iOrdinalPriorityBase=aPriority;
   1.329 +			group->iOrdinalPriority=aPriority;
   1.330 +			}
   1.331 +		}
   1.332 +	SetOrdinalPosition(aPos);
   1.333 +	}
   1.334 +
   1.335 +void CWsWindowGroup::CommandL(TInt aOpcode, const TAny *aCmdData)
   1.336 +	{
   1.337 +#ifdef _DEBUG
   1.338 +	// Save root window for performing CheckTree at the end of this func.
   1.339 +	// When aOpcode is EWsWinOpFree, this object would've been destroyed
   1.340 +	// and a call to RootWindow() in that case would be impossible
   1.341 +	CWsRootWindow* rootWindow=RootWindow();
   1.342 +
   1.343 +	// For certain opcodes, check for the 'screen device deleted' condition. If it
   1.344 +	// has occured for the screen device associated with this group window then
   1.345 +	// those op-codes are not valid, and the client is panicked.
   1.346 +	switch (aOpcode)
   1.347 +		{
   1.348 +		case EWsWinOpEnableScreenChangeEvents:
   1.349 +		case EWsWinOpAllowChildWindowGroup:
   1.350 +		case EWsWinOpReceiveFocus:
   1.351 +		case EWsWinOpAutoForeground:
   1.352 +		case EWsWinOpSetOrdinalPositionPri:
   1.353 +		case EWsWinOpSetOrdinalPriorityAdjust:
   1.354 +		case EWsWinOpCaptureKey:
   1.355 +		case EWsWinOpCaptureKeyUpsAndDowns:
   1.356 +		case EWsWinOpCaptureLongKey:
   1.357 +		case EWsWinOpAddPriorityKey:
   1.358 +		case EWsWinOpSetTextCursor:
   1.359 +		case EWsWinOpSetTextCursorClipped:
   1.360 +		case EWsWinOpSetOwningWindowGroup:
   1.361 +		case EWsWinOpDefaultOwningWindow:
   1.362 +		case EWsWinOpSetName:
   1.363 +		case EWsWinOpDisableKeyClick:
   1.364 +		case EWsWinOpSendPointerEvent:
   1.365 +			{
   1.366 +			if (ScreenDeviceDeleted())
   1.367 +				OwnerPanic(EWservPanicGroupWinScreenDeviceDeleted);
   1.368 +			break;				
   1.369 +			};
   1.370 +		}
   1.371 +#endif
   1.372 +
   1.373 +	TWsWinCmdUnion pData;
   1.374 +	pData.any=aCmdData;
   1.375 +	if (CWsWindowBase::CommandL(aOpcode,pData)==EFalse)
   1.376 +		{
   1.377 +		switch(aOpcode)
   1.378 +			{
   1.379 +			case EWsWinOpAllowChildWindowGroup:
   1.380 +				iChildSID=*pData.UInt;
   1.381 +				break;
   1.382 +			case EWsWinOpEnableScreenChangeEvents:
   1.383 +				SetScreenChangeEventStateL(ETrue);
   1.384 +				break;
   1.385 +			case EWsWinOpDisableScreenChangeEvents:
   1.386 +				SetScreenChangeEventStateL(EFalse);
   1.387 +				break;
   1.388 +			case EWsWinOpReceiveFocus:
   1.389 +				iFlags&=~EGroupFlagReceivesFocus;
   1.390 +				if (*pData.Bool)
   1.391 +					iFlags|=EGroupFlagReceivesFocus;
   1.392 +				iScreen->ResetFocus(NULL);
   1.393 +				break;
   1.394 +			case EWsWinOpAutoForeground:
   1.395 +				iFlags&=~EGroupFlagAutoForeground;
   1.396 +				if (*pData.Bool)
   1.397 +					iFlags|=EGroupFlagAutoForeground;
   1.398 +				break;
   1.399 +			case EWsWinOpSetOrdinalPositionPri:
   1.400 +			case EWsWinOpSetOrdinalPositionErr:
   1.401 +				{
   1.402 +				TInt priority=pData.OrdinalPos->ordinalPriority;
   1.403 +				TBool hascap = CheckCapability(priority);
   1.404 +				SetOrdinalPriority(pData.OrdinalPos->pos, priority);
   1.405 +				if (aOpcode == EWsWinOpSetOrdinalPositionErr)
   1.406 +					{
   1.407 +					SetReply(hascap?KErrNone:KErrPermissionDenied);
   1.408 +					}
   1.409 +				}
   1.410 +				break;
   1.411 +			case EWsWinOpSetOrdinalPriorityAdjust:
   1.412 +				if (!iQueue)
   1.413 +					{
   1.414 +					iOrdinalPriorityAdjust=*pData.Int;
   1.415 +					UpdateOrdinalPriority(ETrue);
   1.416 +					}
   1.417 +				break;
   1.418 +			case EWsWinOpCaptureKey:
   1.419 +				{
   1.420 +				if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureKey API")))
   1.421 +					{
   1.422 +					User::Leave(KErrPermissionDenied);
   1.423 +					}
   1.424 +				CWsCaptureKey *cKey=new(ELeave) CWsCaptureKey(this);
   1.425 +				CleanupStack::PushL(cKey);
   1.426 +				cKey->ConstructL(*pData.CaptureKey);
   1.427 +				CleanupStack::Pop();
   1.428 +				}
   1.429 +				break;
   1.430 +			case EWsWinOpCaptureKeyUpsAndDowns:
   1.431 +				{
   1.432 +				if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureKeyUpsAndDowns API")))
   1.433 +					{
   1.434 +					User::Leave(KErrPermissionDenied);
   1.435 +					}
   1.436 +				CWsCaptureKeyUpsAndDowns *cKey=new(ELeave) CWsCaptureKeyUpsAndDowns(this);
   1.437 +				CleanupStack::PushL(cKey);
   1.438 +				cKey->ConstructL(*pData.CaptureKey);
   1.439 +				CleanupStack::Pop();
   1.440 +				}
   1.441 +				break;
   1.442 +			case EWsWinOpCaptureLongKey:
   1.443 +				{
   1.444 +				if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureLongKey API")))
   1.445 +					{
   1.446 +					User::Leave(KErrPermissionDenied);
   1.447 +					}
   1.448 +				CWsCaptureLongKey *cKey=new(ELeave) CWsCaptureLongKey(this);
   1.449 +				CleanupStack::PushL(cKey);
   1.450 +				cKey->ConstructL(*pData.CaptureLongKey);
   1.451 +				CleanupStack::Pop();
   1.452 +				}
   1.453 +				break;
   1.454 +			case EWsWinOpCancelCaptureKey:
   1.455 +				if (*pData.UInt!=0)	// Ignore null handle
   1.456 +					{
   1.457 +					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt,WS_HANDLE_CAPTURE_KEY);
   1.458 +					if (destroyObj)
   1.459 +						{
   1.460 +						//Cancel any repeat that is underway for this key
   1.461 +						const TWsWinCmdCaptureKey& capKey(*pData.CaptureKey);
   1.462 +						CKeyboardRepeat::CancelRepeat(this,capKey.key,EFalse,capKey.modifierMask);
   1.463 +						delete destroyObj;
   1.464 +						}
   1.465 +					else
   1.466 +						{
   1.467 +#ifdef _DEBUG
   1.468 +						// Attempt to cancel key capture with an incorrect handle
   1.469 +						OwnerPanic(EWservPanicDestroy);  
   1.470 +#endif // _DEBUG
   1.471 +						}					
   1.472 +					}
   1.473 +				break;
   1.474 +			case EWsWinOpCancelCaptureKeyUpsAndDowns:
   1.475 +				if (*pData.UInt!=0)	// Ignore null handle
   1.476 +					{
   1.477 +					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt,WS_HANDLE_CAPTURE_KEY_UPDOWNS);
   1.478 +					if (destroyObj)					
   1.479 +						{
   1.480 +						//Cancel any repeat that is underway for this key
   1.481 +						const TWsWinCmdCaptureKey& capKey(*pData.CaptureKey);
   1.482 +						CKeyboardRepeat::CancelRepeat(this,capKey.key,EFalse,capKey.modifierMask);
   1.483 +						delete destroyObj;
   1.484 +						}
   1.485 +					else
   1.486 +						{
   1.487 +#ifdef _DEBUG						
   1.488 +						// Attempt to cancel ups and downs key capture with an incorrect handle
   1.489 +						OwnerPanic(EWservPanicDestroy);
   1.490 +#endif // _DEBUG
   1.491 +						}					
   1.492 +					}
   1.493 +				break;
   1.494 +			case EWsWinOpCancelCaptureLongKey:
   1.495 +				if (*pData.UInt!=0)	// Ignore null handle
   1.496 +					{
   1.497 +					CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt,WS_HANDLE_CAPTURE_LONG_KEY);
   1.498 +					if (destroyObj)					
   1.499 +						{
   1.500 +						//Cancel any repeat that is underway for this key
   1.501 +						const TWsWinCmdCaptureLongKey& capKey(*pData.CaptureLongKey);
   1.502 +						CKeyboardRepeat::CancelRepeat(this,capKey.inputKey,ETrue,capKey.modifierMask);
   1.503 +						delete destroyObj;
   1.504 +						} 
   1.505 +					else
   1.506 +						{
   1.507 +#ifdef _DEBUG						
   1.508 +						// Attempt to cancel long key capture with an incorrect handle
   1.509 +						OwnerPanic(EWservPanicDestroy);
   1.510 +#endif // _DEBUG
   1.511 +						}					
   1.512 +					}
   1.513 +				break;
   1.514 +			case EWsWinOpAddPriorityKey:
   1.515 +				AddPriorityKeyL(pData.PriorityKey->keycode, pData.PriorityKey->modifierMask, pData.PriorityKey->modifiers);
   1.516 +				break;
   1.517 +			case EWsWinOpRemovePriorityKey:
   1.518 +				RemovePriorityKey(pData.PriorityKey->keycode, pData.PriorityKey->modifierMask, pData.PriorityKey->modifiers);
   1.519 +				break;
   1.520 +			case EWsWinOpSetTextCursor:
   1.521 +				iTextCursor.SetL(*pData.SetTextCursor, EFalse);
   1.522 +				break;
   1.523 +			case EWsWinOpSetTextCursorClipped:
   1.524 +				iTextCursor.SetL(*pData.SetTextCursor, ETrue);
   1.525 +				break;
   1.526 +			case EWsWinOpCancelTextCursor:
   1.527 +				iTextCursor.Cancel();
   1.528 +				break;
   1.529 +			case EWsWinOpSetOwningWindowGroup:
   1.530 +				iOwningWindowGroup=*pData.Int;
   1.531 +				break;
   1.532 +			case EWsWinOpDefaultOwningWindow:
   1.533 +				{
   1.534 +				if(KSecurityPolicy_WriteDeviceData().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::DefaultOwningWindow API")))
   1.535 +					{
   1.536 +					iScreen->SetDefaultOwningWindow(this);
   1.537 +					}
   1.538 +				}
   1.539 +				break;
   1.540 +			case EWsWinOpName:
   1.541 +				iWsOwner->ReplyGroupName(iGroupName,*pData.Int);
   1.542 +				break;
   1.543 +			case EWsWinOpSetName:
   1.544 +				{
   1.545 +				HBufC *newName=NULL;
   1.546 +				const TInt size=*pData.Int;
   1.547 +				if (size>0)
   1.548 +					{
   1.549 +					newName=HBufC::NewLC(size);
   1.550 +					TPtr ptr(newName->Des());
   1.551 +					iWsOwner->RemoteReadL(ptr,0);
   1.552 +					CleanupStack::Pop(newName);
   1.553 +					}
   1.554 +				//Window Group Name is unchanged
   1.555 +				if (iGroupName && newName && *iGroupName == *newName)
   1.556 +					{
   1.557 +					delete newName;
   1.558 +					} 
   1.559 +				else  //Window Group Name is changed
   1.560 +					{  
   1.561 +					delete iGroupName;
   1.562 +					iGroupName=newName;
   1.563 +					TWindowServerEvent::SendGroupChangedEvents();
   1.564 +					}
   1.565 +				}
   1.566 +				break;
   1.567 +			case EWsWinOpIdentifier:
   1.568 +				SetReply(Identifier());
   1.569 +				break;
   1.570 +			case EWsWinOpDisableKeyClick:
   1.571 +				if (*pData.Bool)
   1.572 +					iFlags|=EGroupFlagDisableKeyClick;
   1.573 +				else
   1.574 +					iFlags&=~EGroupFlagDisableKeyClick;
   1.575 +				if (this==CWsTop::FocusWindowGroup())
   1.576 +					UpdateKeyClickState();
   1.577 +				break;
   1.578 +			case EWsWinOpSendPointerEvent:
   1.579 +				if (!TWindowServerEvent::MousePress(*pData.RawEvent,this))
   1.580 +					OwnerPanic(EWservPanicEventType);
   1.581 +				break;
   1.582 +			case EWsWinOpClearChildGroup:
   1.583 +				if(iQueue)
   1.584 +					{				
   1.585 +					TBool fBefore=EFalse; 
   1.586 +					TBool fAfter=EFalse; 
   1.587 +					// If there is nothing to clear, return KErrArgument
   1.588 +					if(iQueue->Last()==this)
   1.589 +						{
   1.590 +						SetReply(KErrArgument);
   1.591 +						break;
   1.592 +						}
   1.593 +					// fBefore is True if there is AT LEAST one window group queued before the current one
   1.594 +					else if(iQueue->First()!=this)
   1.595 +						{
   1.596 +						fBefore=ETrue;
   1.597 +						}
   1.598 +					// fAfter is True if there is MORE THAN one window group queued after the current one
   1.599 +					TDblQueIter<CWsWindowGroup> iter(*iQueue);
   1.600 +					iter.SetToLast();
   1.601 +					if(iter--!=this && iter!=this)
   1.602 +						{
   1.603 +						fAfter=ETrue;
   1.604 +						}
   1.605 +					TDblQue<CWsWindowGroup>* queue=NULL;
   1.606 +					// if fBefore and fAfter are True, create a new queue and copy all window groups after the current one into that queue
   1.607 +					if(fBefore && fAfter)
   1.608 +						{
   1.609 +						TInt ret=KErrNoMemory;
   1.610 +						queue=new TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
   1.611 +						if(queue)
   1.612 +							{
   1.613 +							ret=iChains.Append(queue);	
   1.614 +							if(ret!=KErrNone)
   1.615 +								{
   1.616 +								delete queue;
   1.617 +								queue = NULL;
   1.618 +								}
   1.619 +							}
   1.620 +						// Check that the queue creation and appending worked (we deque all the child groups even if it didn't) 
   1.621 +						if(ret!=KErrNone)
   1.622 +							{
   1.623 +							SetReply(ret);
   1.624 +							}
   1.625 +						}
   1.626 +					// If we've got zero or one window groups after, don't need to queue them
   1.627 +					if(!fAfter || fBefore)
   1.628 +						{
   1.629 +						iter.SetToLast();
   1.630 +						CWsWindowGroup* groupWin;
   1.631 +						while((groupWin=iter--)!=this)
   1.632 +							{
   1.633 +							groupWin->iChainLink.Deque();
   1.634 +							groupWin->iQueue=queue;
   1.635 +							if(queue)
   1.636 +								queue->AddFirst(*groupWin);
   1.637 +							}
   1.638 +						}
   1.639 +					// if we've got no window groups before, don't need to have a queue for this anymore
   1.640 +					if(!fBefore)
   1.641 +						{
   1.642 +						iChainLink.Deque();
   1.643 +						if (!fAfter)
   1.644 +							{
   1.645 +							DeleteQueue(iQueue);
   1.646 +							}
   1.647 +						iQueue=NULL;
   1.648 +						}
   1.649 +					}
   1.650 +				else // if this window group isn't queued, we can't clear any children
   1.651 +					{
   1.652 +					SetReply(KErrArgument);
   1.653 +					}
   1.654 +				break;
   1.655 +			case EWsWinOpSetChildGroup:
   1.656 +				{
   1.657 +				CWsWindowGroup* childWinGroup = CWsWindowGroup::WindowGroupFromIdentifier(*pData.Int);
   1.658 +				if(!childWinGroup																	//(no child to append)
   1.659 +					|| (iQueue && (!iQueue->IsLast(this) || (childWinGroup->iQueue==iQueue)))		//(GpWin has a child) || (GpWin and childGpWin in the same queue)
   1.660 +					|| (childWinGroup->iQueue && !childWinGroup->iQueue->IsFirst(childWinGroup))	//(childGpWin has a parent)
   1.661 +					|| (childWinGroup == this))														//(childGpWin == GpWin)
   1.662 +					{
   1.663 +					SetReply(KErrArgument);
   1.664 +					break;
   1.665 +					}
   1.666 +				if(iQueue)
   1.667 +				// If we have a chain, we're prepending ourselves to the child window group
   1.668 +				// So we take the childs chain and prepend each of the window groups in our own chain
   1.669 +				// beginning with the current window group and working backward
   1.670 +					{
   1.671 +					TDblQueIter<CWsWindowGroup> iter(*iQueue);
   1.672 +					iter.SetToLast();
   1.673 +					CWsWindowGroup* groupWin;
   1.674 +					if(childWinGroup->iQueue)
   1.675 +						{
   1.676 +						TDblQue<CWsWindowGroup>* oldQueue=iQueue;
   1.677 +						while((groupWin=iter--)!=NULL)
   1.678 +							{
   1.679 +							groupWin->iChainLink.Deque();
   1.680 +							childWinGroup->iQueue->AddFirst(*groupWin);
   1.681 +							groupWin->iQueue=childWinGroup->iQueue;
   1.682 +							}
   1.683 +						DeleteQueue(oldQueue);
   1.684 +						}
   1.685 +					else
   1.686 +						{
   1.687 +						iQueue->AddLast(*childWinGroup);
   1.688 +						childWinGroup->iQueue=iQueue;
   1.689 +						}
   1.690 +					}
   1.691 +				else
   1.692 +				// 1. If we don't have a chain, and if the child has a chain, we can simply prepend this wg to the child
   1.693 +				// wg chain
   1.694 +				// 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
   1.695 +				//    as the owning member, and prepend our window group
   1.696 +					{
   1.697 +					if(childWinGroup->iQueue)
   1.698 +						{
   1.699 +						childWinGroup->iQueue->AddFirst(*this);
   1.700 +						iQueue=childWinGroup->iQueue;
   1.701 +						}
   1.702 +					else
   1.703 +						{
   1.704 +						TDblQue<CWsWindowGroup>* queue=new TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
   1.705 +						TInt ret=KErrNoMemory;
   1.706 +						if (queue)
   1.707 +							{
   1.708 +							ret=iChains.Append(queue);
   1.709 +							if(ret!=KErrNone)
   1.710 +								{
   1.711 +								delete queue;
   1.712 +								}
   1.713 +							}
   1.714 +						if(ret!=KErrNone)
   1.715 +							{
   1.716 +							SetReply(ret);
   1.717 +							break;
   1.718 +							}
   1.719 +						queue->AddFirst(*childWinGroup);
   1.720 +						childWinGroup->iQueue=queue;
   1.721 +						queue->AddFirst(*this);
   1.722 +						iQueue=queue;
   1.723 +						}						
   1.724 +					}
   1.725 +				}
   1.726 +				break;
   1.727 +			default:						// All other window commands disallowed
   1.728 +				OwnerPanic(EWservPanicOpcode);
   1.729 +			}
   1.730 +		}
   1.731 +#if defined(_DEBUG)
   1.732 +	rootWindow->CheckTree();
   1.733 +#endif
   1.734 +	}
   1.735 +	
   1.736 +TPoint CWsWindowGroup::Origin() const
   1.737 +	{
   1.738 +	return TPoint(0,0);
   1.739 +	}
   1.740 +	
   1.741 +TRect CWsWindowGroup::AbsRect() const
   1.742 +	{
   1.743 +	return (TRect(RootWindow()->Abs().iTl,RootWindow()->Size()));
   1.744 +	}
   1.745 +
   1.746 +TSize CWsWindowGroup::Size() const
   1.747 +	{
   1.748 +	return RootWindow()->Size();
   1.749 +	}
   1.750 +	
   1.751 +void CWsWindowGroup::UpdateKeyClickState()
   1.752 +	{
   1.753 +	CClick::SetKeyClickOveride(iFlags&EGroupFlagDisableKeyClick);
   1.754 +	}
   1.755 +
   1.756 +void CWsWindowGroup::SetOrdinalPosition(TInt aPos)
   1.757 +	{
   1.758 +	if (aPos==(TInt)KOrdinalPositionSwitchToOwningWindow)
   1.759 +		SwitchToOwningWindow(NULL);
   1.760 +	else
   1.761 +		SetOrdinalPosition(aPos,NULL);
   1.762 +	}
   1.763 +
   1.764 +TBool CWsWindowGroup::SetOrdinalPosition(TInt aPos,CWsWindowGroup* aClosingWindow)
   1.765 +	{
   1.766 +	TBool ret=ETrue;
   1.767 +	if (!iQueue)
   1.768 +		ret=DoSetOrdinalPosition1(aPos,aClosingWindow);
   1.769 +	else
   1.770 +		{
   1.771 +		TDblQueIter<CWsWindowGroup> iter(*iQueue);
   1.772 +		CWsWindowGroup* group;
   1.773 +		iter.SetToLast();
   1.774 +		TInt after=0;
   1.775 +		TInt before=0;
   1.776 +		TInt* inc=&before;
   1.777 +		while ((group=iter--)!=NULL)
   1.778 +			{
   1.779 +			if (group==this)
   1.780 +				inc=&after;
   1.781 +			++(*inc);
   1.782 +			}
   1.783 +		TInt lastWinGpPos=NumWindowGroupsOnMyScreen(OrdinalPriority())-after;
   1.784 +		if (aPos<0)
   1.785 +			aPos=lastWinGpPos;
   1.786 +		else
   1.787 +			aPos=Min(aPos,lastWinGpPos);
   1.788 +		aPos-=before;
   1.789 +		aPos=Max(aPos,0);
   1.790 +		iter.SetToLast();
   1.791 +		CWsWindowGroup* firstForward=iter--;
   1.792 +		while (firstForward && firstForward->OrdinalPosition(EFalse)<aPos)
   1.793 +			{
   1.794 +			firstForward=iter--;
   1.795 +			++aPos;
   1.796 +			}
   1.797 +		if (!firstForward)
   1.798 +			iter.SetToFirst();
   1.799 +		else
   1.800 +			{
   1.801 +			iter.Set(*firstForward);
   1.802 +			MoveChainedWindows(iter,ETrue,aPos,aClosingWindow);
   1.803 +			iter.Set(*firstForward);
   1.804 +			iter++;
   1.805 +			}
   1.806 +		MoveChainedWindows(iter,EFalse,--aPos,aClosingWindow);
   1.807 +#if defined(_DEBUG)
   1.808 +		iter.SetToLast();
   1.809 +		TInt pos1=-1;
   1.810 +		TInt pos2;
   1.811 +		TBool ok=ETrue;
   1.812 +		while ((group=iter--)!=this)
   1.813 +			{
   1.814 +			pos2=group->OrdinalPosition(EFalse);
   1.815 +			if (pos2<=pos1)
   1.816 +				ok=EFalse;
   1.817 +			pos1=pos2;
   1.818 +			}
   1.819 +		WS_ASSERT_DEBUG(ok, EWsPanicGroupWindowChainError);
   1.820 +#endif
   1.821 +		}
   1.822 +
   1.823 +	return ret;
   1.824 +	}
   1.825 +
   1.826 +
   1.827 +void CWsWindowGroup::MoveChainedWindows(TDblQueIter<CWsWindowGroup>& aIter,TBool aForward,TInt aPos,CWsWindowGroup* aClosingWindow)
   1.828 +	{
   1.829 +	CWsWindowGroup* groupWindow;
   1.830 +	while ((groupWindow=(aForward ? aIter-- : aIter++))!=NULL)
   1.831 +		{
   1.832 +		groupWindow->DoSetOrdinalPosition1(aPos,aClosingWindow);
   1.833 +		(aForward ? ++aPos : --aPos);
   1.834 +		}
   1.835 +	}
   1.836 +
   1.837 +TBool CWsWindowGroup::DoSetOrdinalPosition1(TInt aPos,CWsWindowGroup* aClosingWindow)
   1.838 +	{
   1.839 +	TBool ret=EFalse;
   1.840 +	if (CheckOrdinalPositionChange(aPos))
   1.841 +		{
   1.842 +		if (Child())	// A group window with no children can not affect shadows
   1.843 +			{
   1.844 +			ret=ETrue;
   1.845 +			}
   1.846 +		DoSetOrdinalPosition2(aPos,aClosingWindow);
   1.847 +		}
   1.848 +	else
   1.849 +		iScreen->ResetFocus(aClosingWindow);
   1.850 +	return ret;
   1.851 +	}
   1.852 +
   1.853 +void CWsWindowGroup::DoSetOrdinalPosition2(TInt aPos, CWsWindowGroup *aClosingWindow)
   1.854 +	{
   1.855 +	ChangeWindowPosition(aPos,iParent);
   1.856 +	ResetFocus(aClosingWindow);
   1.857 +	}
   1.858 +
   1.859 +void CWsWindowGroup::LostFocus()
   1.860 +	{
   1.861 +	iTextCursor.LostFocus();
   1.862 +	iWsOwner->UpdateWindowOrdinalPrioritys();
   1.863 +	if (iClientHandle!=0)
   1.864 +		QueueEvent(EEventFocusLost);
   1.865 +	TWalkWindowTreeFocusChanged wwt(EFalse);
   1.866 +	WalkWindowTree(wwt,EWalkChildren);
   1.867 +	iWsOwner->SetClientPriority();
   1.868 +	}
   1.869 +
   1.870 +void CWsWindowGroup::ReceivedFocus()
   1.871 +	{
   1.872 +	iWsOwner->UpdateWindowOrdinalPrioritys();
   1.873 +	iTextCursor.ReceivedFocus();
   1.874 +	// Used for event queue testing
   1.875 +	// Calling MoveToFront sets the queue of the focused window to first place, 
   1.876 +	// not doing so puts the queues in unusual situation thus stress testing the queue code. 
   1.877 +	// One such situation is where the focus queue is first but there is a gap before it (iEventPtr>iGlobalEventPtr)" 
   1.878 +#if defined(_DEBUG)
   1.879 +	if (++iSkipCount==5)
   1.880 +		{
   1.881 +		iSkipCount=0;
   1.882 +		}
   1.883 +	else
   1.884 +		{
   1.885 +		WsOwner()->EventQueue()->MoveToFront();
   1.886 +		}
   1.887 +#else
   1.888 +	WsOwner()->EventQueue()->MoveToFront();
   1.889 +#endif
   1.890 +	QueueEvent(EEventFocusGained);
   1.891 +	TWalkWindowTreeFocusChanged wwt(ETrue);
   1.892 +	WalkWindowTree(wwt,EWalkChildren);
   1.893 +	iWsOwner->SetClientPriority();
   1.894 +	UpdateKeyClickState();
   1.895 +	}
   1.896 +
   1.897 +TInt CWsWindowGroup::NumWindowGroups(TBool aAllPriorities, TInt aPriority)
   1.898 +	{
   1.899 +	TInt count=0;
   1.900 +	TInt screenNo;
   1.901 +	for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
   1.902 +		{
   1.903 +		count+=CWsWindowGroup::NumWindowGroupsOnScreen(CWsTop::Screen(screenNo)->RootWindow()->Child(),aAllPriorities,aPriority);
   1.904 +		}
   1.905 +	return(count);
   1.906 +	}
   1.907 +
   1.908 +TInt CWsWindowGroup::NumWindowGroupsOnScreen(const CWsWindowGroup* aGroupWin,TBool aAllPriorities,TInt aPriority)
   1.909 +	{
   1.910 +	TInt count=0;
   1.911 +	while (aGroupWin)
   1.912 +		{
   1.913 +		if (aAllPriorities || aGroupWin->iOrdinalPriority==aPriority)
   1.914 +			++count;
   1.915 +		aGroupWin=aGroupWin->NextSibling();
   1.916 +		}
   1.917 +	return count;
   1.918 +	}
   1.919 +
   1.920 +inline TInt CWsWindowGroup::NumWindowGroupsOnMyScreen(TInt aPriority)
   1.921 +	{
   1.922 +	return(CWsWindowGroup::NumWindowGroupsOnScreen(Parent()->Child(),EFalse,aPriority));
   1.923 +	}
   1.924 +
   1.925 +void CWsWindowGroup::GetFocusWindowGroupL(TInt aScreenNumber)
   1.926 +	{
   1.927 +	CWsWindowGroup *groupWin=(aScreenNumber==KDummyScreenNumber)?CWsTop::FocusWindowGroup():CWsTop::Screen(aScreenNumber)->FocusWindowGroup();	
   1.928 +	if (!groupWin)
   1.929 +		User::Leave(KErrGeneral);
   1.930 +	CWsClient::SetReply(groupWin->Identifier());
   1.931 +	}
   1.932 +
   1.933 +TInt CWsWindowGroup::GetWindowGroupListL(TInt aScreenNo,TBool aAllPriorities,TInt aPriority,TInt aCount,CArrayFixFlat<TInt>* aList)
   1.934 +	{
   1.935 +	TInt count=aList->Count();
   1.936 +	CWsWindowGroup* groupWin=CWsTop::Screen(aScreenNo)->RootWindow()->Child();
   1.937 +	while(!aAllPriorities && groupWin && groupWin->iOrdinalPriority!=aPriority)
   1.938 +		groupWin=groupWin->NextSibling();
   1.939 +	while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==aPriority) && count<aCount)
   1.940 +		{
   1.941 +		aList->AppendL(groupWin->Identifier());
   1.942 +		++count;
   1.943 +		groupWin=groupWin->NextSibling();
   1.944 +		}
   1.945 +	return count;
   1.946 +	}
   1.947 +	
   1.948 +TInt CWsWindowGroup::SendWindowGroupListL(TInt aScreenNumber, TBool aAllPriorities, TInt aPriority, TInt aCount)
   1.949 +	{
   1.950 +	if ((aCount<1) || (aCount>(KArrayMaxGranularity/sizeof(TInt))))
   1.951 +		User::Leave(KErrArgument);
   1.952 +	CArrayFixFlat<TInt>* list=new(ELeave) CArrayFixFlat<TInt>(aCount);
   1.953 +	CleanupStack::PushL(list);
   1.954 +	TInt count(0);	
   1.955 +	TInt requestedScreen=aScreenNumber;	
   1.956 +	
   1.957 +	if(requestedScreen==KDummyScreenNumber)
   1.958 +		{		
   1.959 +		// get list from current focus screen first
   1.960 +		TInt focusScreenNo=CWsTop::CurrentFocusScreen()->ScreenNumber();
   1.961 +		count=GetWindowGroupListL(focusScreenNo, aAllPriorities, aPriority, aCount, list);
   1.962 +		if(count<aCount)
   1.963 +			{
   1.964 +			// now get from the remaining screen
   1.965 +			TInt screenNo;
   1.966 +			for(screenNo=0;screenNo<CWsTop::NumberOfScreens() && count<aCount;++screenNo)
   1.967 +				{
   1.968 +				// skip focus screen
   1.969 +				if (screenNo==focusScreenNo)
   1.970 +					continue;
   1.971 +				// count hold total number of window groups collected so far
   1.972 +				count=GetWindowGroupListL(screenNo, aAllPriorities, aPriority, aCount, list);
   1.973 +				}			
   1.974 +			}
   1.975 +		}
   1.976 +	else
   1.977 +		{
   1.978 +		count=GetWindowGroupListL(requestedScreen, aAllPriorities, aPriority, aCount, list);	
   1.979 +		}
   1.980 +	
   1.981 +	if (list->Count() > 0)	
   1.982 +		CWsClient::ReplyBuf(&list->At(0),count*sizeof(TInt));
   1.983 +	CleanupStack::PopAndDestroy(list);
   1.984 +	return(count);	// How many actually returned, may be less than asked for, but not more
   1.985 +	}
   1.986 +
   1.987 +void CWsWindowGroup::GetWindowGroupListAndChainL(TInt aScreen,TBool aAllPriorities,TInt aPriority
   1.988 +																,RArray<RWsSession::TWindowGroupChainInfo>& list,TInt& aCountLeft)
   1.989 +	{
   1.990 +	CWsWindowGroup *groupWin=CWsTop::Screen(aScreen)->RootWindow()->Child();
   1.991 +	while(!aAllPriorities && groupWin && groupWin->iOrdinalPriority!=aPriority)
   1.992 +		groupWin=groupWin->NextSibling();
   1.993 +	while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==aPriority) && aCountLeft>0)
   1.994 +		{
   1.995 +		RWsSession::TWindowGroupChainInfo windowId;
   1.996 +		windowId.iId=groupWin->Identifier();
   1.997 +		if(!groupWin->IsChained(windowId.iParentId))
   1.998 +			windowId.iParentId=-1;	//Unchained window group
   1.999 +		list.AppendL(windowId);
  1.1000 +		--aCountLeft;
  1.1001 +		groupWin=groupWin->NextSibling();
  1.1002 +		}
  1.1003 +	}
  1.1004 +
  1.1005 +TInt CWsWindowGroup::SendWindowGroupListAndChainL(TBool aAllPriorities, TInt aPriority, TInt aCount)
  1.1006 +	{
  1.1007 +	if ((aCount<1) || (aCount>(KArrayMaxGranularity/sizeof(RWsSession::TWindowGroupChainInfo))))
  1.1008 +		User::Leave(KErrArgument);
  1.1009 +	RArray<RWsSession::TWindowGroupChainInfo> list(aCount);
  1.1010 +	CleanupClosePushL(list);
  1.1011 +	TInt count=aCount;
  1.1012 +	TInt focusScreenNo=CWsTop::CurrentFocusScreen()->ScreenNumber();
  1.1013 +	GetWindowGroupListAndChainL(focusScreenNo,aAllPriorities,aPriority,list,count);
  1.1014 +	TInt screenNo;
  1.1015 +	for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
  1.1016 +		{
  1.1017 +		if (screenNo!=focusScreenNo)
  1.1018 +			GetWindowGroupListAndChainL(screenNo,aAllPriorities,aPriority,list,count);
  1.1019 +		}
  1.1020 +	if (list.Count() > 0)
  1.1021 +		CWsClient::ReplyBuf(&list[0],aCount*sizeof(RWsSession::TWindowGroupChainInfo));
  1.1022 +	CleanupStack::PopAndDestroy(&list);
  1.1023 +	return(aCount-count);	// How many actually returned, may be less than asked for, but not more
  1.1024 +	}
  1.1025 +
  1.1026 +TBool CWsWindowGroup::SendEventToAllGroups(TBool aAllPriorities,TBool aOnePerClient,const TWsClCmdSendEventToWindowGroup& aData)
  1.1027 +	{
  1.1028 +	TWsEvent event=aData.event;
  1.1029 +	if (event.Type()==EEventKey && event.Key()->iRepeats!=0)
  1.1030 +		CKeyboardRepeat::CancelRepeat(NULL);		//Otherwise we will trip an invarient
  1.1031 +	TInt priority=aData.parameter;
  1.1032 +	TBool sentToAll=ETrue;
  1.1033 +	TInt screenNo;
  1.1034 +	for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
  1.1035 +		{
  1.1036 +		CWsWindowGroup *groupWin=CWsTop::Screen(screenNo)->RootWindow()->Child();
  1.1037 +		if (!aAllPriorities)
  1.1038 +			{
  1.1039 +			while(groupWin && groupWin->iOrdinalPriority!=priority)
  1.1040 +				groupWin=groupWin->NextSibling();
  1.1041 +			}
  1.1042 +		CWsWindowGroup* firstGroupWin=groupWin;
  1.1043 +		CWsClient* lastOwner=NULL;
  1.1044 +		CWsWindowGroup* groupWin2;
  1.1045 +		while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==priority))
  1.1046 +			{
  1.1047 +			if (aOnePerClient)
  1.1048 +				{
  1.1049 +				if (lastOwner==groupWin->iWsOwner)
  1.1050 +					goto ContinueLoop;
  1.1051 +				lastOwner=groupWin->iWsOwner;
  1.1052 +				for(groupWin2=firstGroupWin;groupWin2!=groupWin;groupWin2=groupWin2->NextSibling())
  1.1053 +					{
  1.1054 +					if (groupWin2->iWsOwner==groupWin->iWsOwner)
  1.1055 +						break;
  1.1056 +					}
  1.1057 +				if (groupWin2->iWsOwner==groupWin->iWsOwner && groupWin2!=groupWin)
  1.1058 +					goto ContinueLoop;
  1.1059 +				}
  1.1060 +			event.SetHandle(groupWin->ClientHandle());
  1.1061 +			if (!groupWin->EventQueue()->QueueEvent(event))
  1.1062 +				sentToAll=EFalse;
  1.1063 +		ContinueLoop:
  1.1064 +			groupWin=groupWin->NextSibling();
  1.1065 +			}
  1.1066 +		}
  1.1067 +	return sentToAll;
  1.1068 +	}
  1.1069 +
  1.1070 +void CWsWindowGroup::SendMessageToAllGroupsL(CWsClient& aSender,TBool aAllPriorities,const TWsClCmdSendMessageToWindowGroup& aData)
  1.1071 +	{
  1.1072 +	TInt screenNo;
  1.1073 +	for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
  1.1074 +		{
  1.1075 +		CWsWindowGroup* groupWin=CWsTop::Screen(screenNo)->RootWindow()->Child();		
  1.1076 +		if (!aAllPriorities)
  1.1077 +			{
  1.1078 +			while(groupWin && groupWin->iOrdinalPriority!=aData.identifierOrPriority)
  1.1079 +				groupWin=groupWin->NextSibling();
  1.1080 +			}
  1.1081 +		while(groupWin && (aAllPriorities || (groupWin->iOrdinalPriority==aData.identifierOrPriority)))
  1.1082 +			{
  1.1083 +			groupWin->QueueMessageL(aData.uid, aData.dataLength, aSender);
  1.1084 +			groupWin=groupWin->NextSibling();
  1.1085 +			}
  1.1086 +		}
  1.1087 +	}
  1.1088 +
  1.1089 +CWsWindowGroup *CWsWindowGroup::WindowGroupFromIdentifier(TInt aIdentifier)
  1.1090 +	{
  1.1091 +	// apply to all screens
  1.1092 +	TInt screenNo;
  1.1093 +	for (screenNo=0; screenNo<CWsTop::NumberOfScreens(); ++screenNo)
  1.1094 +		{
  1.1095 +		CWsWindowGroup* group;
  1.1096 +		for(group=CWsTop::Screen(screenNo)->RootWindow()->Child(); group; group=group->NextSibling())
  1.1097 +			{
  1.1098 +			if (group->Identifier() == aIdentifier)
  1.1099 +				return group;
  1.1100 +			}
  1.1101 +			
  1.1102 +		}
  1.1103 +		
  1.1104 +	return NULL;
  1.1105 +	}
  1.1106 +
  1.1107 +CWsWindowGroup *CWsWindowGroup::WindowGroupFromIdentifierL(TInt aIdentifier)
  1.1108 +	{
  1.1109 +	CWsWindowGroup *group=WindowGroupFromIdentifier(aIdentifier);
  1.1110 +	if (!group)
  1.1111 +		User::Leave(KErrNotFound);
  1.1112 +	return(group);
  1.1113 +	}
  1.1114 +
  1.1115 +CWsWindowGroup *CWsWindowGroup::FindWindowGroupL(CWsClient* aClient, TInt aIdentifier,TInt aOffset,const TPtrC *aMatch,const TThreadId *aThreadId)
  1.1116 +	{
  1.1117 +	CWsWindowGroup *group;
  1.1118 +	if (aIdentifier)
  1.1119 +		{
  1.1120 +		group=WindowGroupFromIdentifier(aIdentifier);
  1.1121 +		if (group)	// NULL group will cause KErrNotFound to be returned
  1.1122 +			group=group->NextSibling();
  1.1123 +		}
  1.1124 +	else
  1.1125 +		{
  1.1126 +		// get window group for this session
  1.1127 +		//
  1.1128 +		group = aClient->Screen()->RootWindow()->Child();
  1.1129 +		}
  1.1130 +
  1.1131 +	for(;group;group=group->NextSibling())
  1.1132 +		{
  1.1133 +		if (aThreadId)
  1.1134 +			{
  1.1135 +			if (group->WsOwner()->Client().Id()==*aThreadId)
  1.1136 +				break;	// Found one
  1.1137 +			}
  1.1138 +		else
  1.1139 +			{
  1.1140 +			const TDesC *groupName=&nullDescriptor;
  1.1141 +			if (group->GroupName())
  1.1142 +				groupName=group->GroupName();
  1.1143 +			if (groupName->Length()>=aOffset && groupName->Mid(aOffset).MatchF(*aMatch)>=0)
  1.1144 +				break;	// Found one
  1.1145 +			}
  1.1146 +		}
  1.1147 +	if (!group)
  1.1148 +		User::Leave(KErrNotFound);
  1.1149 +	return(group);
  1.1150 +	}
  1.1151 +
  1.1152 +void CWsWindowGroup::AddPriorityKeyL(TUint aKeycode, TUint aModifierMask, TUint aModifiers)
  1.1153 +	{
  1.1154 +	iPriorityKeys=new(ELeave) TPriorityKey(aKeycode,aModifierMask,aModifiers,iPriorityKeys);
  1.1155 +	}
  1.1156 +
  1.1157 +void CWsWindowGroup::RemovePriorityKey(TUint aKeycode, TUint aModifierMask, TUint aModifiers)
  1.1158 +	{
  1.1159 +	for(TPriorityKey **ppk=&iPriorityKeys;*ppk;ppk=&((*ppk)->iNext))
  1.1160 +		if ((*ppk)->Equals(aKeycode, aModifierMask, aModifiers))
  1.1161 +			{
  1.1162 +			TPriorityKey *next=(*ppk)->iNext;
  1.1163 +			delete *ppk;
  1.1164 +			*ppk=next;
  1.1165 +			break;
  1.1166 +			}
  1.1167 +	}
  1.1168 +
  1.1169 +void CWsWindowGroup::RemoveAllPriorityKeys()
  1.1170 +	{
  1.1171 +	TPriorityKey *pk=iPriorityKeys;
  1.1172 +	while(pk)
  1.1173 +		{
  1.1174 +		TPriorityKey *next=pk->iNext;
  1.1175 +		delete pk;
  1.1176 +		pk=next;
  1.1177 +		}
  1.1178 +	}
  1.1179 +
  1.1180 +TBool CWsWindowGroup::CheckForPriorityKey(const TKeyData &aKey, TInt aScanCode)
  1.1181 +	{
  1.1182 +	for(TPriorityKey *pk=iPriorityKeys;pk;pk=pk->iNext)
  1.1183 +		{
  1.1184 +		if (pk->KeyMatches(aKey))
  1.1185 +			{	
  1.1186 +			WsOwner()->PriorityKeyPressed(ClientHandle(),aKey, aScanCode);
  1.1187 +			return(ETrue);
  1.1188 +			}
  1.1189 +		}
  1.1190 +	return(EFalse);
  1.1191 +	}
  1.1192 +
  1.1193 +void CWsWindowGroup::StatusDump(TDes &aBuf)
  1.1194 +	{
  1.1195 +	_LIT(KWSERVStatusDumpWindowGroupInfo,"CWsWindowGroup[0x%x]RWindowGroup[0x%x,%d],Pri=%d,Id=%d,SizeMode=%d");
  1.1196 +	aBuf.AppendFormat(KWSERVStatusDumpWindowGroupInfo,this,iClientHandle,LogHandle(),iOrdinalPriority,iIdentifier,iScreenDevice?iScreenDevice->AppMode():0);
  1.1197 +	}
  1.1198 +
  1.1199 +void CWsWindowGroup::SignalMessageReady()
  1.1200 +	{
  1.1201 +	TWsEvent event;
  1.1202 +	event.SetType(EEventMessageReady);
  1.1203 +	event.SetHandle(ClientHandle());
  1.1204 +	event.SetTimeNow();
  1.1205 +	SEventMessageReady& eventMessageReady=*(SEventMessageReady*)event.EventData();
  1.1206 +	eventMessageReady.iWindowGroupIdentifier=Identifier();
  1.1207 +	eventMessageReady.iMessageUid=(*iMessageArray)[0].iUid;
  1.1208 +	eventMessageReady.iMessageParametersSize=iMessageArray->Length(0)-sizeof(TUid);
  1.1209 +	if(WsOwner()->EventQueue()->QueueEvent(event,EEventPriorityHigh))
  1.1210 +		{
  1.1211 +		iFlags|=EGroupFlagMessageSignalled;
  1.1212 +		}
  1.1213 +	}
  1.1214 +
  1.1215 +void CWsWindowGroup::QueueMessageL(TUid aUid, TInt aDataLength, CWsClient& aSender)
  1.1216 +	{
  1.1217 +	WS_ASSERT_DEBUG(iFlags&(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew) || iMessageArray->Count()>=1,EWsPanicMsgQueueError);
  1.1218 +	if (!(iFlags&(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew)) && iMessageArray->Count()>=KMaxNumberOfMsgsInInactiveQueue)
  1.1219 +		{
  1.1220 +		WS_ASSERT_DEBUG(iMessageArray->Count()<=KMaxNumberOfMsgsInInactiveQueue,EWsPanicMsgQueueError);
  1.1221 +		iMessageArray->Delete(1,iMessageArray->Count()-1);
  1.1222 +		}
  1.1223 +	TWsMessage* message=NULL;
  1.1224 +	TRAPD(err,message=&iMessageArray->ExtendL(aDataLength+sizeof(aUid)));
  1.1225 +	if ((err || (iFlags&EGroupFlagMsgQueueNew)) && iMessageArray->Count()>KMaxNumberOfMsgsInQueue)
  1.1226 +		{
  1.1227 +		iFlags&=~(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew);
  1.1228 +		iMessageArray->Delete(1,iMessageArray->Count()-(err?1:2));
  1.1229 +		iMessageArray->Compress();
  1.1230 +		}
  1.1231 +	User::LeaveIfError(err);
  1.1232 +	if (message)
  1.1233 +		{
  1.1234 +		message->iUid=aUid;
  1.1235 +		TPtr8 ptr(&message->iTheRest[0],aDataLength);
  1.1236 +		TRAP(err,aSender.RemoteReadL(ptr,0));
  1.1237 +		if (err)
  1.1238 +			{
  1.1239 +			iMessageArray->Delete(iMessageArray->Count()-1);
  1.1240 +			User::Leave(err);
  1.1241 +			}
  1.1242 +		if (!(iFlags&EGroupFlagMessageSignalled))
  1.1243 +			{
  1.1244 +			WS_ASSERT_DEBUG(iMessageArray->Count()==1,EWsPanicMsgQueueError);
  1.1245 +			SignalMessageReady();
  1.1246 +			}
  1.1247 +		}
  1.1248 +	}
  1.1249 +
  1.1250 +void CWsWindowGroup::FetchMessageL()
  1.1251 +	{
  1.1252 +	if (!(iFlags&EGroupFlagMessageSignalled))
  1.1253 +		{
  1.1254 +		OwnerPanic(EWservPanicFetchMessage);
  1.1255 +		}
  1.1256 +	CWsClient::ReplyBuf(&((*iMessageArray)[0].iTheRest[0]),(TInt)iMessageArray->Length(0)-sizeof(TUid));
  1.1257 +	iMessageArray->Delete(0);
  1.1258 +	iFlags|=EGroupFlagMsgQueueActive;
  1.1259 +	iFlags&=~(EGroupFlagMessageSignalled|EGroupFlagMsgQueueNew);
  1.1260 +	if (iMessageArray->Count()>0)
  1.1261 +		{
  1.1262 +		SignalMessageReady();
  1.1263 +		}
  1.1264 +	}
  1.1265 +
  1.1266 +TBool CWsWindowGroup::ScreenDeviceValid() const
  1.1267 +	{
  1.1268 +	return(iScreenDevice?iScreenDevice->ScreenDeviceValidState():(iScreen->ScreenSizeMode()==0));
  1.1269 +	}
  1.1270 +
  1.1271 +TBool CWsWindowGroup::CanReceiveFocus() const
  1.1272 +	{
  1.1273 +	return(ReceivesFocus() && iWsOwner->NotClosing() && (ScreenDeviceValid() || iFlags&EGroupFlagHandlesDeviceChange));
  1.1274 +	}
  1.1275 +
  1.1276 +void CWsWindowGroup::SetScreenChangeEventStateL(TBool aEnabled)
  1.1277 +	{
  1.1278 +	iFlags&=~EGroupFlagHandlesDeviceChange;
  1.1279 +	if (aEnabled)
  1.1280 +		{
  1.1281 +		iFlags|=EGroupFlagHandlesDeviceChange;
  1.1282 +		TWindowServerEvent::AddToScreenDeviceChangeEventListL(*this);
  1.1283 +		if (iScreen->ScreenSizeMode()!=0)
  1.1284 +			TWindowServerEvent::SendScreenDeviceChangedEvent(this);
  1.1285 +		}
  1.1286 +	else
  1.1287 +		TWindowServerEvent::RemoveFromScreenDeviceChangeEventList(*this);
  1.1288 +	iScreen->ResetFocus(NULL);
  1.1289 +	}
  1.1290 +
  1.1291 +void CWsWindowGroup::SetScreenDeviceValidState(const DWsScreenDevice *aDevice)
  1.1292 +	{
  1.1293 +	if (iScreenDevice==aDevice)
  1.1294 +		{
  1.1295 +		TBool state=ScreenDeviceValid();
  1.1296 +		for(CWsClientWindow *win=Child();win;win=win->NextSibling())
  1.1297 +			{
  1.1298 +			win->SetScreenDeviceValidState(state);
  1.1299 +			}
  1.1300 +		}
  1.1301 +	}
  1.1302 +
  1.1303 +void CWsWindowGroup::SetScreenDeviceValidStates(const DWsScreenDevice *aDevice)
  1.1304 +	{
  1.1305 +	for(CWsWindowGroup *groupWin=aDevice->RootWindow()->Child();groupWin;groupWin=groupWin->NextSibling())
  1.1306 +		groupWin->SetScreenDeviceValidState(aDevice);
  1.1307 +	}
  1.1308 +
  1.1309 +TBool CWsWindowGroup::SetScreenDeviceValidStates(const TBool aScreenSizeChanged,const TBool aSwapWidthAndHeight, CScreen* aScreen)
  1.1310 +	{
  1.1311 +	TBool ret=EFalse;
  1.1312 +	CWsRootWindow* rootWindow = aScreen->RootWindow();
  1.1313 +
  1.1314 +	CWsWindowGroup* groupWin;
  1.1315 +	CWsClientWindow* win;
  1.1316 +	for(groupWin=rootWindow->Child();groupWin;groupWin=groupWin->NextSibling())
  1.1317 +		{
  1.1318 +		TBool state=groupWin->ScreenDeviceValid();
  1.1319 +		for(win=groupWin->Child();win;win=win->NextSibling())
  1.1320 +			{
  1.1321 +			win->SetScreenDeviceValidStateFlag(state);
  1.1322 +			win->ResetHiddenFlagsInParentAndChildren();
  1.1323 +			}
  1.1324 +		}
  1.1325 +	if (aScreenSizeChanged)
  1.1326 +		{
  1.1327 +		rootWindow->ScreenSizeChanged(aSwapWidthAndHeight);
  1.1328 +		}
  1.1329 +
  1.1330 +	aScreen->AddRedrawRegion(rootWindow->WindowArea());
  1.1331 +
  1.1332 +	return ret;
  1.1333 +	}
  1.1334 +
  1.1335 +void CWsWindowGroup::SetScreenDevice(DWsScreenDevice *aDevice)
  1.1336 +	{
  1.1337 +	iScreenDevice=aDevice;	
  1.1338 +	}
  1.1339 +
  1.1340 +void CWsWindowGroup::NewOrientation(TInt aMode,CFbsBitGc::TGraphicsOrientation aRotation, CWsRootWindow* aRootWindow)
  1.1341 +	{
  1.1342 +	for(CWsWindowGroup *groupWin=aRootWindow->Child();groupWin;groupWin=groupWin->NextSibling())
  1.1343 +		{
  1.1344 +		DWsScreenDevice *device=groupWin->Device();
  1.1345 +		if (device)
  1.1346 +			device->NewOrientation(aMode,aRotation);
  1.1347 +		}
  1.1348 +	}
  1.1349 +
  1.1350 +void CWsWindowGroup::ResetFocus(CWsWindowGroup *aClosingWindow)
  1.1351 +	{
  1.1352 +	if (iScreen)
  1.1353 +		{
  1.1354 +		iScreen->ResetFocus(aClosingWindow);
  1.1355 +		}
  1.1356 +	}
  1.1357 +
  1.1358 +TBool CWsWindowGroup::IsChained(TInt& aParentId)
  1.1359 +	{
  1.1360 +	if (!iQueue)
  1.1361 +		return EFalse;
  1.1362 +	if (iQueue->First()==this)
  1.1363 +		aParentId=0;
  1.1364 +	else
  1.1365 +		aParentId=BeforeInChain()->Identifier();
  1.1366 +	return ETrue;
  1.1367 +	}
  1.1368 +
  1.1369 +inline CWsWindowGroup* CWsWindowGroup::BeforeInChain()
  1.1370 +	{		//You should only call this function if you know the window has a parent
  1.1371 +	return reinterpret_cast<CWsWindowGroup*>(PtrSub(iChainLink.iPrev,_FOFF(CWsWindowGroup,iChainLink)));
  1.1372 +	}
  1.1373 +
  1.1374 +TBool CWsWindowGroup::CheckCapability(TInt& aOrdinalPriority)
  1.1375 +	{
  1.1376 +	if(aOrdinalPriority>=KPasswordWindowGroupPriority)
  1.1377 +		{
  1.1378 +		if(!KSecurityPolicy_SwEvent().CheckPolicy(WsOwner()->Client(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed")))
  1.1379 +			{
  1.1380 +			aOrdinalPriority=KPasswordWindowGroupPriority-1;
  1.1381 +			return EFalse;
  1.1382 +			}
  1.1383 +		}
  1.1384 + 	return ETrue;
  1.1385 +	}
  1.1386 +	
  1.1387 +TBool CWsWindowGroup::HasVisibleTranslucentChild()
  1.1388 +	{
  1.1389 +	CWsWindowBase * child = iChild;
  1.1390 +	while (child)
  1.1391 +		{
  1.1392 +		if (child->WinType() == EWinTypeClient)
  1.1393 +			{
  1.1394 +			CWsClientWindow * cliwin = static_cast<CWsClientWindow *>(child);
  1.1395 +			if (cliwin->IsTranslucent() && cliwin->IsVisible())
  1.1396 +				return ETrue;
  1.1397 +			}
  1.1398 +		else if (static_cast<CWsWindowGroup*>(child)->HasVisibleTranslucentChild())
  1.1399 +			{
  1.1400 +			return ETrue;
  1.1401 +			}
  1.1402 +		child = child->NextSibling();
  1.1403 +		}
  1.1404 +	return EFalse;
  1.1405 +	}
  1.1406 +
  1.1407 +TInt CWsWindowGroup::NumClientWindowGroups()
  1.1408 +	{
  1.1409 +	CWsObjectIx& objix=*WsOwner()->ObjectIndex();
  1.1410 +	const TWsObject* ptr=objix.FirstObject();
  1.1411 +	const TWsObject* end=ptr+objix.Length();
  1.1412 +	TInt count=0;
  1.1413 +	while(++ptr<end)		//First one should always have a NULL object
  1.1414 +		{
  1.1415 +		const CWsObject* obj=ptr->iObject;
  1.1416 +		if (obj && obj->Type()==WS_HANDLE_GROUP_WINDOW)
  1.1417 +			++count;
  1.1418 +		}
  1.1419 +	return count;
  1.1420 +	}
  1.1421 +