windowing/windowserver/nonnga/SERVER/WINDOW.CPP
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Window functions
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "server.h"
       
    19 #include "rootwin.h"
       
    20 #include "window.h"
       
    21 #include "walkwindowtree.h"
       
    22 #include "wstop.h"
       
    23 #include "ScrDev.H"
       
    24 #include "EVENT.H"
       
    25 #include "ANIM.H"
       
    26 #include "Direct.H"
       
    27 #include "panics.h"
       
    28 #include "backedupwindow.h"
       
    29 #include "wstypes.h"
       
    30 #include "offscreenbitmap.h"
       
    31 
       
    32 CWsWindow* CWsWindow::iAccessListRecentEnd = 0;
       
    33 CWsWindow* CWsWindow::iAccessListOldestEnd = 0;
       
    34 
       
    35 CWsWindow::CWsWindow(CWsClient* aOwner,WH_HANDLES aType, CScreen* aScreen) : CWsWindowBase(aOwner,aType,aScreen),
       
    36 	iFlags(EFlagHidden),
       
    37 	 iDSAs(_FOFF(CWsDirectScreenAccess,iMultipleDSALink))
       
    38 	{
       
    39 	}
       
    40 
       
    41 CWsWindow::~CWsWindow()
       
    42 	{
       
    43 	iFadableRegion.Close();
       
    44 	}
       
    45 
       
    46 void CWsWindow::Construct()
       
    47 	{
       
    48 	InsertIntoAccessListOldestEnd();
       
    49 	}
       
    50 
       
    51 void CWsWindow::Shutdown()
       
    52 	{
       
    53 	TWindowServerEvent::NotifyDrawer(TWservCrEvent(TWservCrEvent::EWindowClosing, 0, 0, this));
       
    54 	RemoveFromAccessList();	
       
    55 	CWsAnim::WindowClosing(iAnimList);	// Destroy any animated objects attached to this window
       
    56 	iVisibleRegion.Close();
       
    57 	iScheduledRegion.Close();
       
    58 	AbortAllDSAs();
       
    59 	CWsWindowBase::Shutdown();
       
    60 	SetPointerCursor(NULL);
       
    61 	delete iRedraw;
       
    62 	}
       
    63 
       
    64 //
       
    65 // Region and invalid area functions //
       
    66 //
       
    67 
       
    68 TRect CWsWindow::FullRect() const
       
    69 	{
       
    70 	return(TRect(iOrigin,iRel.Size()));
       
    71 	}
       
    72 
       
    73 //
       
    74 // Normal regions //
       
    75 //
       
    76 
       
    77 void CWsWindow::SetNonFading(TBool aNonFade)
       
    78 	{
       
    79 	if (aNonFade)
       
    80 		iFlags|=EFlagNonFadingWindow;
       
    81 	else
       
    82 		iFlags&=(~EFlagNonFadingWindow);
       
    83 	}
       
    84 
       
    85 TPoint CWsWindow::InquireOffset(TUint32 aHandle) const
       
    86 	{
       
    87 	CWsWindowBase *win2;
       
    88 	iWsOwner->HandleToWindow(aHandle,&win2);
       
    89 	return(iOrigin-win2->Origin());
       
    90 	}
       
    91 
       
    92 TDisplayMode CWsWindow::DisplayMode() const
       
    93 	{
       
    94 	return iScreen->DisplayMode();
       
    95 	}
       
    96 
       
    97 void CWsWindow::StatusDump(TDes &aBuf)
       
    98 	{
       
    99 	_LIT(KStatusString1,"CWsWindow[0x%x]RWindow[0x%x,%d],Pos(%d,%d),Size(%d,%d)");
       
   100 	_LIT(KStatusString3,",Mode=%d");
       
   101 	_LIT(KStatusInvisible,",Inv");
       
   102 	aBuf.AppendFormat(KStatusString1,this,iClientHandle,LogHandle(),iRel.iTl.iX,iRel.iTl.iY,Size().iWidth,Size().iHeight);
       
   103 	aBuf.AppendFormat(KStatusString3,(TInt)iScreen->DisplayMode());
       
   104 	if (!IsVisible())
       
   105 		aBuf.Append(KStatusInvisible);
       
   106 	}
       
   107 
       
   108 TDblQue<TPointerKeyList> *CWsWindow::PointerKeyList() const
       
   109 	{
       
   110 	return(NULL);
       
   111 	}
       
   112 
       
   113 void CWsWindow::AbortAllDSAs()
       
   114 	{
       
   115 	iScreen->AbortDSAs(RDirectScreenAccess::ETerminateRegion,iDSAs);
       
   116 	}
       
   117 
       
   118 void CWsWindow::PossibleVisibilityChangedEvent(TBool aForceSend)
       
   119 	{
       
   120 	// notify plugin
       
   121 	//
       
   122 	TWservCrEvent crEvent(TWservCrEvent::EWindowVisibilityChanged, HasBeenDrawnToScreen(), IsVisible()? &iVisibleRegion : NULL, this);
       
   123 	TWindowServerEvent::NotifyDrawer(crEvent);
       
   124 	
       
   125 	if (!(iFlags & EFlagGeneratesVisibilityEvents))
       
   126 		return;
       
   127 
       
   128 	if (!IsVisible())
       
   129 		{
       
   130 		goto notvisible;
       
   131 		}
       
   132 
       
   133 	if (iVisibleRegion.Count() == 0)
       
   134 		{
       
   135 		goto notvisible;
       
   136 		}
       
   137 
       
   138 		{// braces here to avoid gccxml error
       
   139 		TInt visibleArea = 0;
       
   140 		TInt count = iVisibleRegion.Count();
       
   141 		TInt ii;
       
   142 		for (ii = 0; ii < count; ii++)
       
   143 			{
       
   144 			visibleArea+= iVisibleRegion[ii].Width() * iVisibleRegion[ii].Height();
       
   145 			}
       
   146 
       
   147 		const TRegion* baseRegion = (static_cast<CWsClientWindow*>(this))->BaseArea();
       
   148 		TInt baseArea = 0;
       
   149 		count = baseRegion->Count();
       
   150 		for (ii = 0; ii < count; ii++)
       
   151 			{
       
   152 			const TRect& rect = (*baseRegion)[ii];
       
   153 			baseArea+= rect.Width() * rect.Height();
       
   154 			}
       
   155 
       
   156 		if (visibleArea == baseArea)
       
   157 			{
       
   158 			goto fullyvisible;
       
   159 			}
       
   160 		else
       
   161 			{
       
   162 			goto partiallyvisible;
       
   163 			}
       
   164 		}
       
   165 
       
   166 fullyvisible:
       
   167 	if (aForceSend || !(iFlags & EFlagNotCantBeSeen) || !(iFlags & EFlagCanBeSeen))
       
   168 		{
       
   169 		iFlags |= (EFlagCanBeSeen | EFlagNotCantBeSeen);
       
   170 		TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::EPartiallyVisible | TWsVisibilityChangedEvent::EFullyVisible);
       
   171 		// we have to set EPartiallyVisible too for compatibility reasons
       
   172 		}
       
   173 	return;
       
   174 
       
   175 partiallyvisible:
       
   176 	if (aForceSend || !(iFlags & EFlagCanBeSeen) || (iFlags & EFlagNotCantBeSeen))
       
   177 		{
       
   178 		iFlags |= EFlagCanBeSeen;
       
   179 		iFlags &= ~EFlagNotCantBeSeen;
       
   180 		TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::EPartiallyVisible);
       
   181 		}
       
   182 	return;
       
   183 
       
   184 notvisible:
       
   185 	if (aForceSend || (iFlags & EFlagCanBeSeen) || (iFlags & EFlagNotCantBeSeen))
       
   186 		{
       
   187 		iFlags &= ~(EFlagCanBeSeen | EFlagNotCantBeSeen);
       
   188 		TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::ENotVisible);
       
   189 		}
       
   190 	return;
       
   191 	}
       
   192 
       
   193 TPoint CWsWindow::Origin() const
       
   194 	{
       
   195 	return iOrigin;
       
   196 	}
       
   197 
       
   198 TRect CWsWindow::AbsRect() const
       
   199 	{
       
   200 	return iAbs;
       
   201 	}
       
   202 	
       
   203 TSize CWsWindow::Size() const
       
   204 	{
       
   205 	return iRel.Size();
       
   206 	}
       
   207 
       
   208 TBool CWsWindow::SetScheduledRegion(const RWsRegion& aRegion)
       
   209 	{
       
   210 	iScheduledRegion.Copy(aRegion);
       
   211 	return !iScheduledRegion.CheckError();
       
   212 	}
       
   213 
       
   214 void CWsWindow::ClearScheduledRegion()
       
   215 	{
       
   216 	iScheduledRegion.Clear();
       
   217 	}
       
   218 
       
   219 void CWsWindow::SetFadeBehind(TBool aFade)
       
   220 	{
       
   221 	if (aFade != ((iFlags & EFlagFadeBehind) != 0))
       
   222 		{
       
   223 		iFlags ^= EFlagFadeBehind;
       
   224 		}
       
   225 	}
       
   226 
       
   227 void CWsWindow::FocusChanged(TBool aNewFocusState)
       
   228 	{
       
   229 	TRAPD(err,FocusChangedL(aNewFocusState));
       
   230 	if (err!=KErrNone)
       
   231 		OwnerPanic(EWservPanicAnimLeave);
       
   232 	}
       
   233 
       
   234 void CWsWindow::FocusChangedL(TBool aNewFocusState)
       
   235 	{
       
   236 	for (CWsAnim * anim = iAnimList; anim; anim = anim->Next())
       
   237 		{
       
   238 		anim->FocusChanged(aNewFocusState);
       
   239 		}
       
   240 	}
       
   241 
       
   242 // Moves a window to the recent end of the accessed list
       
   243 void CWsWindow::Accessed()
       
   244 	{
       
   245 	WS_ASSERT_DEBUG(iAccessListRecentEnd && iAccessListOldestEnd, EWsPanicAccessList);
       
   246 
       
   247 	RemoveFromAccessList();	
       
   248 	InsertIntoAccessListRecentEnd();
       
   249 	}
       
   250 
       
   251 void CWsWindow::InsertIntoAccessListOldestEnd()
       
   252 	{
       
   253 	iAccessListPrev = 0;
       
   254 	iAccessListNext = iAccessListOldestEnd;
       
   255 	if (iAccessListNext)
       
   256 		iAccessListNext->iAccessListPrev = this;
       
   257 	iAccessListOldestEnd = this;
       
   258 	if (!iAccessListRecentEnd)
       
   259 		iAccessListRecentEnd = this;
       
   260 	}
       
   261 
       
   262 void CWsWindow::InsertIntoAccessListRecentEnd()
       
   263 	{
       
   264 	iAccessListNext = 0;
       
   265 	iAccessListPrev = iAccessListRecentEnd;
       
   266 	if (iAccessListPrev)
       
   267 		iAccessListPrev->iAccessListNext = this;
       
   268 	iAccessListRecentEnd = this;
       
   269 	if (!iAccessListOldestEnd)
       
   270 		iAccessListOldestEnd = this;
       
   271 	}
       
   272 
       
   273 void CWsWindow::RemoveFromAccessList()
       
   274 	{
       
   275 	if (iAccessListOldestEnd == this)
       
   276 		iAccessListOldestEnd = iAccessListNext;
       
   277 	if (iAccessListRecentEnd == this)
       
   278 		iAccessListRecentEnd = iAccessListPrev;
       
   279 	if (iAccessListPrev)
       
   280 		iAccessListPrev->iAccessListNext = iAccessListNext;
       
   281 	if (iAccessListNext)
       
   282 		iAccessListNext->iAccessListPrev = iAccessListPrev;
       
   283 	}
       
   284 	
       
   285 TBool CWsWindow::ReleaseMemory(MWsMemoryRelease::TMemoryReleaseLevel aLevel)
       
   286 	{
       
   287 	for (CWsWindow * access = iAccessListOldestEnd; access; access = access->iAccessListNext)
       
   288 		{
       
   289 		if(access->Redraw())
       
   290 			{
       
   291 			if (access->Redraw()->ReleaseMemory(aLevel))
       
   292 				return ETrue;
       
   293 			}
       
   294 		}
       
   295 	return EFalse;
       
   296 	}
       
   297 
       
   298 const TRegion& CWsWindow::VisibleRegion() const
       
   299 	{
       
   300 	return(iVisibleRegion);
       
   301 	}
       
   302 
       
   303 TBool CWsWindow::IsDSAHost() const
       
   304 	{
       
   305 	TBool res = EFalse; 
       
   306 	if ( !iDSAs.IsEmpty() )
       
   307 		{
       
   308 		TSglQueIter<CWsDirectScreenAccess> iter( (TSglQueBase&)iDSAs );
       
   309 		iter.SetToFirst();
       
   310 		CWsDirectScreenAccess* dsa;
       
   311 		while ( (dsa = iter++) != NULL && !res )
       
   312 			{
       
   313 			res = dsa->IsVisible() || dsa->IsSyncTimeoutPending();
       
   314 			}
       
   315 		}
       
   316 	return res;
       
   317 	}
       
   318 
       
   319 void CWsWindow::ResetVisibleRegion()
       
   320 	{
       
   321 	if (!iVisibleRegion.IsEmpty())
       
   322 		{
       
   323 		iVisibleRegion.Clear();
       
   324 		}
       
   325 	iFadableRegion.Clear();
       
   326 	}
       
   327 
       
   328 void CWsWindow::SetVisibleRegion(const TRegion& aNewRegion, const TRegion* aTop, TRegion& aNewFadableRegion)
       
   329 	{
       
   330 	STACK_REGION difference;
       
   331 	TBool diffs = EFalse;
       
   332 
       
   333 	difference.Copy(iVisibleRegion);
       
   334 	difference.SubRegion(aNewRegion);
       
   335 	if (!difference.IsEmpty())
       
   336 		{
       
   337 		diffs = ETrue;
       
   338 		if (IsTranslucent())
       
   339 			{
       
   340 			// Andy - If this is a client window (what else could it be) we can also subtract the
       
   341 			// user defined opaque region before doing this:
       
   342 			iScreen->AddRedrawRegion(difference, EFalse);
       
   343 			}
       
   344 		}
       
   345 
       
   346 	difference.Copy(aNewRegion);
       
   347 	if (HasBeenDrawnToScreen())
       
   348 		{
       
   349 		difference.SubRegion(iVisibleRegion);
       
   350 		}
       
   351 	if (!difference.IsEmpty())
       
   352 		{
       
   353 		diffs = ETrue;
       
   354 		STACK_REGION topDiff;
       
   355 		topDiff.Copy(difference);
       
   356 		WS_ASSERT_DEBUG(aTop,EWsPanicRegion);
       
   357 		topDiff.Intersect(*aTop);
       
   358 		difference.SubRegion(topDiff);
       
   359 		iScreen->AddRedrawRegion(topDiff, EFalse, ERedrawTopOnly);
       
   360 		iScreen->AddRedrawRegion(difference, EFalse, ERedrawAll);
       
   361 		topDiff.Close();
       
   362 		}
       
   363 
       
   364 	difference.Close();
       
   365 
       
   366 	AbortDsaIfRequired(aNewRegion, aTop);
       
   367 
       
   368 	if (diffs)
       
   369 		{
       
   370 		ResetVisibleRegion();
       
   371 		iVisibleRegion.Copy(aNewRegion);
       
   372 		PossibleVisibilityChangedEvent(EFalse);
       
   373 		}
       
   374 
       
   375 	iFadableRegion.Copy( aNewFadableRegion );
       
   376 	
       
   377 	// Just because the visible region (screen coordinates) didn't change doesn't
       
   378 	// mean the invalid region (window coordinates) didn't change, so we always call this.
       
   379 	iRedraw->VisibleRegionChange();
       
   380 	}
       
   381 	
       
   382 void CWsWindow::ClearVisibleRegion()
       
   383 	{
       
   384 	AbortAllDSAs();         
       
   385 	iScreen->AddRedrawRegion(VisibleRegion(), EFalse);
       
   386 	ResetVisibleRegion();
       
   387 	PossibleVisibilityChangedEvent(EFalse);
       
   388 	iFlags &= ~EFlagDrawnToScreen;
       
   389 	}
       
   390 
       
   391 void CWsWindow::AbortDsaIfRequired(const TRegion& aNewRegion, const TRegion* aTop)
       
   392 	{
       
   393 	if (!iDSAs.IsEmpty())
       
   394 		{
       
   395 		// If the top visible region of this window has changed, DSA clients may need
       
   396 		// to be sent a DSA abort, as they may be drawing to a different region
       
   397 		STACK_REGION newTopVisible;
       
   398 		newTopVisible.Copy(aNewRegion); // new visible region
       
   399 		if (aTop!=NULL)
       
   400 			{
       
   401 			newTopVisible.Intersect(*aTop); // area of new visible region not obscured by any other opaque or translucent windows
       
   402 			}
       
   403 		// Build a list of DSA clients that need to be sent a DSA abort
       
   404 		TSglQue<CWsDirectScreenAccess> dsaList(_FOFF(CWsDirectScreenAccess,iAbortLink));
       
   405 		TSglQueIter<CWsDirectScreenAccess> iter(iDSAs);
       
   406 		CWsDirectScreenAccess* dsa;
       
   407 		while ((dsa=iter++)!=NULL)
       
   408 			{
       
   409 			if (dsa->IsAbortRequired(newTopVisible))
       
   410 				{
       
   411 				dsaList.AddLast(*dsa);
       
   412 				}
       
   413 			}
       
   414 		if (!dsaList.IsEmpty())
       
   415 			{
       
   416 			iScreen->AbortDSAs(RDirectScreenAccess::ETerminateRegion, dsaList);
       
   417 			}
       
   418 		newTopVisible.Close();
       
   419 		}
       
   420 	}
       
   421 
       
   422 const TRegion* CWsWindow::VisibleRegionIfValid() const
       
   423 	{
       
   424 	return iVisibleRegion.CheckError() ? NULL : &iVisibleRegion;
       
   425 	}
       
   426 	
       
   427 TBool CWsWindow::ReadyToDraw() const
       
   428 	{
       
   429 	return iRedraw->ReadyToDraw();
       
   430 	}
       
   431 
       
   432 /**
       
   433 This function draws the region specified
       
   434 Andy - I would be happier if no region was specified here - the GC should incorporate that information
       
   435 */
       
   436 void CWsWindow::Render(CFbsBitGc * aGc, const TRegion& aRegion)
       
   437 	{
       
   438 	WS_ASSERT_DEBUG(IsVisible() || (WinType() == EWinTypeRoot), EWsPanicScheduledRedraw);
       
   439 	
       
   440 	Accessed();
       
   441 	iFlags |= EFlagDrawnToScreen;
       
   442 	
       
   443 	iRedraw->PreDrawWindow(aGc, aRegion);
       
   444 	iRedraw->DrawWindow();
       
   445 	iRedraw->PostDrawWindow(aGc);
       
   446 	}
       
   447 
       
   448 void CWsWindow::SetNextScheduled(CWsWindow * aWin)
       
   449 	{
       
   450 	iNextScheduled = aWin;
       
   451 	}
       
   452 	
       
   453 CWsWindow * CWsWindow::NextScheduled()  const
       
   454 	{
       
   455 	return iNextScheduled;
       
   456 	}
       
   457 
       
   458 void CWsWindow::AddSprite(CWsSpriteBase * aSprite)
       
   459 	{
       
   460 	aSprite->SetNext(iSpriteList);
       
   461 	iSpriteList = aSprite;
       
   462 	}
       
   463 	
       
   464 void CWsWindow::RemoveSprite(CWsSpriteBase * aSprite)
       
   465 	{
       
   466 	if (aSprite == iSpriteList)
       
   467 		{
       
   468 		iSpriteList = aSprite->Next();
       
   469 		}
       
   470 	else
       
   471 		{
       
   472 		for (CWsSpriteBase * sprite = iSpriteList; sprite; sprite = sprite->Next())
       
   473 			{
       
   474 			if (sprite->Next() == aSprite)
       
   475 				{
       
   476 				sprite->SetNext(aSprite->Next());
       
   477 				}
       
   478 			}
       
   479 		}
       
   480 	aSprite->SetNext(0);
       
   481 	}
       
   482 
       
   483 void CWsWindow::DeactivateAllSprites()
       
   484 	{
       
   485 	CWsSpriteBase * current = iSpriteList;
       
   486 	while (current)
       
   487 		{
       
   488 		CWsSpriteBase * next = current->Next();
       
   489 		current->Deactivate();
       
   490 		current = next;
       
   491 		}
       
   492 	}
       
   493 
       
   494 void CWsWindow::ClipRectToViewport(TRect& aRect) const
       
   495 	{
       
   496 	const CWsWindowBase * win = this;
       
   497 	while (win)
       
   498 		{
       
   499 		if (win->WinType() != EWinTypeGroup)
       
   500 			{
       
   501 			aRect.Intersection(win->AbsRect());
       
   502 			}
       
   503 		win = win->BaseParent();
       
   504 		}
       
   505 	}
       
   506 
       
   507 const TRegion& CWsWindow::FadableRegion() const
       
   508 	{
       
   509 	return iFadableRegion;
       
   510 	}
       
   511 
       
   512 /**
       
   513 MWsWindow
       
   514 */
       
   515 MWsWindow * CWsWindow::FindChildByHandle(TUint32 aHandle)
       
   516 	{
       
   517 	TWalkWindowTreeFindByHandle wwt(aHandle);
       
   518 	WalkWindowTree(wwt, EWalkChildren);
       
   519 	return wwt.Found();
       
   520 	}
       
   521 
       
   522 TUint32 CWsWindow::Handle() const
       
   523 	{
       
   524 	return ClientHandle();
       
   525 	}
       
   526 
       
   527 MWsScreen * CWsWindow::WsScreen() const
       
   528 	{
       
   529 	return iScreen;
       
   530 	}
       
   531 
       
   532 TInt CWsWindow::OrdinalPriority() const
       
   533 	{
       
   534 	return iOrdinalPriority;
       
   535 	}