author | Gareth Stockwell <gareth.stockwell@accenture.com> |
Fri, 22 Oct 2010 11:38:29 +0100 | |
branch | bug235_bringup_0 |
changeset 206 | c170e304623f |
parent 0 | 5d03bc08d59c |
permissions | -rw-r--r-- |
// Copyright (c) 1994-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: // Window functions // // #include "server.h" #include "rootwin.h" #include "window.h" #include "walkwindowtree.h" #include "wstop.h" #include "ScrDev.H" #include "EVENT.H" #include "ANIM.H" #include "Direct.H" #include "panics.h" #include "backedupwindow.h" #include "wstypes.h" #include "offscreenbitmap.h" CWsWindow* CWsWindow::iAccessListRecentEnd = 0; CWsWindow* CWsWindow::iAccessListOldestEnd = 0; CWsWindow::CWsWindow(CWsClient* aOwner,WH_HANDLES aType, CScreen* aScreen) : CWsWindowBase(aOwner,aType,aScreen), iFlags(EFlagHidden), iDSAs(_FOFF(CWsDirectScreenAccess,iMultipleDSALink)) { } CWsWindow::~CWsWindow() { iFadableRegion.Close(); } void CWsWindow::Construct() { InsertIntoAccessListOldestEnd(); } void CWsWindow::Shutdown() { TWindowServerEvent::NotifyDrawer(TWservCrEvent(TWservCrEvent::EWindowClosing, 0, 0, this)); RemoveFromAccessList(); CWsAnim::WindowClosing(iAnimList); // Destroy any animated objects attached to this window iVisibleRegion.Close(); iScheduledRegion.Close(); AbortAllDSAs(); CWsWindowBase::Shutdown(); SetPointerCursor(NULL); delete iRedraw; } // // Region and invalid area functions // // TRect CWsWindow::FullRect() const { return(TRect(iOrigin,iRel.Size())); } // // Normal regions // // void CWsWindow::SetNonFading(TBool aNonFade) { if (aNonFade) iFlags|=EFlagNonFadingWindow; else iFlags&=(~EFlagNonFadingWindow); } TPoint CWsWindow::InquireOffset(TUint32 aHandle) const { CWsWindowBase *win2; iWsOwner->HandleToWindow(aHandle,&win2); return(iOrigin-win2->Origin()); } TDisplayMode CWsWindow::DisplayMode() const { return iScreen->DisplayMode(); } void CWsWindow::StatusDump(TDes &aBuf) { _LIT(KStatusString1,"CWsWindow[0x%x]RWindow[0x%x,%d],Pos(%d,%d),Size(%d,%d)"); _LIT(KStatusString3,",Mode=%d"); _LIT(KStatusInvisible,",Inv"); aBuf.AppendFormat(KStatusString1,this,iClientHandle,LogHandle(),iRel.iTl.iX,iRel.iTl.iY,Size().iWidth,Size().iHeight); aBuf.AppendFormat(KStatusString3,(TInt)iScreen->DisplayMode()); if (!IsVisible()) aBuf.Append(KStatusInvisible); } TDblQue<TPointerKeyList> *CWsWindow::PointerKeyList() const { return(NULL); } void CWsWindow::AbortAllDSAs() { iScreen->AbortDSAs(RDirectScreenAccess::ETerminateRegion,iDSAs); } void CWsWindow::PossibleVisibilityChangedEvent(TBool aForceSend) { // notify plugin // TWservCrEvent crEvent(TWservCrEvent::EWindowVisibilityChanged, HasBeenDrawnToScreen(), IsVisible()? &iVisibleRegion : NULL, this); TWindowServerEvent::NotifyDrawer(crEvent); if (!(iFlags & EFlagGeneratesVisibilityEvents)) return; if (!IsVisible()) { goto notvisible; } if (iVisibleRegion.Count() == 0) { goto notvisible; } {// braces here to avoid gccxml error TInt visibleArea = 0; TInt count = iVisibleRegion.Count(); TInt ii; for (ii = 0; ii < count; ii++) { visibleArea+= iVisibleRegion[ii].Width() * iVisibleRegion[ii].Height(); } const TRegion* baseRegion = (static_cast<CWsClientWindow*>(this))->BaseArea(); TInt baseArea = 0; count = baseRegion->Count(); for (ii = 0; ii < count; ii++) { const TRect& rect = (*baseRegion)[ii]; baseArea+= rect.Width() * rect.Height(); } if (visibleArea == baseArea) { goto fullyvisible; } else { goto partiallyvisible; } } fullyvisible: if (aForceSend || !(iFlags & EFlagNotCantBeSeen) || !(iFlags & EFlagCanBeSeen)) { iFlags |= (EFlagCanBeSeen | EFlagNotCantBeSeen); TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::EPartiallyVisible | TWsVisibilityChangedEvent::EFullyVisible); // we have to set EPartiallyVisible too for compatibility reasons } return; partiallyvisible: if (aForceSend || !(iFlags & EFlagCanBeSeen) || (iFlags & EFlagNotCantBeSeen)) { iFlags |= EFlagCanBeSeen; iFlags &= ~EFlagNotCantBeSeen; TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::EPartiallyVisible); } return; notvisible: if (aForceSend || (iFlags & EFlagCanBeSeen) || (iFlags & EFlagNotCantBeSeen)) { iFlags &= ~(EFlagCanBeSeen | EFlagNotCantBeSeen); TWindowServerEvent::SendVisibilityChangedEvents(this, TWsVisibilityChangedEvent::ENotVisible); } return; } TPoint CWsWindow::Origin() const { return iOrigin; } TRect CWsWindow::AbsRect() const { return iAbs; } TSize CWsWindow::Size() const { return iRel.Size(); } TBool CWsWindow::SetScheduledRegion(const RWsRegion& aRegion) { iScheduledRegion.Copy(aRegion); return !iScheduledRegion.CheckError(); } void CWsWindow::ClearScheduledRegion() { iScheduledRegion.Clear(); } void CWsWindow::SetFadeBehind(TBool aFade) { if (aFade != ((iFlags & EFlagFadeBehind) != 0)) { iFlags ^= EFlagFadeBehind; } } void CWsWindow::FocusChanged(TBool aNewFocusState) { TRAPD(err,FocusChangedL(aNewFocusState)); if (err!=KErrNone) OwnerPanic(EWservPanicAnimLeave); } void CWsWindow::FocusChangedL(TBool aNewFocusState) { for (CWsAnim * anim = iAnimList; anim; anim = anim->Next()) { anim->FocusChanged(aNewFocusState); } } // Moves a window to the recent end of the accessed list void CWsWindow::Accessed() { WS_ASSERT_DEBUG(iAccessListRecentEnd && iAccessListOldestEnd, EWsPanicAccessList); RemoveFromAccessList(); InsertIntoAccessListRecentEnd(); } void CWsWindow::InsertIntoAccessListOldestEnd() { iAccessListPrev = 0; iAccessListNext = iAccessListOldestEnd; if (iAccessListNext) iAccessListNext->iAccessListPrev = this; iAccessListOldestEnd = this; if (!iAccessListRecentEnd) iAccessListRecentEnd = this; } void CWsWindow::InsertIntoAccessListRecentEnd() { iAccessListNext = 0; iAccessListPrev = iAccessListRecentEnd; if (iAccessListPrev) iAccessListPrev->iAccessListNext = this; iAccessListRecentEnd = this; if (!iAccessListOldestEnd) iAccessListOldestEnd = this; } void CWsWindow::RemoveFromAccessList() { if (iAccessListOldestEnd == this) iAccessListOldestEnd = iAccessListNext; if (iAccessListRecentEnd == this) iAccessListRecentEnd = iAccessListPrev; if (iAccessListPrev) iAccessListPrev->iAccessListNext = iAccessListNext; if (iAccessListNext) iAccessListNext->iAccessListPrev = iAccessListPrev; } TBool CWsWindow::ReleaseMemory(MWsMemoryRelease::TMemoryReleaseLevel aLevel) { for (CWsWindow * access = iAccessListOldestEnd; access; access = access->iAccessListNext) { if(access->Redraw()) { if (access->Redraw()->ReleaseMemory(aLevel)) return ETrue; } } return EFalse; } const TRegion& CWsWindow::VisibleRegion() const { return(iVisibleRegion); } TBool CWsWindow::IsDSAHost() const { TBool res = EFalse; if ( !iDSAs.IsEmpty() ) { TSglQueIter<CWsDirectScreenAccess> iter( (TSglQueBase&)iDSAs ); iter.SetToFirst(); CWsDirectScreenAccess* dsa; while ( (dsa = iter++) != NULL && !res ) { res = dsa->IsVisible() || dsa->IsSyncTimeoutPending(); } } return res; } void CWsWindow::ResetVisibleRegion() { if (!iVisibleRegion.IsEmpty()) { iVisibleRegion.Clear(); } iFadableRegion.Clear(); } void CWsWindow::SetVisibleRegion(const TRegion& aNewRegion, const TRegion* aTop, TRegion& aNewFadableRegion) { STACK_REGION difference; TBool diffs = EFalse; difference.Copy(iVisibleRegion); difference.SubRegion(aNewRegion); if (!difference.IsEmpty()) { diffs = ETrue; if (IsTranslucent()) { // Andy - If this is a client window (what else could it be) we can also subtract the // user defined opaque region before doing this: iScreen->AddRedrawRegion(difference, EFalse); } } difference.Copy(aNewRegion); if (HasBeenDrawnToScreen()) { difference.SubRegion(iVisibleRegion); } if (!difference.IsEmpty()) { diffs = ETrue; STACK_REGION topDiff; topDiff.Copy(difference); WS_ASSERT_DEBUG(aTop,EWsPanicRegion); topDiff.Intersect(*aTop); difference.SubRegion(topDiff); iScreen->AddRedrawRegion(topDiff, EFalse, ERedrawTopOnly); iScreen->AddRedrawRegion(difference, EFalse, ERedrawAll); topDiff.Close(); } difference.Close(); AbortDsaIfRequired(aNewRegion, aTop); if (diffs) { ResetVisibleRegion(); iVisibleRegion.Copy(aNewRegion); PossibleVisibilityChangedEvent(EFalse); } iFadableRegion.Copy( aNewFadableRegion ); // Just because the visible region (screen coordinates) didn't change doesn't // mean the invalid region (window coordinates) didn't change, so we always call this. iRedraw->VisibleRegionChange(); } void CWsWindow::ClearVisibleRegion() { AbortAllDSAs(); iScreen->AddRedrawRegion(VisibleRegion(), EFalse); ResetVisibleRegion(); PossibleVisibilityChangedEvent(EFalse); iFlags &= ~EFlagDrawnToScreen; } void CWsWindow::AbortDsaIfRequired(const TRegion& aNewRegion, const TRegion* aTop) { if (!iDSAs.IsEmpty()) { // If the top visible region of this window has changed, DSA clients may need // to be sent a DSA abort, as they may be drawing to a different region STACK_REGION newTopVisible; newTopVisible.Copy(aNewRegion); // new visible region if (aTop!=NULL) { newTopVisible.Intersect(*aTop); // area of new visible region not obscured by any other opaque or translucent windows } // Build a list of DSA clients that need to be sent a DSA abort TSglQue<CWsDirectScreenAccess> dsaList(_FOFF(CWsDirectScreenAccess,iAbortLink)); TSglQueIter<CWsDirectScreenAccess> iter(iDSAs); CWsDirectScreenAccess* dsa; while ((dsa=iter++)!=NULL) { if (dsa->IsAbortRequired(newTopVisible)) { dsaList.AddLast(*dsa); } } if (!dsaList.IsEmpty()) { iScreen->AbortDSAs(RDirectScreenAccess::ETerminateRegion, dsaList); } newTopVisible.Close(); } } const TRegion* CWsWindow::VisibleRegionIfValid() const { return iVisibleRegion.CheckError() ? NULL : &iVisibleRegion; } TBool CWsWindow::ReadyToDraw() const { return iRedraw->ReadyToDraw(); } /** This function draws the region specified Andy - I would be happier if no region was specified here - the GC should incorporate that information */ void CWsWindow::Render(CFbsBitGc * aGc, const TRegion& aRegion) { WS_ASSERT_DEBUG(IsVisible() || (WinType() == EWinTypeRoot), EWsPanicScheduledRedraw); Accessed(); iFlags |= EFlagDrawnToScreen; iRedraw->PreDrawWindow(aGc, aRegion); iRedraw->DrawWindow(); iRedraw->PostDrawWindow(aGc); } void CWsWindow::SetNextScheduled(CWsWindow * aWin) { iNextScheduled = aWin; } CWsWindow * CWsWindow::NextScheduled() const { return iNextScheduled; } void CWsWindow::AddSprite(CWsSpriteBase * aSprite) { aSprite->SetNext(iSpriteList); iSpriteList = aSprite; } void CWsWindow::RemoveSprite(CWsSpriteBase * aSprite) { if (aSprite == iSpriteList) { iSpriteList = aSprite->Next(); } else { for (CWsSpriteBase * sprite = iSpriteList; sprite; sprite = sprite->Next()) { if (sprite->Next() == aSprite) { sprite->SetNext(aSprite->Next()); } } } aSprite->SetNext(0); } void CWsWindow::DeactivateAllSprites() { CWsSpriteBase * current = iSpriteList; while (current) { CWsSpriteBase * next = current->Next(); current->Deactivate(); current = next; } } void CWsWindow::ClipRectToViewport(TRect& aRect) const { const CWsWindowBase * win = this; while (win) { if (win->WinType() != EWinTypeGroup) { aRect.Intersection(win->AbsRect()); } win = win->BaseParent(); } } const TRegion& CWsWindow::FadableRegion() const { return iFadableRegion; } /** MWsWindow */ MWsWindow * CWsWindow::FindChildByHandle(TUint32 aHandle) { TWalkWindowTreeFindByHandle wwt(aHandle); WalkWindowTree(wwt, EWalkChildren); return wwt.Found(); } TUint32 CWsWindow::Handle() const { return ClientHandle(); } MWsScreen * CWsWindow::WsScreen() const { return iScreen; } TInt CWsWindow::OrdinalPriority() const { return iOrdinalPriority; }