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