diff --git a/mozilla/layout/base/nsDisplayList.h b/mozilla/layout/base/nsDisplayList.h index 41a32623d39..1b9c9e03c8a 100644 --- a/mozilla/layout/base/nsDisplayList.h +++ b/mozilla/layout/base/nsDisplayList.h @@ -441,6 +441,17 @@ public: return NS_OK; } + /** + * Append a new item to the bottom of the list. If the item is null we return + * NS_ERROR_OUT_OF_MEMORY. The intended usage is AppendNewToBottom(new ...); + */ + nsresult AppendNewToBottom(nsDisplayItem* aItem) { + if (!aItem) + return NS_ERROR_OUT_OF_MEMORY; + AppendToBottom(aItem); + return NS_OK; + } + /** * Append a new item to the bottom of the list. The item must be non-null * and not already in a list. diff --git a/mozilla/layout/base/nsLayoutUtils.cpp b/mozilla/layout/base/nsLayoutUtils.cpp index 351cd6e12c6..ba0f1256452 100644 --- a/mozilla/layout/base/nsLayoutUtils.cpp +++ b/mozilla/layout/base/nsLayoutUtils.cpp @@ -611,9 +611,42 @@ nsLayoutUtils::GetFrameForPoint(nsIFrame* aFrame, nsPoint aPt) return result; } +/** + * A simple display item that just renders a solid color across the entire + * visible area. + */ +MOZ_DECL_CTOR_COUNTER(nsDisplaySolidColor) +class nsDisplaySolidColor : public nsDisplayItem { +public: + nsDisplaySolidColor(nsIFrame* aFrame, nscolor aColor) + : mFrame(aFrame), mColor(aColor) { + MOZ_COUNT_CTOR(nsDisplaySolidColor); + } +#ifdef NS_BUILD_REFCNT_LOGGING + virtual ~nsDisplaySolidColor() { + MOZ_COUNT_DTOR(nsDisplaySolidColor); + } +#endif + + virtual nsIFrame* GetUnderlyingFrame() { return mFrame; } + virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx, + const nsRect& aDirtyRect); + NS_DISPLAY_DECL_NAME("SolidColor") +private: + nsIFrame* mFrame; + nscolor mColor; +}; + +void nsDisplaySolidColor::Paint(nsDisplayListBuilder* aBuilder, + nsIRenderingContext* aCtx, const nsRect& aDirtyRect) +{ + aCtx->SetColor(mColor); + aCtx->FillRect(aDirtyRect); +} + nsresult nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFrame, - const nsRegion& aDirtyRegion) + const nsRegion& aDirtyRegion, nscolor aBackground) { nsDisplayListBuilder builder(aFrame, PR_FALSE); nsDisplayList list; @@ -622,6 +655,16 @@ nsLayoutUtils::PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFra aFrame->BuildDisplayListForStackingContext(&builder, dirtyRect, &list); NS_ENSURE_SUCCESS(rv, rv); + if (NS_GET_A(aBackground) > 0) { + // Fill the visible area with a background color. In the common case, + // the visible area is entirely covered by the background of the root + // document (at least!) so this will be removed by the optimizer. In some + // cases we might not have a root frame, so this will prevent garbage + // from being drawn. + rv = list.AppendNewToBottom(new (&builder) nsDisplaySolidColor(aFrame, aBackground)); + NS_ENSURE_SUCCESS(rv, rv); + } + #ifdef DEBUG if (gDumpPaintList) { fprintf(stderr, "Painting --- before optimization (dirty %d,%d,%d,%d):\n", diff --git a/mozilla/layout/base/nsLayoutUtils.h b/mozilla/layout/base/nsLayoutUtils.h index 24f462a929b..5d100e88f79 100644 --- a/mozilla/layout/base/nsLayoutUtils.h +++ b/mozilla/layout/base/nsLayoutUtils.h @@ -329,9 +329,11 @@ public: * is the origin of aFrame * @param aDirtyRegion the region that must be painted, in the coordinates * of aFrame + * @param aBackground paint the dirty area with this color before drawing + * the actual content; pass NS_RGBA(0,0,0,0) to draw no background */ static nsresult PaintFrame(nsIRenderingContext* aRenderingContext, nsIFrame* aFrame, - const nsRegion& aDirtyRegion); + const nsRegion& aDirtyRegion, nscolor aBackground); /** * @param aRootFrame the root frame of the tree to be displayed diff --git a/mozilla/layout/base/nsPresShell.cpp b/mozilla/layout/base/nsPresShell.cpp index df5794a75b0..8c9f89d84dc 100644 --- a/mozilla/layout/base/nsPresShell.cpp +++ b/mozilla/layout/base/nsPresShell.cpp @@ -5498,28 +5498,45 @@ PresShell::Paint(nsIView* aView, NS_ASSERTION(!(nsnull == aView), "null view"); frame = NS_STATIC_CAST(nsIFrame*, aView->GetClientData()); - - if (nsnull != frame) - { - if (mCaret) - mCaret->EraseCaret(); + nscolor backgroundColor; + mViewManager->GetDefaultBackgroundColor(&backgroundColor); + nsIView* rootView; + mViewManager->GetRootView(rootView); + if (!rootView->GetParent() && rootView->HasWidget()) { + PRBool widgetIsTranslucent; + rootView->GetWidget()->GetWindowTranslucency(widgetIsTranslucent); + if (widgetIsTranslucent) { + backgroundColor = NS_RGBA(0,0,0,0); + } + } + + if (!frame) { + if (NS_GET_A(backgroundColor) > 0) { + aRenderingContext->SetColor(backgroundColor); + aRenderingContext->FillRect(aDirtyRegion.GetBounds()); + } + return NS_OK; + } + + if (mCaret) + mCaret->EraseCaret(); - nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion); + nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion, + backgroundColor); #ifdef NS_DEBUG - // Draw a border around the frame - if (nsIFrameDebug::GetShowFrameBorders()) { - nsRect r = frame->GetRect(); - aRenderingContext->SetColor(NS_RGB(0,0,255)); - aRenderingContext->DrawRect(0, 0, r.width, r.height); - } - // Draw a border around the current event target - if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) && (aView == mCurrentTargetView)) { - aRenderingContext->SetColor(NS_RGB(128,0,128)); - aRenderingContext->DrawRect(mCurrentTargetRect.x, mCurrentTargetRect.y, mCurrentTargetRect.width, mCurrentTargetRect.height); - } -#endif + // Draw a border around the frame + if (nsIFrameDebug::GetShowFrameBorders()) { + nsRect r = frame->GetRect(); + aRenderingContext->SetColor(NS_RGB(0,0,255)); + aRenderingContext->DrawRect(0, 0, r.width, r.height); } + // Draw a border around the current event target + if ((nsIFrameDebug::GetShowEventTargetFrameBorder()) && (aView == mCurrentTargetView)) { + aRenderingContext->SetColor(NS_RGB(128,0,128)); + aRenderingContext->DrawRect(mCurrentTargetRect.x, mCurrentTargetRect.y, mCurrentTargetRect.width, mCurrentTargetRect.height); + } +#endif return rv; }