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