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