--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nonnga/SERVER/GROUPWIN.CPP Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,1418 @@
+// 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;
+ }
+