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 CWsBackedUpWindow::Scroll(const TRect &aClipRect, const TPoint &aOffset,const TRect &aRect) { TRect winBorder=TRect(iWsWin->Size()); TRect clipRect=aClipRect; TRect srcRect = aRect; clipRect.Intersection(winBorder); if (!clipRect.IsEmpty()) { // If we have to do something (a visible part will change) srcRect.Intersection(clipRect); STACK_REGION regionToClear; regionToClear.AddRect(aRect); regionToClear.SubRect(srcRect); regionToClear.Offset(aOffset); ActivateGc(); iBitGc->SetClippingRect(clipRect); iBitGc->SetDrawMode(CGraphicsContext::EDrawModeWriteAlpha); iBitGc->CopyRect(aOffset,srcRect); for (TInt k=0;k<regionToClear.Count();k++) { iBitGc->Clear(regionToClear[k]); } iBitGc->SetClippingRect(winBorder); iBitGc->SetDrawMode(CGraphicsContext::EDrawModePEN); TRegionFix<1> fixRegion(iWsWin->AbsRect()); UpdateScreen(fixRegion); regionToClear.Close(); } }
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(); } }
/** This function selects the desired behaviour depending on whether the screen is run in CHANGETRACKING mode or not. @param aRegion in screen coordinates */ void CWsBackedUpWindow::UpdateScreen(const TRegion& aRegion) { if (Screen()->ChangeTracking()) { STACK_REGION region; region.Copy(aRegion); region.Offset(-WsWin()->Origin()); //convert to window coordinates MarkDirtyAndSchedule(region); region.Close(); } else { Screen()->AddRedrawRegion(aRegion); } }
void CWsSpriteBase::CalcRedrawRegion(const TRegion& aSourceRegion, TRegion& aTarget) const { aTarget.Copy(aSourceRegion); if (ClipSprite()) { TPoint origin(0,0); if(iWin) origin = iWin->Origin(); TRect rect(iBasePos + origin + iClipOffset, iClipSize); aTarget.ClipRect(rect); } aTarget.ClipRect(RootWindow()->Abs()); // Only need to draw if the region being redrawn overlaps the sprite const TRect spriteRect(Pos(), iSize); STACK_REGION spriteRegion; spriteRegion.AddRect(spriteRect); aTarget.Intersect(spriteRegion); spriteRegion.Close(); }
void CWsSpriteManager::DrawFloatingSprites(MWsGraphicsContext* aGc,const TRegion& aRegion) { if (iFloatingSprites.Count() == 0) return; //avoid sending events unless necessary for (TInt i = iFloatingSprites.Count() - 1; i >= 0 ; i--) { STACK_REGION redrawRegion; CWsSpriteBase* sprite = iFloatingSprites[i]; sprite->CalcRedrawRegion(aRegion, redrawRegion); if(redrawRegion.CheckError() || !redrawRegion.IsEmpty()) { if (sprite->IsFlashingEnabled() || sprite->IsDirty() || sprite->HasAnimation()) { AnnotateSpriteRedrawStart(*sprite, redrawRegion); if(sprite->HasAnimation()) { CWsAnim* anim = static_cast<CWsSprite*>(sprite)->iAnim; ASSERT(anim); TRAPD(err, anim->AnimateSpriteAnimL(sprite->Screen()->Now())); if(err!=KErrNone) { AnnotateSpriteRedrawEnd(*sprite); anim->Panic(EWservPanicAnimLeave); continue; } } aGc->Reset(); sprite->Redraw(aGc, redrawRegion); AnnotateSpriteRedrawEnd(*sprite); } } redrawRegion.Close(); } }
void CWsDirectScreenAccess::Request(TInt handle) { if (iStatus!=EDirectStatusNone) { if (iStatus==EDirectStatusCompleted) { iMsgQueue->Cancel(); } else { iWsOwner->PPanic(EWservPanicDirectMisuse); } } iWsOwner->HandleToClientWindow(handle,&iWin); iScreen=iWin->Screen(); STACK_REGION region; iWin->GenerateTopRegion(region); const TInt regionCount=region.Count(); region.Close(); SetReply(regionCount); iStatus=EDirectStatusInitialising; }
//This function sets up the quick fadable region. //It removes anything that cannot be quick faded, and schedules it to be drawn in the normal fashion. void CWsWindow::SetFadeableRegion(const TRegion& aNewFadableRegion, const TRegion& aTop) { WS_ASSERT_DEBUG(iScreen, EWsPanicNoScreen); iFadableRegion.Copy(aNewFadableRegion); //Try to figure out if any part of iFadableRegion can be quick faded (i.e. fading applied to //the screen without first having to redraw all visible windows intersecting the region). if ( !iFadableRegion.IsEmpty() && iScreen->IsQuickFadeScheduled(this) ) { if (IsTranslucent()) { //If a window is semitransparent, then we cannot apply a quickfade to it if //the window below is faded too. iScreen->AddRedrawRegion(iVisibleRegion, EFalse, ERedrawAll); iScreen->RemoveFromQuickFadeList(this); } else { iQuickFadeRegion.Intersection(iFadableRegion, aTop); //Remove any regions not possible to quick fade from iQuickFadeRegion and //schedule these regions for full back-front rendering instead. STACK_REGION nonQuickFadableRegion; for(CWsSpriteBase * sprite = iSpriteList; sprite; sprite = sprite->Next()) { nonQuickFadableRegion.AddRect(sprite->Rect()); } for(CWsAnim * anim = iAnimList; anim; anim = anim->Next()) { nonQuickFadableRegion.AddRect(anim->BestRect()); } RWsTextCursor* const cursor = CWsTop::CurrentTextCursor(); if( cursor && (cursor->Window()==this) && cursor->IsStandardCursorActive() ) { nonQuickFadableRegion.AddRect(cursor->Rect()); } //Any regions scheduled for fading but partly or fully covered by transparent windows above them STACK_REGION coveredFadableRegion; coveredFadableRegion.Copy(iFadableRegion); coveredFadableRegion.SubRegion(iQuickFadeRegion); nonQuickFadableRegion.Union(coveredFadableRegion); coveredFadableRegion.Close(); nonQuickFadableRegion.Tidy(); //Remove any regions not possible to quick fade from iQuickFadeRegion iQuickFadeRegion.SubRegion(nonQuickFadableRegion); if (!nonQuickFadableRegion.CheckError()) { //Schedule normal drawing (full back to front rendering) for the region not possible to quick fade if (!nonQuickFadableRegion.IsEmpty()) { iScreen->AddRedrawRegion(nonQuickFadableRegion, EFalse, ERedrawAll); } } else { //Schedule normal drawing for the whole iVisibleRegion if the calculations are broken iScreen->AddRedrawRegion(iVisibleRegion, EFalse, ERedrawAll); } nonQuickFadableRegion.Close(); } } else { iQuickFadeRegion.Reset(); } }
void CWsWindow::SetVisibleRegion(const TRegion& aNewRegion, const TRegion* aTop) { WS_ASSERT_DEBUG(iScreen, EWsPanicNoScreen); STACK_REGION difference; TBool diffs = EFalse; difference.Copy(iVisibleRegion); difference.SubRegion(aNewRegion); if (!difference.IsEmpty()) { diffs = ETrue; if (IsTranslucent()) { iScreen->AddRedrawRegion(difference, EFalse); } } difference.Copy(aNewRegion); if (HasBeenDrawnToScreen()) { difference.SubRegion(iVisibleRegion); } if (!difference.IsEmpty()) { diffs = ETrue; if(!iScreen->ChangeTracking()) { //the following code will restart animations 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(); } else if(IsVisible()) { RestartAnimations(aNewRegion); } } difference.Close(); AbortDsaIfRequired(aNewRegion, aTop); if (diffs) { ResetVisibleRegion(); iVisibleRegion.Copy(aNewRegion); PossibleVisibilityChangedEvent(EFalse); if (Redraw()->HasElement()) { WS_ASSERT_DEBUG(WinType()==EWinTypeClient,EWsPanicWindowType); if (WinType()==EWinTypeClient) { iScreen->WindowElements().SetVisibleRegion(*static_cast<CWsClientWindow*>(this)); } } } // 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(); }