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::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); } }
//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(); }