Bug 478079 - Kill nsViewManager::DefaultRefresh, and move the cached canvas background to the pres shell; r+sr=roc
authorZack Weinberg <zweinberg@mozilla.com>
Mon, 23 Feb 2009 02:10:23 +0100
changeset 25385 c67bc280f52fe1a247c539e9a66c485c5efee405
parent 25384 6410c3cdd64fbb18fbc4a2c750f9a666847e1fe7
child 25386 e648702fc8c327e57aa61352031564bbf08d778c
push id5527
push usersgautherie.bz@free.fr
push dateMon, 23 Feb 2009 01:22:10 +0000
treeherdermozilla-central@f6cdd2d6a9ea [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs478079
milestone1.9.2a1pre
Bug 478079 - Kill nsViewManager::DefaultRefresh, and move the cached canvas background to the pres shell; r+sr=roc
docshell/base/nsDocShell.cpp
layout/base/nsDocumentViewer.cpp
layout/base/nsIPresShell.h
layout/base/nsPresShell.cpp
view/public/nsIViewManager.h
view/public/nsIViewObserver.h
view/src/nsViewManager.cpp
view/src/nsViewManager.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -6488,42 +6488,34 @@ nsDocShell::SetupNewViewer(nsIContentVie
             }
 
             if (ourWindow == focusedWindow || isSubWindow)
               focusController->ResetElementFocus();
         }
     }
 
     nscolor bgcolor = NS_RGBA(0, 0, 0, 0);
-    PRBool bgSet = PR_FALSE;
-
     // Ensure that the content viewer is destroyed *after* the GC - bug 71515
     nsCOMPtr<nsIContentViewer> kungfuDeathGrip = mContentViewer;
     if (mContentViewer) {
         // Stop any activity that may be happening in the old document before
         // releasing it...
         mContentViewer->Stop();
 
-        // Try to extract the default background color from the old
-        // view manager, so we can use it for the next document.
+        // Try to extract the canvas background color from the old
+        // presentation shell, so we can use it for the next document.
         nsCOMPtr<nsIDocumentViewer> docviewer =
         do_QueryInterface(mContentViewer);
 
         if (docviewer) {
             nsCOMPtr<nsIPresShell> shell;
             docviewer->GetPresShell(getter_AddRefs(shell));
 
             if (shell) {
-                nsIViewManager* vm = shell->GetViewManager();
-
-                if (vm) {
-                    vm->GetDefaultBackgroundColor(&bgcolor);
-                    // If the background color is not known, don't propagate it.
-                    bgSet = NS_GET_A(bgcolor) != 0;
-                }
+                bgcolor = shell->GetCanvasBackground();
             }
         }
 
         mContentViewer->Close(mSavingOldViewer ? mOSHE.get() : nsnull);
         aNewViewer->SetPreviousViewer(mContentViewer);
 
         mContentViewer = nsnull;
     }
@@ -6574,33 +6566,28 @@ nsDocShell::SetupNewViewer(nsIContentVie
        document, mContentViewer->Init finally puts a reference to that
        document into the DOM window, which prevents an infinite recursion
        attempting to lazily create the document as focus is unsuppressed
        (bug 110856). */
     if (focusController)
         focusController->SetSuppressFocus(PR_FALSE,
                                           "Win32-Only Link Traversal Issue");
 
-    if (bgSet && widget) {
-        // Stuff the bgcolor from the last view manager into the new
-        // view manager. This improves page load continuity.
-        nsCOMPtr<nsIDocumentViewer> docviewer =
-            do_QueryInterface(mContentViewer);
-
-        if (docviewer) {
-            nsCOMPtr<nsIPresShell> shell;
-            docviewer->GetPresShell(getter_AddRefs(shell));
-
-            if (shell) {
-                nsIViewManager* vm = shell->GetViewManager();
-
-                if (vm) {
-                    vm->SetDefaultBackgroundColor(bgcolor);
-                }
-            }
+
+    // Stuff the bgcolor from the old pres shell into the new
+    // pres shell. This improves page load continuity.
+    nsCOMPtr<nsIDocumentViewer> docviewer =
+        do_QueryInterface(mContentViewer);
+
+    if (docviewer) {
+        nsCOMPtr<nsIPresShell> shell;
+        docviewer->GetPresShell(getter_AddRefs(shell));
+
+        if (shell) {
+            shell->SetCanvasBackground(bgcolor);
         }
     }
 
 // XXX: It looks like the LayoutState gets restored again in Embed()
 //      right after the call to SetupNewViewer(...)
 
     // We don't show the mContentViewer yet, since we want to draw the old page
     // until we have enough of the new page to show.  Just return with the new
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -717,22 +717,16 @@ DocumentViewerImpl::InitPresentationStuf
   nscoord width = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel() * bounds.width;
   nscoord height = mPresContext->DeviceContext()->UnscaledAppUnitsPerDevPixel() * bounds.height;
 
   mViewManager->DisableRefresh();
   mViewManager->SetWindowDimensions(width, height);
   mPresContext->SetTextZoom(mTextZoom);
   mPresContext->SetFullZoom(mPageZoom);
 
-  // Setup default view manager background color
-
-  // This may be overridden by the docshell with the background color
-  // for the last document loaded into the docshell
-  mViewManager->SetDefaultBackgroundColor(mPresContext->DefaultBackgroundColor());
-
   if (aDoInitialReflow) {
     nsCOMPtr<nsIHTMLDocument> htmlDoc = do_QueryInterface(mDocument);
     if (htmlDoc) {
       nsCOMPtr<nsIDOMHTMLFrameSetElement> frameset =
         do_QueryInterface(mDocument->GetRootContent());
       htmlDoc->SetIsFrameset(frameset != nsnull);
     }
 
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -96,20 +96,20 @@ template<class E> class nsCOMArray;
 class nsWeakFrame;
 class nsIScrollableFrame;
 class gfxASurface;
 class gfxContext;
 
 typedef short SelectionType;
 typedef PRUint32 nsFrameState;
 
-// 780d34b0-00c3-4bbd-b57d-c600aaf53613
-#define NS_IPRESSHELL_IID \
-{ 0x780d34b0, 0xc3, 0x4bbd, \
-  { 0xb5, 0x7d, 0xc6, 0x0, 0xaa, 0xf5, 0x36, 0x13 } }
+// 445e6184-5e7e-4a9b-97f7-c9391e6773d2
+#define NS_IPRESSHELL_IID     \
+{ 0x445e6184, 0x5e7e, 0x4a9b, \
+  { 0x97, 0xf7, 0xc9, 0x39, 0x1e, 0x67, 0x73, 0xd2 } }
 
 // Constants for ScrollContentIntoView() function
 #define NS_PRESSHELL_SCROLL_TOP      0
 #define NS_PRESSHELL_SCROLL_BOTTOM   100
 #define NS_PRESSHELL_SCROLL_LEFT     0
 #define NS_PRESSHELL_SCROLL_RIGHT    100
 #define NS_PRESSHELL_SCROLL_CENTER   50
 #define NS_PRESSHELL_SCROLL_ANYWHERE -1
@@ -771,21 +771,30 @@ public:
 #ifdef NS_DEBUG
   nsIFrame* GetDrawEventTargetFrame() { return mDrawEventTargetFrame; }
 #endif
 
   /**
    * Stop or restart non synthetic test mouse event handling on *all*
    * presShells.
    *
-   * @param aDisable  If true, disable all non synthetic test mouse events on all
-   * presShells.  Otherwise, enable them.
+   * @param aDisable If true, disable all non synthetic test mouse
+   * events on all presShells.  Otherwise, enable them.
    */
   NS_IMETHOD DisableNonTestMouseEvents(PRBool aDisable) = 0;
 
+  /* Record the background color of the most recently loaded canvas.
+   * This color is composited on top of the user's default background
+   * color whenever we need to provide an "ultimate" background color.
+   * See PresShell::Paint, PresShell::PaintDefaultBackground, and
+   * nsDocShell::SetupNewViewer; bug 476557 and other bugs mentioned there.
+   */
+  void SetCanvasBackground(nscolor aColor) { mCanvasBackgroundColor = aColor; }
+  nscolor GetCanvasBackground() { return mCanvasBackgroundColor; }
+
 protected:
   // IMPORTANT: The ownership implicit in the following member variables
   // has been explicitly checked.  If you add any members to this class,
   // please make the ownership explicit (pinkerton, scc).
 
   // these are the same Document and PresContext owned by the DocViewer.
   // we must share ownership.
   nsIDocument*              mDocument;      // [STRONG]
@@ -814,16 +823,19 @@ protected:
 #endif
 
   // Set to true when the accessibility service is being used to mirror
   // the dom/layout trees
   PRPackedBool              mIsAccessibilityActive;
 
   // A list of weak frames. This is a pointer to the last item in the list.
   nsWeakFrame*              mWeakFrames;
+
+  // Most recent canvas background color.
+  nscolor                   mCanvasBackgroundColor;
 };
 
 /**
  * Create a new empty presentation shell. Upon success, call Init
  * before attempting to use the shell.
  */
 nsresult
 NS_NewPresShell(nsIPresShell** aInstancePtrResult);
--- a/layout/base/nsPresShell.cpp
+++ b/layout/base/nsPresShell.cpp
@@ -896,16 +896,19 @@ public:
                                                         nsIntPoint& aPoint,
                                                         nsIntRect* aScreenRect);
 
   //nsIViewObserver interface
 
   NS_IMETHOD Paint(nsIView *aView,
                    nsIRenderingContext* aRenderingContext,
                    const nsRegion& aDirtyRegion);
+  NS_IMETHOD PaintDefaultBackground(nsIView *aView,
+                                    nsIRenderingContext* aRenderingContext,
+                                    const nsRect& aDirtyRect);
   NS_IMETHOD ComputeRepaintRegionForCopy(nsIView*      aRootView,
                                          nsIView*      aMovingView,
                                          nsPoint       aDelta,
                                          const nsRect& aCopyRect,
                                          nsRegion*     aRepaintRegion);
   NS_IMETHOD HandleEvent(nsIView*        aView,
                          nsGUIEvent*     aEvent,
                          nsEventStatus*  aEventStatus);
@@ -5372,78 +5375,74 @@ PresShell::Paint(nsIView*             aV
                  nsIRenderingContext* aRenderingContext,
                  const nsRegion&      aDirtyRegion)
 {
   AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Paint);
 
   NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
   NS_ASSERTION(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 it must be totally opaque.  The user's default
-  // background color as recorded in the prescontext is guaranteed to
-  // be opaque.
-
-  PRBool needTransparency = PR_FALSE;
-  nscolor backgroundColor = mPresContext->DefaultBackgroundColor();
-  for (nsIView *view = aView; view; view = view->GetParent()) {
-    if (view->HasWidget() &&
-        view->GetWidget()->GetTransparencyMode() != eTransparencyOpaque) {
-      needTransparency = PR_TRUE;
-      break;
-    }
-  }
-
-  // Check whether the view manager knows the background color of the
-  // canvas.  We set this below, and the docshell propagates it across
-  // page loads; using it in preference to the user's default color
-  // avoids screen flashing in between pages that use the same
-  // non-default background.
-  //
-  // If we're called at some weird moment when there is no view
-  // manager, default to transparent.
-  nscolor viewDefaultColor = NS_RGBA(0,0,0,0);
-  if (mViewManager)
-    mViewManager->GetDefaultBackgroundColor(&viewDefaultColor);
-
-  // If we don't have a frame tree yet, all we can do is paint the
-  // backstop colors.
-  nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
-  if (!frame) {
-    if (!needTransparency) {
-      backgroundColor = NS_ComposeColors(backgroundColor, viewDefaultColor);
-      aRenderingContext->SetColor(backgroundColor);
-      aRenderingContext->FillRect(aDirtyRegion.GetBounds());
-    }
-    return NS_OK;
-  }
-
-  // If we do have a frame tree, check whether it specifies a canvas
-  // background color yet.  If it does, use that instead of whatever
-  // color the view manager reported, and update the view manager
-  // accordingly.
+  // If we have a frame tree and it has style information that
+  // specifies the background color of the canvas, update our local
+  // cache of that color.
   nsIFrame* rootFrame = FrameConstructor()->GetRootElementStyleFrame();
   if (rootFrame) {
     const nsStyleBackground* bgStyle =
       nsCSSRendering::FindRootFrameBackground(rootFrame);
-    // XXX ideally we would set the view manager default to
-    // bgStyle->mBackgroundColor, and nsViewManager::DefaultRefresh would
-    // be able to cope with partial transparency.  But it can't so we can't.
-    // -- zwol 2009-02-11
-    backgroundColor = NS_ComposeColors(backgroundColor,
-                                       bgStyle->mBackgroundColor);
-    mViewManager->SetDefaultBackgroundColor(backgroundColor);
+    mCanvasBackgroundColor = bgStyle->mBackgroundColor;
+  }
+
+  // Compute the backstop color for the view.
+  nscolor bgcolor;
+  nsIWidget* widget = aView->GetNearestWidget(nsnull);
+  if (widget && widget->GetTransparencyMode() != eTransparencyOpaque) {
+    // Within a transparent widget, so the backstop color must be
+    // totally transparent.
+    bgcolor = NS_RGBA(0,0,0,0);
+  } else {
+    // Within an opaque widget (or no widget at all), so the backstop
+    // color must be totally opaque.  The cached canvas background
+    // color is not guaranteed to be opaque, but the user's default
+    // background as reported by the prescontext is.  Composing the
+    // former on top of the latter prevents window flashing in between
+    // pages that use the same non-default background.
+    bgcolor = NS_ComposeColors(mPresContext->DefaultBackgroundColor(),
+                               mCanvasBackgroundColor);
+  }
+
+  nsIFrame* frame = static_cast<nsIFrame*>(aView->GetClientData());
+  if (frame) {
+    nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion, bgcolor);
   } else {
-    backgroundColor = NS_ComposeColors(backgroundColor, viewDefaultColor);
-  }
-
-  nsLayoutUtils::PaintFrame(aRenderingContext, frame, aDirtyRegion,
-                            needTransparency ? NS_RGBA(0,0,0,0)
-                            : backgroundColor);
+    aRenderingContext->SetColor(bgcolor);
+    aRenderingContext->FillRect(aDirtyRegion.GetBounds());
+  }
+  return NS_OK;
+}
+
+NS_IMETHODIMP
+PresShell::PaintDefaultBackground(nsIView*             aView,
+                                  nsIRenderingContext* aRenderingContext,
+                                  const nsRect&       aDirtyRect)
+{
+  AUTO_LAYOUT_PHASE_ENTRY_POINT(GetPresContext(), Paint);
+
+  NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell");
+  NS_ASSERTION(aView, "null view");
+
+  // The view manager does not call this function if there is no
+  // widget or it is transparent.  We must not look at the frame tree,
+  // so all we have to use is the canvas default color as set above,
+  // or failing that, the user's default color.
+  
+  nscolor bgcolor = NS_ComposeColors(mPresContext->DefaultBackgroundColor(),
+                                     mCanvasBackgroundColor);
+
+  aRenderingContext->SetColor(bgcolor);
+  aRenderingContext->FillRect(aDirtyRect);
   return NS_OK;
 }
 
 nsIFrame*
 PresShell::GetCurrentEventFrame()
 {
   if (NS_UNLIKELY(mIsDestroying)) {
     return nsnull;
--- a/view/public/nsIViewManager.h
+++ b/view/public/nsIViewManager.h
@@ -35,17 +35,16 @@
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef nsIViewManager_h___
 #define nsIViewManager_h___
 
 #include "nscore.h"
 #include "nsIView.h"
-#include "nsColor.h"
 #include "nsEvent.h"
 #include "nsIRenderingContext.h"
 
 class nsIScrollableView;
 class nsIWidget;
 struct nsRect;
 class nsRegion;
 class nsIDeviceContext;
@@ -55,20 +54,20 @@ enum nsRectVisibility {
   nsRectVisibility_kVisible, 
   nsRectVisibility_kAboveViewport, 
   nsRectVisibility_kBelowViewport, 
   nsRectVisibility_kLeftOfViewport, 
   nsRectVisibility_kRightOfViewport, 
   nsRectVisibility_kZeroAreaRect
 }; 
 
-// de2a2d24-9753-4488-9fdc-dd0accb484f7
+// fa490965-ebd0-4203-836c-51c42d01fedb
 #define NS_IVIEWMANAGER_IID   \
-{ 0xde2a2d24, 0x9753, 0x4488, \
-  { 0x9f, 0xdc, 0xdd, 0x0a, 0xcc, 0xb4, 0x84, 0xf7 } }
+{ 0xfa490965, 0xebd0, 0x4203, \
+  { 0x83, 0x6c, 0x51, 0xc4, 0x2d, 0x01, 0xfe, 0xdb } }
 
 class nsIViewManager : public nsISupports
 {
 public:
 
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEWMANAGER_IID)
   /**
    * Initialize the ViewManager
@@ -437,32 +436,16 @@ public:
    * Indicate whether the viewmanager is currently painting
    *
    * @param aPainting PR_TRUE if the viewmanager is painting
    *                  PR_FALSE otherwise
    */
   NS_IMETHOD IsPainting(PRBool& aIsPainting)=0;
 
   /**
-   * Set the default background color that the view manager should use
-   * to paint otherwise unowned areas. If the color isn't known, just set
-   * it to zero (which means 'transparent' since the color is RGBA).
-   *
-   * @param aColor the default background color
-   */
-  NS_IMETHOD SetDefaultBackgroundColor(nscolor aColor)=0;
-
-  /**
-   * Retrieve the default background color.
-   *
-   * @param aColor the default background color
-   */
-  NS_IMETHOD GetDefaultBackgroundColor(nscolor* aColor)=0;
-
-  /**
    * Retrieve the time of the last user event. User events
    * include mouse and keyboard events. The viewmanager
    * saves the time of the last user event.
    *
    * @param aTime Last user event time in microseconds
    */
   NS_IMETHOD GetLastUserEventTime(PRUint32& aTime)=0;
 
--- a/view/public/nsIViewObserver.h
+++ b/view/public/nsIViewObserver.h
@@ -41,41 +41,61 @@
 #include "nsISupports.h"
 #include "nsEvent.h"
 #include "nsColor.h"
 #include "nsRect.h"
 
 class nsIRenderingContext;
 class nsGUIEvent;
 
-// cb03e6e3-9d14-4018-85f8-7d46af878c98
-#define NS_IVIEWOBSERVER_IID   \
-{ 0xcb03e6e3, 0x9d14, 0x4018, \
-  { 0x85, 0xf8, 0x7d, 0x46, 0xaf, 0x87, 0x8c, 0x98 } }
+// 52b3b616-23a9-4516-a8d3-452b4126eb2b
+#define NS_IVIEWOBSERVER_IID  \
+{ 0x52b3b616, 0x23a9, 0x4516, \
+  { 0xa8, 0xd3, 0x45, 0x2b, 0x41, 0x26, 0xeb, 0x2b } }
 
 class nsIViewObserver : public nsISupports
 {
 public:
   
   NS_DECLARE_STATIC_IID_ACCESSOR(NS_IVIEWOBSERVER_IID)
 
   /* called when the observer needs to paint. This paints the entire
    * frame subtree rooted at the view, including frame subtrees from
    * subdocuments.
    * @param aRenderingContext rendering context to paint to; the origin
    * of the view is painted at (0,0) in the rendering context's current
    * transform. For best results this should transform to pixel-aligned
    * coordinates.
-   * @param aDirtyRegion the region to be painted, in the coordinates of aRootView
+   * @param aDirtyRegion the region to be painted, in the coordinates of
+   * aRootView
    * @return error status
    */
   NS_IMETHOD Paint(nsIView*             aRootView,
                    nsIRenderingContext* aRenderingContext,
                    const nsRegion&      aDirtyRegion) = 0;
 
+  /* called when the observer needs to paint something, but the view
+   * tree is unstable, so it must *not* paint, or even examine, the
+   * frame subtree rooted at the view.  (It is, however, safe to inspect
+   * the state of the view itself, and any associated widget.)  The name
+   * illustrates the expected behavior, which is to paint some default
+   * background color over the dirty rect.
+   *
+   * @param aRenderingContext rendering context to paint to; the origin
+   * of the view is painted at (0,0) in the rendering context's current
+   * transform. For best results this should transform to pixel-aligned
+   * coordinates.
+   * @param aDirtyRect the rectangle to be painted, in the coordinates
+   * of aRootView
+   * @return error status
+   */
+  NS_IMETHOD PaintDefaultBackground(nsIView*             aRootView,
+                                    nsIRenderingContext* aRenderingContext,
+                                    const nsRect&        aDirtyRect) = 0;
+
   /**
    * @see nsLayoutUtils::ComputeRepaintRegionForCopy
    */
   NS_IMETHOD ComputeRepaintRegionForCopy(nsIView*      aRootView,
                                          nsIView*      aMovingView,
                                          nsPoint       aDelta,
                                          const nsRect& aCopyRect,
                                          nsRegion*     aRepaintRegion) = 0;
--- a/view/src/nsViewManager.cpp
+++ b/view/src/nsViewManager.cpp
@@ -175,17 +175,16 @@ nsViewManager::nsViewManager()
 
   gViewManagers->AppendElement(this);
 
   if (++mVMCount == 1) {
     NS_AddFocusSuppressorCallback(&nsViewManager::SuppressFocusEvents);
   }
   // NOTE:  we use a zeroing operator new, so all data members are
   // assumed to be cleared here.
-  mDefaultBackgroundColor = NS_RGBA(0, 0, 0, 0);
   mHasPendingUpdates = PR_FALSE;
   mRecursiveRefreshPending = PR_FALSE;
   mUpdateBatchFlags = 0;
 }
 
 nsViewManager::~nsViewManager()
 {
   if (mRootView) {
@@ -527,54 +526,16 @@ void nsViewManager::Refresh(nsView *aVie
   MOZ_TIMER_DEBUGLOG(("Stop: nsViewManager::Refresh(region), this=%p\n", this));
   MOZ_TIMER_STOP(mWatch);
   MOZ_TIMER_LOG(("vm2 Paint time (this=%p): ", this));
   MOZ_TIMER_PRINT(mWatch);
 #endif
 
 }
 
-// aRect is in app units and relative to the top-left of the aView->GetWidget()
-void nsViewManager::DefaultRefresh(nsView* aView,
-                                   nsIRenderingContext *aContext,
-                                   const nsRect* aRect)
-{
-  NS_PRECONDITION(aView, "Must have a view to work with!");
-
-  // Don't draw anything if there's no widget or it's transparent.
-  nsIWidget* widget = aView->GetNearestWidget(nsnull);
-  if (!widget || widget->GetTransparencyMode() != eTransparencyOpaque)
-    return;
-
-  nsCOMPtr<nsIRenderingContext> context = aContext;
-  if (!context)
-    context = CreateRenderingContext(*aView);
-
-  // XXXzw I think this can only happen if we don't have a widget, in
-  // which case we bailed out above.
-  if (!context) {
-    NS_WARNING("nsViewManager: No rendering context for DefaultRefresh");
-    return;
-  }
-
-  nscolor bgcolor = mDefaultBackgroundColor;
-  // If we somehow get here before any default background color has
-  // been set, warn and use white.
-  if (bgcolor == NS_RGBA(0,0,0,0)) {
-    NS_WARNING("nsViewManager: DefaultRefresh called with no background set");
-    bgcolor = NS_RGB(255,255,255);
-  }
-
-  NS_ASSERTION(NS_GET_A(bgcolor) == 255,
-               "nsViewManager: non-opaque background color snuck in");
-
-  context->SetColor(bgcolor);
-  context->FillRect(*aRect);
-}
-
 void nsViewManager::AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceContext* aContext,
                                                      nsView* aRootView) {
   NS_PRECONDITION(aRootView, "Must have root view");
   
   // We accumulate the bounds of widgets obscuring aRootView's widget into opaqueRgn.
   // In OptimizeDisplayList, display list elements which lie behind obscuring native
   // widgets are dropped.
   // This shouldn't really be necessary, since the GFX/Widget toolkit should remove these
@@ -1129,21 +1090,35 @@ NS_IMETHODIMP nsViewManager::DispatchEve
             
             if (view) {
               Refresh(view, event->renderingContext, region,
                       NS_VMREFRESH_DOUBLE_BUFFER);
             }
           }
         } else {
           // since we got an NS_PAINT event, we need to
-          // draw something so we don't get blank areas.
+          // draw something so we don't get blank areas,
+          // unless there's no widget or it's transparent.
           nsIntRect damIntRect;
-          region->GetBoundingBox(&damIntRect.x, &damIntRect.y, &damIntRect.width, &damIntRect.height);
-          nsRect damRect = nsIntRect::ToAppUnits(damIntRect, mContext->AppUnitsPerDevPixel());
-          DefaultRefresh(view, event->renderingContext, &damRect);
+          region->GetBoundingBox(&damIntRect.x, &damIntRect.y,
+                                 &damIntRect.width, &damIntRect.height);
+          nsRect damRect =
+            nsIntRect::ToAppUnits(damIntRect, mContext->AppUnitsPerDevPixel());
+
+          nsIWidget* widget = view->GetNearestWidget(nsnull);
+          if (widget && widget->GetTransparencyMode() == eTransparencyOpaque) {
+            nsCOMPtr<nsIRenderingContext> context = event->renderingContext;
+            if (!context)
+              context = CreateRenderingContext(*view);
+
+            if (context)
+              mObserver->PaintDefaultBackground(view, context, damRect);
+            else
+              NS_WARNING("nsViewManager: no rc for default refresh");
+          }
         
           // Clients like the editor can trigger multiple
           // reflows during what the user perceives as a single
           // edit operation, so it disables view manager
           // refreshing until the edit operation is complete
           // so that users don't see the intermediate steps.
           // 
           // Unfortunately some of these reflows can trigger
@@ -1158,17 +1133,17 @@ NS_IMETHODIMP nsViewManager::DispatchEve
           // painted properly when refresh is enabled.
           //
           // Note that calling UpdateView() here was deemed
           // to have the least impact on performance, since the
           // other alternative was to make Scroll() post an
           // async paint event for the *entire* ScrollPort or
           // ScrollingView's viewable area. (See bug 97674 for this
           // alternate patch.)
-          
+
           UpdateView(view, damRect, NS_VMREFRESH_NO_SYNC);
         }
 
         break;
       }
 
     case NS_CREATE:
     case NS_DESTROY:
@@ -2227,32 +2202,16 @@ nsViewManager::ProcessInvalidateEvent()
   mInvalidateEvent.Forget();
   if (!processEvent) {
     // We didn't actually process this event... post a new one
     PostInvalidateEvent();
   }
 }
 
 NS_IMETHODIMP
-nsViewManager::SetDefaultBackgroundColor(nscolor aColor)
-{
-  NS_ASSERTION(NS_GET_A(aColor) == 255, "default background must be opaque");
-  mDefaultBackgroundColor = aColor;
-  return NS_OK;
-}
-
-NS_IMETHODIMP
-nsViewManager::GetDefaultBackgroundColor(nscolor* aColor)
-{
-  *aColor = mDefaultBackgroundColor;
-  return NS_OK;
-}
-
-
-NS_IMETHODIMP
 nsViewManager::GetLastUserEventTime(PRUint32& aTime)
 {
   aTime = gLastUserEventTime;
   return NS_OK;
 }
 
 class nsSynthMouseMoveEvent : public nsViewManagerEvent {
 public:
--- a/view/src/nsViewManager.h
+++ b/view/src/nsViewManager.h
@@ -171,18 +171,16 @@ public:
   NS_IMETHOD  SetRootScrollableView(nsIScrollableView *aScrollable);
   NS_IMETHOD  GetRootScrollableView(nsIScrollableView **aScrollable);
 
   NS_IMETHOD GetWidget(nsIWidget **aWidget);
   nsIWidget* GetWidget() { return mRootView ? mRootView->GetWidget() : nsnull; }
   NS_IMETHOD ForceUpdate();
  
   NS_IMETHOD IsPainting(PRBool& aIsPainting);
-  NS_IMETHOD SetDefaultBackgroundColor(nscolor aColor);
-  NS_IMETHOD GetDefaultBackgroundColor(nscolor* aColor);
   NS_IMETHOD GetLastUserEventTime(PRUint32& aTime);
   void ProcessInvalidateEvent();
   static PRUint32 gLastUserEventTime;
 
   /**
    * Determine if a rectangle specified in the view's coordinate system 
    * is completely, or partially visible.
    * @param aView view that aRect coordinates are specified relative to
@@ -257,20 +255,16 @@ private:
   already_AddRefed<nsIRenderingContext> CreateRenderingContext(nsView &aView);
   void UpdateWidgetArea(nsView *aWidgetView, const nsRegion &aDamagedRegion,
                         nsView* aIgnoreWidgetView);
 
   void UpdateViews(nsView *aView, PRUint32 aUpdateFlags);
 
   void Refresh(nsView *aView, nsIRenderingContext *aContext,
                nsIRegion *region, PRUint32 aUpdateFlags);
-  /**
-   * Refresh aView (which must be non-null) with our default background color
-   */
-  void DefaultRefresh(nsView* aView, nsIRenderingContext *aContext, const nsRect* aRect);
   void RenderViews(nsView *aRootView, nsIRenderingContext& aRC,
                    const nsRegion& aRegion);
 
   void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut, PRUint32 aUpdateFlags);
   void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,
                                           PRUint32 aUpdateFlags, nscoord aY1, nscoord aY2, PRBool aInCutOut);
 
   void AddCoveringWidgetsToOpaqueRegion(nsRegion &aRgn, nsIDeviceContext* aContext,
@@ -422,17 +416,16 @@ public: // NOT in nsIViewManager, so pri
 
   // Call this when you need to let the viewmanager know that it now has
   // pending updates.
   void PostPendingUpdate() { RootViewManager()->mHasPendingUpdates = PR_TRUE; }
 private:
   nsIDeviceContext  *mContext;
   nsIViewObserver   *mObserver;
   nsIScrollableView *mRootScrollable;
-  nscolor           mDefaultBackgroundColor;
   nsIntPoint        mMouseLocation; // device units, relative to mRootView
 
   // The size for a resize that we delayed until the root view becomes
   // visible again.
   nsSize            mDelayedResize;
 
   nsCOMPtr<nsIFactory> mRegionFactory;
   nsView            *mRootView;