From d2971a102c05d50820e2717075c6d59a75e1a635 Mon Sep 17 00:00:00 2001 From: Zack Weinberg Date: Sat, 13 Dec 2008 17:07:08 +0100 Subject: [PATCH] Bug 467459: make sure PresShell::Paint() uses an opaque color for the backstop; r+sr=roc --- layout/base/nsPresShell.cpp | 61 ++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 24 deletions(-) diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index ce0945d5f50e..48a8d99991fc 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5409,41 +5409,54 @@ PresShell::Paint(nsIView* aView, const nsRegion& aDirtyRegion) { AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Paint); - nsIFrame* frame; - nsresult rv = NS_OK; - if (mIsDestroying) { - NS_ASSERTION(PR_FALSE, "A paint message was dispatched to a destroyed PresShell"); - return NS_OK; - } + NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell"); + NS_ASSERTION(aView, "null view"); - NS_ASSERTION(!(nsnull == aView), "null view"); + // Compute the backstop color for the view. This color must be + // totally transparent if the view is within a glass or transparent + // widget; otherwise, we compose all the view managers' default + // background colors in order to get something completely opaque. + // Nested view managers might not have an opaque default, but the + // root view manager must. See bug 467459. - frame = static_cast(aView->GetClientData()); + PRBool needTransparency = PR_FALSE; + nsIViewManager *lastMgr = mViewManager; nscolor backgroundColor; - mViewManager->GetDefaultBackgroundColor(&backgroundColor); + lastMgr->GetDefaultBackgroundColor(&backgroundColor); + for (nsIView *view = aView; view; view = view->GetParent()) { - if (view->HasWidget()) { - // Both glass and transparent windows need the transparent bg color - if (eTransparencyOpaque != view->GetWidget()->GetTransparencyMode()) { - backgroundColor = NS_RGBA(0,0,0,0); - break; + if (view->HasWidget() && + view->GetWidget()->GetTransparencyMode() != eTransparencyOpaque) { + backgroundColor = NS_RGBA(0,0,0,0); + needTransparency = PR_TRUE; + break; + } + if (NS_GET_A(backgroundColor) < 255) { + nsIViewManager *thisMgr = view->GetViewManager(); + NS_ASSERTION(thisMgr, "view without view manager"); + if (lastMgr != thisMgr) { + nscolor underColor; + thisMgr->GetDefaultBackgroundColor(&underColor); + backgroundColor = NS_ComposeColors(underColor, backgroundColor); + lastMgr = thisMgr; } } } + + NS_ASSERTION(needTransparency || NS_GET_A(backgroundColor) == 255, + "root view manager's default background isn't opaque"); - if (!frame) { - if (NS_GET_A(backgroundColor) > 0) { - aRenderingContext->SetColor(backgroundColor); - aRenderingContext->FillRect(aDirtyRegion.GetBounds()); - } - return NS_OK; + nsIFrame* frame = static_cast(aView->GetClientData()); + if (frame) { + nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion, + backgroundColor); + } else if (NS_GET_A(backgroundColor) > 0) { + aRenderingContext->SetColor(backgroundColor); + aRenderingContext->FillRect(aDirtyRegion.GetBounds()); } - nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion, - backgroundColor); - - return rv; + return NS_OK; } nsIFrame*