Applied patch 1, to provide a syborg specific minigui oby file.
Need to compare this with the "stripped" version currently in the tree.
This supplied version applies for Nokia builds, but need to repeat the
test for SF builds to see if pruning is needed, or if the file needs to
be device-specific.
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of "Eclipse Public License v1.0"
// which accompanies this distribution, and is available
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
//
// Initial Contributors:
// Nokia Corporation - initial contribution.
//
// Contributors:
//
// Description:
// Group window sub-class of CWsWindow
//
//
#include <e32std.h>
#include "W32STD.H"
#include "W32CLICK.H"
#include "server.h"
#include "rootwin.h"
#include "windowgroup.h"
#include "walkwindowtree.h"
#include "wstop.h"
#include "EVENT.H"
#include "KEYCLICK.H"
#include "PRIKEY.H"
#include "panics.h"
GLREF_D TPtr nullDescriptor;
GLREF_D CDebugLogBase* wsDebugLog;
#if defined(_DEBUG)
TInt CWsWindowGroup::iSkipCount=0;
#endif
TInt CWsWindowGroup::iIdentifierCount=1;
TBool CWsWindowGroup::iFocusGainPreProcess=EFalse; //'REMOVEFADINGONFOCUSGAIN' flag in INI file
RPointerArray< TDblQue<CWsWindowGroup> > CWsWindowGroup::iChains(3);
static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_SwEvent,ECapabilitySwEvent);
static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_WriteDeviceData,ECapabilityWriteDeviceData);
const TInt KArrayMaxGranularity=0x10000000;
CWsWindowGroup* CWsWindowGroup::NewL(CWsClient* aOwner, CScreen* aScreen,
const TWsClCmdCreateWindowGroup& aCmd)
{
CWsWindowGroup* self = new(ELeave) CWsWindowGroup(aOwner, aScreen);
CleanupStack::PushL(self);
self->ConstructL(aCmd);
CleanupStack::Pop(self);
return self;
}
CWsWindowGroup::CWsWindowGroup(CWsClient* aOwner, CScreen* aScreen) : CWsWindowBase(aOwner,WS_HANDLE_GROUP_WINDOW,aScreen)
{
__DECLARE_NAME(_S("CWsWindowGroup"));
iWinType=EWinTypeGroup;
}
void CWsWindowGroup::PurgeCapturedKeys()
{
CWsObjectIx& objix=*WsOwner()->ObjectIndex();
const TWsObject* ptr=objix.FirstObject();
const TWsObject* end=ptr+objix.Length();
while(++ptr<end) //Fisrt one should always have a NULL object
{
const CWsObject* obj=ptr->iObject;
if (obj
&& ((obj->Type()==WS_HANDLE_CAPTURE_KEY && STATIC_CAST(const CWsCaptureKey*,obj)->WindowGroup()==this)
|| (obj->Type()==WS_HANDLE_CAPTURE_KEY_UPDOWNS && STATIC_CAST(const CWsCaptureKeyUpsAndDowns*,obj)->WindowGroup()==this)
|| (obj->Type()==WS_HANDLE_CAPTURE_LONG_KEY && STATIC_CAST(const CWsCaptureLongKey*,obj)->WindowGroup()==this)))
{
objix.Remove(ptr);
delete obj;
}
}
objix.Tidy();
CKeyboardRepeat::CancelRepeat(this);
}
void CWsWindowGroup::SwitchToOwningWindow(CWsWindowGroup *aClosingWindow)
{
if (this==CWsTop::FocusWindowGroup())
{
CWsWindowGroup *winGroup=NULL;
//
// First try for an 'owning' window
//
if (iOwningWindowGroup)
{
for(winGroup=RootWindow()->Child();winGroup;winGroup=winGroup->NextSibling())
if (winGroup->Identifier()==iOwningWindowGroup && winGroup->iOrdinalPriority==iOrdinalPriority)
goto gotIt;
}
//
// If that failed look for the frontmost window belonging to the owner of dying window
//
for(winGroup=RootWindow()->Child();winGroup;winGroup=winGroup->NextSibling())
if (winGroup!=this && winGroup->WsOwner()==WsOwner() && winGroup->iOrdinalPriority==iOrdinalPriority)
goto gotIt;
//
// Next try for the nominated default owning window group
//
winGroup=iScreen->DefaultOwningWindowGroup();
if (winGroup && winGroup->iOrdinalPriority==iOrdinalPriority)
{
gotIt: winGroup->SetOrdinalPosition(0,this);
return;
}
}
ResetFocus(aClosingWindow);
}
CWsWindowGroup::~CWsWindowGroup()
{
if (wsDebugLog)
{
TLogMessageText buf;
_LIT(KWSERVDebugLogGroupWindowId,"Destroying: RWindowGroup[0x%x,%d],Id=%d");
buf.Format(KWSERVDebugLogGroupWindowId,iClientHandle,LogHandle(),iIdentifier);
wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, buf);
}
if (CClick::IsHandler())
{
CClick::OtherEvent(EEventGroupWindowClose,reinterpret_cast<TAny*>(iIdentifier));
}
if (iQueue)
{
if (iQueue->Last()!=this)
{ //Unlink all the children of the window that is being deleted
TDblQueIter<CWsWindowGroup> iter(*iQueue);
CWsWindowGroup* groupWin;
iter.SetToLast();
while ((groupWin=iter--)!=this)
{
WS_ASSERT_DEBUG(groupWin!=NULL && groupWin->iQueue==iQueue,EWsPanicGroupWindowChainError);
groupWin->iChainLink.Deque();
groupWin->iQueue=NULL;
}
}
WS_ASSERT_DEBUG(iQueue->Last()==this,EWsPanicGroupWindowChainError);
TDblQueLinkBase* parentLink=iChainLink.iPrev;
iChainLink.Deque();
if (parentLink->iNext==parentLink->iPrev) //Check to see chain no longer required
{
if (!iQueue->IsEmpty())
{ //Only the parent is left in queue
CWsWindowGroup* parent=iQueue->First();
static_cast<TDblQueLink*>(parentLink)->Deque();
WS_ASSERT_DEBUG(parent->iQueue==iQueue,EWsPanicGroupWindowChainError);
parent->iQueue=NULL;
}
DeleteQueue(iQueue);
}
iQueue=NULL;
}
RemoveAllPriorityKeys();
PurgeCapturedKeys();
iTextCursor.Close();
SetPointerCursor(NULL);
for(CWsClientWindow *win=Child();win;win=win->NextSibling())
win->SetInactive();
if (iScreen)
{
iScreen->RemoveFromDefaultOwningList(this);
}
CWsWindowBase::Shutdown();
TWindowServerEvent::SendGroupChangedEvents();
iClientHandle=0; // To block focus lost events being sent
// Decide which window to give focus to if WServ isn't shutting down
if (iScreen && !CWsTop::ShuttingDown())
SwitchToOwningWindow(this);
delete iGroupName;
delete iMessageArray;
}
void CWsWindowGroup::DeleteQueue(TDblQue<CWsWindowGroup>* aQueue)
{
iChains.Remove(iChains.Find(aQueue));
delete aQueue;
if (iChains.Count()==0)
{
iChains.Compress();
}
}
void CWsWindowGroup::AdvanceIdentifierCount()
{
if (++iIdentifierCount>EMaxIdentifierCount)
iIdentifierCount=1; // so limit it to low value
}
void CWsWindowGroup::ConstructL(const TWsClCmdCreateWindowGroup &aCmd)
{
#if defined(_DEBUG)
if (IsClientHandleInUse(aCmd.clientHandle))
{
OwnerPanic(EWservPanicDuplicateHandle);
}
#endif
NewObjL();
iFlags=EGroupFlagAutoForeground|EGroupFlagMsgQueueNew;
if (aCmd.focus)
{
iFlags|=EGroupFlagReceivesFocus;
}
iTextCursor.ConstructL(this);
iClientHandle=aCmd.clientHandle;
if(aCmd.screenDeviceHandle <= 0)
{
//Use primary screen. Client should make sure PrimaryScreenDevice is correct set up immediately after establishing session.
iScreenDevice=iWsOwner->PrimaryScreenDevice();
}
else
{
//Use the specified screen
iScreenDevice=STATIC_CAST(DWsScreenDevice*,iWsOwner->HandleToObj(aCmd.screenDeviceHandle,WS_HANDLE_SCREEN_DEVICE));
}
iScreen = (iScreenDevice) ? iScreenDevice->Screen() : CWsTop::Screen(); //if no screen device use screen 0
CWsWindowGroup* parent=NULL;
if (aCmd.parentId>0)
{
parent=CWsWindowGroup::WindowGroupFromIdentifier(aCmd.parentId);
if (!parent)
{
OwnerPanic(EWservPanicWindow);
}
if(parent->Screen() != iScreen)
{
OwnerPanic(EWservPanicWrongScreen);
}
if (parent->iOrdinalPriorityAdjust>0)
{
WS_ASSERT_DEBUG(parent->iQueue==NULL,EWsPanicGroupWindowChainError);
parent->iOrdinalPriorityAdjust=0;
parent->UpdateOrdinalPriority(ETrue);
}
iOrdinalPriorityBase=parent->iOrdinalPriorityBase;
iOrdinalPriority=iOrdinalPriorityBase;
}
CWsWindowBase::ConstructL(RootWindow());
if (parent)
{
TDblQue<CWsWindowGroup>* queue=parent->iQueue;
if (queue && queue->Last()!=parent)
User::Leave(KErrInUse);
if (parent->iWsOwner!=iWsOwner)
{
_LIT_SECURITY_POLICY_S0(securityPolicy,parent->iChildSID);
if (!securityPolicy().CheckPolicy(iWsOwner->ClientMessage()))
User::Leave(KErrPermissionDenied);
}
if (!queue)
{
queue=new(ELeave) TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
CleanupStack::PushL(queue);
User::LeaveIfError(iChains.Append(queue));
CleanupStack::Pop(queue);
queue->AddFirst(*parent);
parent->iQueue=queue;
}
iQueue=queue; //Shouldn't set the queue until after it can leave
iChainLink.Enque(&parent->iChainLink);
}
do
{
AdvanceIdentifierCount(); // Always advance by at least one to stop re-using last id
} while (WindowGroupFromIdentifier(iIdentifierCount)); // If current count is in use try again
iIdentifier=iIdentifierCount;
iMessageArray=new(ELeave) CArrayVarSeg<TWsMessage>(1);
if (CClick::IsHandler())
{
TGroupWindowOpenData params;
params.iIdentifier=iIdentifier;
params.iClient=iWsOwner->ConnectionHandle();
params.iNumClientWindowGroups=NumClientWindowGroups()-1; //Don't include this one
CClick::OtherEvent(EEventGroupWindowOpen,¶ms);
}
if (wsDebugLog)
{
TLogMessageText buf;
_LIT(KWSERVDebugLogGroupWindowId,"Creating: RWindowGroup[0x%x,%d],Id=%d");
buf.Format(KWSERVDebugLogGroupWindowId,iClientHandle,LogHandle(),iIdentifier);
wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, buf);
}
}
void CWsWindowGroup::UpdateOrdinalPriority(TBool aDoAdjust)
{
TInt newPri;
newPri=iOrdinalPriorityBase;
if (iWsOwner==CWsTop::FocusWindowGroupOwner())
newPri+=iOrdinalPriorityAdjust;
CheckCapability(newPri);
if (newPri!=iOrdinalPriority)
{
iOrdinalPriority=newPri;
if (aDoAdjust)
SetOrdinalPosition(0);
}
}
void CWsWindowGroup::SetOrdinalPriority(TInt aPos,TInt aPriority)
{
if (!iQueue)
{
iOrdinalPriorityBase=aPriority;
UpdateOrdinalPriority(EFalse);
}
else
{
TDblQueIter<CWsWindowGroup> iter(*iQueue);
CWsWindowGroup* group;
while ((group=iter++)!=NULL)
{
group->iOrdinalPriorityBase=aPriority;
group->iOrdinalPriority=aPriority;
}
}
SetOrdinalPosition(aPos);
}
void CWsWindowGroup::CommandL(TInt aOpcode, const TAny *aCmdData)
{
#ifdef _DEBUG
// Save root window for performing CheckTree at the end of this func.
// When aOpcode is EWsWinOpFree, this object would've been destroyed
// and a call to RootWindow() in that case would be impossible
CWsRootWindow* rootWindow=RootWindow();
// For certain opcodes, check for the 'screen device deleted' condition. If it
// has occured for the screen device associated with this group window then
// those op-codes are not valid, and the client is panicked.
switch (aOpcode)
{
case EWsWinOpEnableScreenChangeEvents:
case EWsWinOpAllowChildWindowGroup:
case EWsWinOpReceiveFocus:
case EWsWinOpAutoForeground:
case EWsWinOpSetOrdinalPositionPri:
case EWsWinOpSetOrdinalPriorityAdjust:
case EWsWinOpCaptureKey:
case EWsWinOpCaptureKeyUpsAndDowns:
case EWsWinOpCaptureLongKey:
case EWsWinOpAddPriorityKey:
case EWsWinOpSetTextCursor:
case EWsWinOpSetTextCursorClipped:
case EWsWinOpSetOwningWindowGroup:
case EWsWinOpDefaultOwningWindow:
case EWsWinOpSetName:
case EWsWinOpDisableKeyClick:
case EWsWinOpSendPointerEvent:
{
if (ScreenDeviceDeleted())
OwnerPanic(EWservPanicGroupWinScreenDeviceDeleted);
break;
};
}
#endif
TWsWinCmdUnion pData;
pData.any=aCmdData;
if (CWsWindowBase::CommandL(aOpcode,pData)==EFalse)
{
switch(aOpcode)
{
case EWsWinOpAllowChildWindowGroup:
iChildSID=*pData.UInt;
break;
case EWsWinOpEnableScreenChangeEvents:
SetScreenChangeEventStateL(ETrue);
break;
case EWsWinOpDisableScreenChangeEvents:
SetScreenChangeEventStateL(EFalse);
break;
case EWsWinOpReceiveFocus:
iFlags&=~EGroupFlagReceivesFocus;
if (*pData.Bool)
iFlags|=EGroupFlagReceivesFocus;
iScreen->ResetFocus(NULL);
break;
case EWsWinOpAutoForeground:
iFlags&=~EGroupFlagAutoForeground;
if (*pData.Bool)
iFlags|=EGroupFlagAutoForeground;
break;
case EWsWinOpSetOrdinalPositionPri:
case EWsWinOpSetOrdinalPositionErr:
{
TInt priority=pData.OrdinalPos->ordinalPriority;
TBool hascap = CheckCapability(priority);
SetOrdinalPriority(pData.OrdinalPos->pos, priority);
if (aOpcode == EWsWinOpSetOrdinalPositionErr)
{
SetReply(hascap?KErrNone:KErrPermissionDenied);
}
}
break;
case EWsWinOpSetOrdinalPriorityAdjust:
if (!iQueue)
{
iOrdinalPriorityAdjust=*pData.Int;
UpdateOrdinalPriority(ETrue);
}
break;
case EWsWinOpCaptureKey:
{
if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureKey API")))
{
User::Leave(KErrPermissionDenied);
}
CWsCaptureKey *cKey=new(ELeave) CWsCaptureKey(this);
CleanupStack::PushL(cKey);
cKey->ConstructL(*pData.CaptureKey);
CleanupStack::Pop();
}
break;
case EWsWinOpCaptureKeyUpsAndDowns:
{
if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureKeyUpsAndDowns API")))
{
User::Leave(KErrPermissionDenied);
}
CWsCaptureKeyUpsAndDowns *cKey=new(ELeave) CWsCaptureKeyUpsAndDowns(this);
CleanupStack::PushL(cKey);
cKey->ConstructL(*pData.CaptureKey);
CleanupStack::Pop();
}
break;
case EWsWinOpCaptureLongKey:
{
if(!KSecurityPolicy_SwEvent().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::CaptureLongKey API")))
{
User::Leave(KErrPermissionDenied);
}
CWsCaptureLongKey *cKey=new(ELeave) CWsCaptureLongKey(this);
CleanupStack::PushL(cKey);
cKey->ConstructL(*pData.CaptureLongKey);
CleanupStack::Pop();
}
break;
case EWsWinOpCancelCaptureKey:
if (*pData.UInt!=0) // Ignore null handle
{
CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt,WS_HANDLE_CAPTURE_KEY);
if (destroyObj)
{
//Cancel any repeat that is underway for this key
const TWsWinCmdCaptureKey& capKey(*pData.CaptureKey);
CKeyboardRepeat::CancelRepeat(this,capKey.key,EFalse,capKey.modifierMask);
delete destroyObj;
}
else
{
#ifdef _DEBUG
// Attempt to cancel key capture with an incorrect handle
OwnerPanic(EWservPanicDestroy);
#endif // _DEBUG
}
}
break;
case EWsWinOpCancelCaptureKeyUpsAndDowns:
if (*pData.UInt!=0) // Ignore null handle
{
CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt,WS_HANDLE_CAPTURE_KEY_UPDOWNS);
if (destroyObj)
{
//Cancel any repeat that is underway for this key
const TWsWinCmdCaptureKey& capKey(*pData.CaptureKey);
CKeyboardRepeat::CancelRepeat(this,capKey.key,EFalse,capKey.modifierMask);
delete destroyObj;
}
else
{
#ifdef _DEBUG
// Attempt to cancel ups and downs key capture with an incorrect handle
OwnerPanic(EWservPanicDestroy);
#endif // _DEBUG
}
}
break;
case EWsWinOpCancelCaptureLongKey:
if (*pData.UInt!=0) // Ignore null handle
{
CWsObject *destroyObj = iWsOwner->HandleToObj(*pData.UInt,WS_HANDLE_CAPTURE_LONG_KEY);
if (destroyObj)
{
//Cancel any repeat that is underway for this key
const TWsWinCmdCaptureLongKey& capKey(*pData.CaptureLongKey);
CKeyboardRepeat::CancelRepeat(this,capKey.inputKey,ETrue,capKey.modifierMask);
delete destroyObj;
}
else
{
#ifdef _DEBUG
// Attempt to cancel long key capture with an incorrect handle
OwnerPanic(EWservPanicDestroy);
#endif // _DEBUG
}
}
break;
case EWsWinOpAddPriorityKey:
AddPriorityKeyL(pData.PriorityKey->keycode, pData.PriorityKey->modifierMask, pData.PriorityKey->modifiers);
break;
case EWsWinOpRemovePriorityKey:
RemovePriorityKey(pData.PriorityKey->keycode, pData.PriorityKey->modifierMask, pData.PriorityKey->modifiers);
break;
case EWsWinOpSetTextCursor:
iTextCursor.SetL(*pData.SetTextCursor, EFalse);
break;
case EWsWinOpSetTextCursorClipped:
iTextCursor.SetL(*pData.SetTextCursor, ETrue);
break;
case EWsWinOpCancelTextCursor:
iTextCursor.Cancel();
break;
case EWsWinOpSetOwningWindowGroup:
iOwningWindowGroup=*pData.Int;
break;
case EWsWinOpDefaultOwningWindow:
{
if(KSecurityPolicy_WriteDeviceData().CheckPolicy(iWsOwner->ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWindowGroup::DefaultOwningWindow API")))
{
iScreen->SetDefaultOwningWindow(this);
}
}
break;
case EWsWinOpName:
iWsOwner->ReplyGroupName(iGroupName,*pData.Int);
break;
case EWsWinOpSetName:
{
HBufC *newName=NULL;
const TInt size=*pData.Int;
if (size>0)
{
newName=HBufC::NewLC(size);
TPtr ptr(newName->Des());
iWsOwner->RemoteReadL(ptr,0);
CleanupStack::Pop(newName);
}
//Window Group Name is unchanged
if (iGroupName && newName && *iGroupName == *newName)
{
delete newName;
}
else //Window Group Name is changed
{
delete iGroupName;
iGroupName=newName;
TWindowServerEvent::SendGroupChangedEvents();
}
}
break;
case EWsWinOpIdentifier:
SetReply(Identifier());
break;
case EWsWinOpDisableKeyClick:
if (*pData.Bool)
iFlags|=EGroupFlagDisableKeyClick;
else
iFlags&=~EGroupFlagDisableKeyClick;
if (this==CWsTop::FocusWindowGroup())
UpdateKeyClickState();
break;
case EWsWinOpSendPointerEvent:
if (!TWindowServerEvent::MousePress(*pData.RawEvent,this))
OwnerPanic(EWservPanicEventType);
break;
case EWsWinOpClearChildGroup:
if(iQueue)
{
TBool fBefore=EFalse;
TBool fAfter=EFalse;
// If there is nothing to clear, return KErrArgument
if(iQueue->Last()==this)
{
SetReply(KErrArgument);
break;
}
// fBefore is True if there is AT LEAST one window group queued before the current one
else if(iQueue->First()!=this)
{
fBefore=ETrue;
}
// fAfter is True if there is MORE THAN one window group queued after the current one
TDblQueIter<CWsWindowGroup> iter(*iQueue);
iter.SetToLast();
if(iter--!=this && iter!=this)
{
fAfter=ETrue;
}
TDblQue<CWsWindowGroup>* queue=NULL;
// if fBefore and fAfter are True, create a new queue and copy all window groups after the current one into that queue
if(fBefore && fAfter)
{
TInt ret=KErrNoMemory;
queue=new TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
if(queue)
{
ret=iChains.Append(queue);
if(ret!=KErrNone)
{
delete queue;
queue = NULL;
}
}
// Check that the queue creation and appending worked (we deque all the child groups even if it didn't)
if(ret!=KErrNone)
{
SetReply(ret);
}
}
// If we've got zero or one window groups after, don't need to queue them
if(!fAfter || fBefore)
{
iter.SetToLast();
CWsWindowGroup* groupWin;
while((groupWin=iter--)!=this)
{
groupWin->iChainLink.Deque();
groupWin->iQueue=queue;
if(queue)
queue->AddFirst(*groupWin);
}
}
// if we've got no window groups before, don't need to have a queue for this anymore
if(!fBefore)
{
iChainLink.Deque();
if (!fAfter)
{
DeleteQueue(iQueue);
}
iQueue=NULL;
}
}
else // if this window group isn't queued, we can't clear any children
{
SetReply(KErrArgument);
}
break;
case EWsWinOpSetChildGroup:
{
CWsWindowGroup* childWinGroup = CWsWindowGroup::WindowGroupFromIdentifier(*pData.Int);
if(!childWinGroup //(no child to append)
|| (iQueue && (!iQueue->IsLast(this) || (childWinGroup->iQueue==iQueue))) //(GpWin has a child) || (GpWin and childGpWin in the same queue)
|| (childWinGroup->iQueue && !childWinGroup->iQueue->IsFirst(childWinGroup)) //(childGpWin has a parent)
|| (childWinGroup == this)) //(childGpWin == GpWin)
{
SetReply(KErrArgument);
break;
}
if(iQueue)
// If we have a chain, we're prepending ourselves to the child window group
// So we take the childs chain and prepend each of the window groups in our own chain
// beginning with the current window group and working backward
{
TDblQueIter<CWsWindowGroup> iter(*iQueue);
iter.SetToLast();
CWsWindowGroup* groupWin;
if(childWinGroup->iQueue)
{
TDblQue<CWsWindowGroup>* oldQueue=iQueue;
while((groupWin=iter--)!=NULL)
{
groupWin->iChainLink.Deque();
childWinGroup->iQueue->AddFirst(*groupWin);
groupWin->iQueue=childWinGroup->iQueue;
}
DeleteQueue(oldQueue);
}
else
{
iQueue->AddLast(*childWinGroup);
childWinGroup->iQueue=iQueue;
}
}
else
// 1. If we don't have a chain, and if the child has a chain, we can simply prepend this wg to the child
// wg chain
// 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
// as the owning member, and prepend our window group
{
if(childWinGroup->iQueue)
{
childWinGroup->iQueue->AddFirst(*this);
iQueue=childWinGroup->iQueue;
}
else
{
TDblQue<CWsWindowGroup>* queue=new TDblQue<CWsWindowGroup>(_FOFF(CWsWindowGroup,iChainLink));
TInt ret=KErrNoMemory;
if (queue)
{
ret=iChains.Append(queue);
if(ret!=KErrNone)
{
delete queue;
}
}
if(ret!=KErrNone)
{
SetReply(ret);
break;
}
queue->AddFirst(*childWinGroup);
childWinGroup->iQueue=queue;
queue->AddFirst(*this);
iQueue=queue;
}
}
}
break;
default: // All other window commands disallowed
OwnerPanic(EWservPanicOpcode);
}
}
#if defined(_DEBUG)
rootWindow->CheckTree();
#endif
}
TPoint CWsWindowGroup::Origin() const
{
return TPoint(0,0);
}
TRect CWsWindowGroup::AbsRect() const
{
return (TRect(RootWindow()->Abs().iTl,RootWindow()->Size()));
}
TSize CWsWindowGroup::Size() const
{
return RootWindow()->Size();
}
void CWsWindowGroup::UpdateKeyClickState()
{
CClick::SetKeyClickOveride(iFlags&EGroupFlagDisableKeyClick);
}
void CWsWindowGroup::SetOrdinalPosition(TInt aPos)
{
if (aPos==(TInt)KOrdinalPositionSwitchToOwningWindow)
SwitchToOwningWindow(NULL);
else
SetOrdinalPosition(aPos,NULL);
}
TBool CWsWindowGroup::SetOrdinalPosition(TInt aPos,CWsWindowGroup* aClosingWindow)
{
TBool ret=ETrue;
if (!iQueue)
ret=DoSetOrdinalPosition1(aPos,aClosingWindow);
else
{
TDblQueIter<CWsWindowGroup> iter(*iQueue);
CWsWindowGroup* group;
iter.SetToLast();
TInt after=0;
TInt before=0;
TInt* inc=&before;
while ((group=iter--)!=NULL)
{
if (group==this)
inc=&after;
++(*inc);
}
TInt lastWinGpPos=NumWindowGroupsOnMyScreen(OrdinalPriority())-after;
if (aPos<0)
aPos=lastWinGpPos;
else
aPos=Min(aPos,lastWinGpPos);
aPos-=before;
aPos=Max(aPos,0);
iter.SetToLast();
CWsWindowGroup* firstForward=iter--;
while (firstForward && firstForward->OrdinalPosition(EFalse)<aPos)
{
firstForward=iter--;
++aPos;
}
if (!firstForward)
iter.SetToFirst();
else
{
iter.Set(*firstForward);
MoveChainedWindows(iter,ETrue,aPos,aClosingWindow);
iter.Set(*firstForward);
iter++;
}
MoveChainedWindows(iter,EFalse,--aPos,aClosingWindow);
#if defined(_DEBUG)
iter.SetToLast();
TInt pos1=-1;
TInt pos2;
TBool ok=ETrue;
while ((group=iter--)!=this)
{
pos2=group->OrdinalPosition(EFalse);
if (pos2<=pos1)
ok=EFalse;
pos1=pos2;
}
WS_ASSERT_DEBUG(ok, EWsPanicGroupWindowChainError);
#endif
}
return ret;
}
void CWsWindowGroup::MoveChainedWindows(TDblQueIter<CWsWindowGroup>& aIter,TBool aForward,TInt aPos,CWsWindowGroup* aClosingWindow)
{
CWsWindowGroup* groupWindow;
while ((groupWindow=(aForward ? aIter-- : aIter++))!=NULL)
{
groupWindow->DoSetOrdinalPosition1(aPos,aClosingWindow);
(aForward ? ++aPos : --aPos);
}
}
TBool CWsWindowGroup::DoSetOrdinalPosition1(TInt aPos,CWsWindowGroup* aClosingWindow)
{
TBool ret=EFalse;
if (CheckOrdinalPositionChange(aPos))
{
if (Child()) // A group window with no children can not affect shadows
{
ret=ETrue;
}
DoSetOrdinalPosition2(aPos,aClosingWindow);
}
else
iScreen->ResetFocus(aClosingWindow);
return ret;
}
void CWsWindowGroup::DoSetOrdinalPosition2(TInt aPos, CWsWindowGroup *aClosingWindow)
{
ChangeWindowPosition(aPos,iParent);
ResetFocus(aClosingWindow);
}
void CWsWindowGroup::LostFocus()
{
iTextCursor.LostFocus();
iWsOwner->UpdateWindowOrdinalPrioritys();
if (iClientHandle!=0)
QueueEvent(EEventFocusLost);
TWalkWindowTreeFocusChanged wwt(EFalse);
WalkWindowTree(wwt,EWalkChildren);
iWsOwner->SetClientPriority();
}
void CWsWindowGroup::ReceivedFocus()
{
iWsOwner->UpdateWindowOrdinalPrioritys();
iTextCursor.ReceivedFocus();
// Used for event queue testing
// Calling MoveToFront sets the queue of the focused window to first place,
// not doing so puts the queues in unusual situation thus stress testing the queue code.
// One such situation is where the focus queue is first but there is a gap before it (iEventPtr>iGlobalEventPtr)"
#if defined(_DEBUG)
if (++iSkipCount==5)
{
iSkipCount=0;
}
else
{
WsOwner()->EventQueue()->MoveToFront();
}
#else
WsOwner()->EventQueue()->MoveToFront();
#endif
QueueEvent(EEventFocusGained);
TWalkWindowTreeFocusChanged wwt(ETrue);
WalkWindowTree(wwt,EWalkChildren);
iWsOwner->SetClientPriority();
UpdateKeyClickState();
}
TInt CWsWindowGroup::NumWindowGroups(TBool aAllPriorities, TInt aPriority)
{
TInt count=0;
TInt screenNo;
for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
{
count+=CWsWindowGroup::NumWindowGroupsOnScreen(CWsTop::Screen(screenNo)->RootWindow()->Child(),aAllPriorities,aPriority);
}
return(count);
}
TInt CWsWindowGroup::NumWindowGroupsOnScreen(const CWsWindowGroup* aGroupWin,TBool aAllPriorities,TInt aPriority)
{
TInt count=0;
while (aGroupWin)
{
if (aAllPriorities || aGroupWin->iOrdinalPriority==aPriority)
++count;
aGroupWin=aGroupWin->NextSibling();
}
return count;
}
inline TInt CWsWindowGroup::NumWindowGroupsOnMyScreen(TInt aPriority)
{
return(CWsWindowGroup::NumWindowGroupsOnScreen(Parent()->Child(),EFalse,aPriority));
}
void CWsWindowGroup::GetFocusWindowGroupL(TInt aScreenNumber)
{
CWsWindowGroup *groupWin=(aScreenNumber==KDummyScreenNumber)?CWsTop::FocusWindowGroup():CWsTop::Screen(aScreenNumber)->FocusWindowGroup();
if (!groupWin)
User::Leave(KErrGeneral);
CWsClient::SetReply(groupWin->Identifier());
}
TInt CWsWindowGroup::GetWindowGroupListL(TInt aScreenNo,TBool aAllPriorities,TInt aPriority,TInt aCount,CArrayFixFlat<TInt>* aList)
{
TInt count=aList->Count();
CWsWindowGroup* groupWin=CWsTop::Screen(aScreenNo)->RootWindow()->Child();
while(!aAllPriorities && groupWin && groupWin->iOrdinalPriority!=aPriority)
groupWin=groupWin->NextSibling();
while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==aPriority) && count<aCount)
{
aList->AppendL(groupWin->Identifier());
++count;
groupWin=groupWin->NextSibling();
}
return count;
}
TInt CWsWindowGroup::SendWindowGroupListL(TInt aScreenNumber, TBool aAllPriorities, TInt aPriority, TInt aCount)
{
if ((aCount<1) || (aCount>(KArrayMaxGranularity/sizeof(TInt))))
User::Leave(KErrArgument);
CArrayFixFlat<TInt>* list=new(ELeave) CArrayFixFlat<TInt>(aCount);
CleanupStack::PushL(list);
TInt count(0);
TInt requestedScreen=aScreenNumber;
if(requestedScreen==KDummyScreenNumber)
{
// get list from current focus screen first
TInt focusScreenNo=CWsTop::CurrentFocusScreen()->ScreenNumber();
count=GetWindowGroupListL(focusScreenNo, aAllPriorities, aPriority, aCount, list);
if(count<aCount)
{
// now get from the remaining screen
TInt screenNo;
for(screenNo=0;screenNo<CWsTop::NumberOfScreens() && count<aCount;++screenNo)
{
// skip focus screen
if (screenNo==focusScreenNo)
continue;
// count hold total number of window groups collected so far
count=GetWindowGroupListL(screenNo, aAllPriorities, aPriority, aCount, list);
}
}
}
else
{
count=GetWindowGroupListL(requestedScreen, aAllPriorities, aPriority, aCount, list);
}
if (list->Count() > 0)
CWsClient::ReplyBuf(&list->At(0),count*sizeof(TInt));
CleanupStack::PopAndDestroy(list);
return(count); // How many actually returned, may be less than asked for, but not more
}
void CWsWindowGroup::GetWindowGroupListAndChainL(TInt aScreen,TBool aAllPriorities,TInt aPriority
,RArray<RWsSession::TWindowGroupChainInfo>& list,TInt& aCountLeft)
{
CWsWindowGroup *groupWin=CWsTop::Screen(aScreen)->RootWindow()->Child();
while(!aAllPriorities && groupWin && groupWin->iOrdinalPriority!=aPriority)
groupWin=groupWin->NextSibling();
while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==aPriority) && aCountLeft>0)
{
RWsSession::TWindowGroupChainInfo windowId;
windowId.iId=groupWin->Identifier();
if(!groupWin->IsChained(windowId.iParentId))
windowId.iParentId=-1; //Unchained window group
list.AppendL(windowId);
--aCountLeft;
groupWin=groupWin->NextSibling();
}
}
TInt CWsWindowGroup::SendWindowGroupListAndChainL(TBool aAllPriorities, TInt aPriority, TInt aCount)
{
if ((aCount<1) || (aCount>(KArrayMaxGranularity/sizeof(RWsSession::TWindowGroupChainInfo))))
User::Leave(KErrArgument);
RArray<RWsSession::TWindowGroupChainInfo> list(aCount);
CleanupClosePushL(list);
TInt count=aCount;
TInt focusScreenNo=CWsTop::CurrentFocusScreen()->ScreenNumber();
GetWindowGroupListAndChainL(focusScreenNo,aAllPriorities,aPriority,list,count);
TInt screenNo;
for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
{
if (screenNo!=focusScreenNo)
GetWindowGroupListAndChainL(screenNo,aAllPriorities,aPriority,list,count);
}
if (list.Count() > 0)
CWsClient::ReplyBuf(&list[0],aCount*sizeof(RWsSession::TWindowGroupChainInfo));
CleanupStack::PopAndDestroy(&list);
return(aCount-count); // How many actually returned, may be less than asked for, but not more
}
TBool CWsWindowGroup::SendEventToAllGroups(TBool aAllPriorities,TBool aOnePerClient,const TWsClCmdSendEventToWindowGroup& aData)
{
TWsEvent event=aData.event;
if (event.Type()==EEventKey && event.Key()->iRepeats!=0)
CKeyboardRepeat::CancelRepeat(NULL); //Otherwise we will trip an invarient
TInt priority=aData.parameter;
TBool sentToAll=ETrue;
TInt screenNo;
for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
{
CWsWindowGroup *groupWin=CWsTop::Screen(screenNo)->RootWindow()->Child();
if (!aAllPriorities)
{
while(groupWin && groupWin->iOrdinalPriority!=priority)
groupWin=groupWin->NextSibling();
}
CWsWindowGroup* firstGroupWin=groupWin;
CWsClient* lastOwner=NULL;
CWsWindowGroup* groupWin2;
while(groupWin && (aAllPriorities || groupWin->iOrdinalPriority==priority))
{
if (aOnePerClient)
{
if (lastOwner==groupWin->iWsOwner)
goto ContinueLoop;
lastOwner=groupWin->iWsOwner;
for(groupWin2=firstGroupWin;groupWin2!=groupWin;groupWin2=groupWin2->NextSibling())
{
if (groupWin2->iWsOwner==groupWin->iWsOwner)
break;
}
if (groupWin2->iWsOwner==groupWin->iWsOwner && groupWin2!=groupWin)
goto ContinueLoop;
}
event.SetHandle(groupWin->ClientHandle());
if (!groupWin->EventQueue()->QueueEvent(event))
sentToAll=EFalse;
ContinueLoop:
groupWin=groupWin->NextSibling();
}
}
return sentToAll;
}
void CWsWindowGroup::SendMessageToAllGroupsL(CWsClient& aSender,TBool aAllPriorities,const TWsClCmdSendMessageToWindowGroup& aData)
{
TInt screenNo;
for(screenNo=0;screenNo<CWsTop::NumberOfScreens();++screenNo)
{
CWsWindowGroup* groupWin=CWsTop::Screen(screenNo)->RootWindow()->Child();
if (!aAllPriorities)
{
while(groupWin && groupWin->iOrdinalPriority!=aData.identifierOrPriority)
groupWin=groupWin->NextSibling();
}
while(groupWin && (aAllPriorities || (groupWin->iOrdinalPriority==aData.identifierOrPriority)))
{
groupWin->QueueMessageL(aData.uid, aData.dataLength, aSender);
groupWin=groupWin->NextSibling();
}
}
}
CWsWindowGroup *CWsWindowGroup::WindowGroupFromIdentifier(TInt aIdentifier)
{
// apply to all screens
TInt screenNo;
for (screenNo=0; screenNo<CWsTop::NumberOfScreens(); ++screenNo)
{
CWsWindowGroup* group;
for(group=CWsTop::Screen(screenNo)->RootWindow()->Child(); group; group=group->NextSibling())
{
if (group->Identifier() == aIdentifier)
return group;
}
}
return NULL;
}
CWsWindowGroup *CWsWindowGroup::WindowGroupFromIdentifierL(TInt aIdentifier)
{
CWsWindowGroup *group=WindowGroupFromIdentifier(aIdentifier);
if (!group)
User::Leave(KErrNotFound);
return(group);
}
CWsWindowGroup *CWsWindowGroup::FindWindowGroupL(CWsClient* aClient, TInt aIdentifier,TInt aOffset,const TPtrC *aMatch,const TThreadId *aThreadId)
{
CWsWindowGroup *group;
if (aIdentifier)
{
group=WindowGroupFromIdentifier(aIdentifier);
if (group) // NULL group will cause KErrNotFound to be returned
group=group->NextSibling();
}
else
{
// get window group for this session
//
group = aClient->Screen()->RootWindow()->Child();
}
for(;group;group=group->NextSibling())
{
if (aThreadId)
{
if (group->WsOwner()->Client().Id()==*aThreadId)
break; // Found one
}
else
{
const TDesC *groupName=&nullDescriptor;
if (group->GroupName())
groupName=group->GroupName();
if (groupName->Length()>=aOffset && groupName->Mid(aOffset).MatchF(*aMatch)>=0)
break; // Found one
}
}
if (!group)
User::Leave(KErrNotFound);
return(group);
}
void CWsWindowGroup::AddPriorityKeyL(TUint aKeycode, TUint aModifierMask, TUint aModifiers)
{
iPriorityKeys=new(ELeave) TPriorityKey(aKeycode,aModifierMask,aModifiers,iPriorityKeys);
}
void CWsWindowGroup::RemovePriorityKey(TUint aKeycode, TUint aModifierMask, TUint aModifiers)
{
for(TPriorityKey **ppk=&iPriorityKeys;*ppk;ppk=&((*ppk)->iNext))
if ((*ppk)->Equals(aKeycode, aModifierMask, aModifiers))
{
TPriorityKey *next=(*ppk)->iNext;
delete *ppk;
*ppk=next;
break;
}
}
void CWsWindowGroup::RemoveAllPriorityKeys()
{
TPriorityKey *pk=iPriorityKeys;
while(pk)
{
TPriorityKey *next=pk->iNext;
delete pk;
pk=next;
}
}
TBool CWsWindowGroup::CheckForPriorityKey(const TKeyData &aKey, TInt aScanCode)
{
for(TPriorityKey *pk=iPriorityKeys;pk;pk=pk->iNext)
{
if (pk->KeyMatches(aKey))
{
WsOwner()->PriorityKeyPressed(ClientHandle(),aKey, aScanCode);
return(ETrue);
}
}
return(EFalse);
}
void CWsWindowGroup::StatusDump(TDes &aBuf)
{
_LIT(KWSERVStatusDumpWindowGroupInfo,"CWsWindowGroup[0x%x]RWindowGroup[0x%x,%d],Pri=%d,Id=%d,SizeMode=%d");
aBuf.AppendFormat(KWSERVStatusDumpWindowGroupInfo,this,iClientHandle,LogHandle(),iOrdinalPriority,iIdentifier,iScreenDevice?iScreenDevice->AppMode():0);
}
void CWsWindowGroup::SignalMessageReady()
{
TWsEvent event;
event.SetType(EEventMessageReady);
event.SetHandle(ClientHandle());
event.SetTimeNow();
SEventMessageReady& eventMessageReady=*(SEventMessageReady*)event.EventData();
eventMessageReady.iWindowGroupIdentifier=Identifier();
eventMessageReady.iMessageUid=(*iMessageArray)[0].iUid;
eventMessageReady.iMessageParametersSize=iMessageArray->Length(0)-sizeof(TUid);
if(WsOwner()->EventQueue()->QueueEvent(event,EEventPriorityHigh))
{
iFlags|=EGroupFlagMessageSignalled;
}
}
void CWsWindowGroup::QueueMessageL(TUid aUid, TInt aDataLength, CWsClient& aSender)
{
WS_ASSERT_DEBUG(iFlags&(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew) || iMessageArray->Count()>=1,EWsPanicMsgQueueError);
if (!(iFlags&(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew)) && iMessageArray->Count()>=KMaxNumberOfMsgsInInactiveQueue)
{
WS_ASSERT_DEBUG(iMessageArray->Count()<=KMaxNumberOfMsgsInInactiveQueue,EWsPanicMsgQueueError);
iMessageArray->Delete(1,iMessageArray->Count()-1);
}
TWsMessage* message=NULL;
TRAPD(err,message=&iMessageArray->ExtendL(aDataLength+sizeof(aUid)));
if ((err || (iFlags&EGroupFlagMsgQueueNew)) && iMessageArray->Count()>KMaxNumberOfMsgsInQueue)
{
iFlags&=~(EGroupFlagMsgQueueActive|EGroupFlagMsgQueueNew);
iMessageArray->Delete(1,iMessageArray->Count()-(err?1:2));
iMessageArray->Compress();
}
User::LeaveIfError(err);
if (message)
{
message->iUid=aUid;
TPtr8 ptr(&message->iTheRest[0],aDataLength);
TRAP(err,aSender.RemoteReadL(ptr,0));
if (err)
{
iMessageArray->Delete(iMessageArray->Count()-1);
User::Leave(err);
}
if (!(iFlags&EGroupFlagMessageSignalled))
{
WS_ASSERT_DEBUG(iMessageArray->Count()==1,EWsPanicMsgQueueError);
SignalMessageReady();
}
}
}
void CWsWindowGroup::FetchMessageL()
{
if (!(iFlags&EGroupFlagMessageSignalled))
{
OwnerPanic(EWservPanicFetchMessage);
}
CWsClient::ReplyBuf(&((*iMessageArray)[0].iTheRest[0]),(TInt)iMessageArray->Length(0)-sizeof(TUid));
iMessageArray->Delete(0);
iFlags|=EGroupFlagMsgQueueActive;
iFlags&=~(EGroupFlagMessageSignalled|EGroupFlagMsgQueueNew);
if (iMessageArray->Count()>0)
{
SignalMessageReady();
}
}
TBool CWsWindowGroup::ScreenDeviceValid() const
{
return(iScreenDevice?iScreenDevice->ScreenDeviceValidState():(iScreen->ScreenSizeMode()==0));
}
TBool CWsWindowGroup::CanReceiveFocus() const
{
return(ReceivesFocus() && iWsOwner->NotClosing() && (ScreenDeviceValid() || iFlags&EGroupFlagHandlesDeviceChange));
}
void CWsWindowGroup::SetScreenChangeEventStateL(TBool aEnabled)
{
iFlags&=~EGroupFlagHandlesDeviceChange;
if (aEnabled)
{
iFlags|=EGroupFlagHandlesDeviceChange;
TWindowServerEvent::AddToScreenDeviceChangeEventListL(*this);
if (iScreen->ScreenSizeMode()!=0)
TWindowServerEvent::SendScreenDeviceChangedEvent(this);
}
else
TWindowServerEvent::RemoveFromScreenDeviceChangeEventList(*this);
iScreen->ResetFocus(NULL);
}
void CWsWindowGroup::SetScreenDeviceValidState(const DWsScreenDevice *aDevice)
{
if (iScreenDevice==aDevice)
{
TBool state=ScreenDeviceValid();
for(CWsClientWindow *win=Child();win;win=win->NextSibling())
{
win->SetScreenDeviceValidState(state);
}
}
}
void CWsWindowGroup::SetScreenDeviceValidStates(const DWsScreenDevice *aDevice)
{
for(CWsWindowGroup *groupWin=aDevice->RootWindow()->Child();groupWin;groupWin=groupWin->NextSibling())
groupWin->SetScreenDeviceValidState(aDevice);
}
TBool CWsWindowGroup::SetScreenDeviceValidStates(const TBool aScreenSizeChanged,const TBool aSwapWidthAndHeight, CScreen* aScreen)
{
TBool ret=EFalse;
CWsRootWindow* rootWindow = aScreen->RootWindow();
CWsWindowGroup* groupWin;
CWsClientWindow* win;
for(groupWin=rootWindow->Child();groupWin;groupWin=groupWin->NextSibling())
{
TBool state=groupWin->ScreenDeviceValid();
for(win=groupWin->Child();win;win=win->NextSibling())
{
win->SetScreenDeviceValidStateFlag(state);
win->ResetHiddenFlagsInParentAndChildren();
}
}
if (aScreenSizeChanged)
{
rootWindow->ScreenSizeChanged(aSwapWidthAndHeight);
}
aScreen->AddRedrawRegion(rootWindow->WindowArea());
return ret;
}
void CWsWindowGroup::SetScreenDevice(DWsScreenDevice *aDevice)
{
iScreenDevice=aDevice;
}
void CWsWindowGroup::NewOrientation(TInt aMode,CFbsBitGc::TGraphicsOrientation aRotation, CWsRootWindow* aRootWindow)
{
for(CWsWindowGroup *groupWin=aRootWindow->Child();groupWin;groupWin=groupWin->NextSibling())
{
DWsScreenDevice *device=groupWin->Device();
if (device)
device->NewOrientation(aMode,aRotation);
}
}
void CWsWindowGroup::ResetFocus(CWsWindowGroup *aClosingWindow)
{
if (iScreen)
{
iScreen->ResetFocus(aClosingWindow);
}
}
TBool CWsWindowGroup::IsChained(TInt& aParentId)
{
if (!iQueue)
return EFalse;
if (iQueue->First()==this)
aParentId=0;
else
aParentId=BeforeInChain()->Identifier();
return ETrue;
}
inline CWsWindowGroup* CWsWindowGroup::BeforeInChain()
{ //You should only call this function if you know the window has a parent
return reinterpret_cast<CWsWindowGroup*>(PtrSub(iChainLink.iPrev,_FOFF(CWsWindowGroup,iChainLink)));
}
TBool CWsWindowGroup::CheckCapability(TInt& aOrdinalPriority)
{
if(aOrdinalPriority>=KPasswordWindowGroupPriority)
{
if(!KSecurityPolicy_SwEvent().CheckPolicy(WsOwner()->Client(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed")))
{
aOrdinalPriority=KPasswordWindowGroupPriority-1;
return EFalse;
}
}
return ETrue;
}
TBool CWsWindowGroup::HasVisibleTranslucentChild()
{
CWsWindowBase * child = iChild;
while (child)
{
if (child->WinType() == EWinTypeClient)
{
CWsClientWindow * cliwin = static_cast<CWsClientWindow *>(child);
if (cliwin->IsTranslucent() && cliwin->IsVisible())
return ETrue;
}
else if (static_cast<CWsWindowGroup*>(child)->HasVisibleTranslucentChild())
{
return ETrue;
}
child = child->NextSibling();
}
return EFalse;
}
TInt CWsWindowGroup::NumClientWindowGroups()
{
CWsObjectIx& objix=*WsOwner()->ObjectIndex();
const TWsObject* ptr=objix.FirstObject();
const TWsObject* end=ptr+objix.Length();
TInt count=0;
while(++ptr<end) //First one should always have a NULL object
{
const CWsObject* obj=ptr->iObject;
if (obj && obj->Type()==WS_HANDLE_GROUP_WINDOW)
++count;
}
return count;
}