Bug 601603. Part 5 - Ensure that the layer that holds the window background is never opaque for glass windows. r=roc a=beta8
authorFelipe Gomes <felipc@gmail.com>
Tue, 19 Oct 2010 15:02:25 -0200
changeset 56101 c9d327fec92eed3462e9f291183cfc1568944ad2
parent 56100 d73eaa05f59d8ae9ac4a99b9c841f86c0d9c8be0
child 56102 87b059ee9a6734e7097807eb5bf365e390fe3b9b
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc, beta8
bugs601603
milestone2.0b8pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 601603. Part 5 - Ensure that the layer that holds the window background is never opaque for glass windows. r=roc a=beta8
layout/base/FrameLayerBuilder.cpp
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsLayoutUtils.cpp
layout/generic/nsCanvasFrame.h
layout/generic/nsHTMLCanvasFrame.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
widget/src/windows/nsNativeThemeWin.cpp
--- a/layout/base/FrameLayerBuilder.cpp
+++ b/layout/base/FrameLayerBuilder.cpp
@@ -157,17 +157,18 @@ protected:
    * makes it more likely a display item will be rendered to an opaque
    * layer, giving us the best chance of getting subpixel AA.
    */
   class ThebesLayerData {
   public:
     ThebesLayerData() :
       mActiveScrolledRoot(nsnull), mLayer(nsnull),
       mIsSolidColorInVisibleRegion(PR_FALSE),
-      mHasText(PR_FALSE), mHasTextOverTransparent(PR_FALSE) {}
+      mHasText(PR_FALSE), mHasTextOverTransparent(PR_FALSE),
+      mForceTransparentSurface(PR_FALSE) {}
     /**
      * Record that an item has been added to the ThebesLayer, so we
      * need to update our regions.
      * @param aVisibleRect the area of the item that's visible
      * @param aDrawRect the area of the item that would be drawn if it
      * was completely visible
      * @param aOpaqueRect if non-null, the area of the item that's opaque.
      * We pass in a separate opaque rect because the opaque rect can be
@@ -235,16 +236,23 @@ protected:
      * True if there is any text visible in the layer.
      */
     PRPackedBool mHasText;
     /**
      * True if there is any text visible in the layer that's over
      * transparent pixels in the layer.
      */
     PRPackedBool mHasTextOverTransparent;
+    /**
+     * Set if the layer should be treated as transparent, even if its entire
+     * area is covered by opaque display items. For example, this needs to
+     * be set if something is going to "punch holes" in the layer by clearing
+     * part of its surface.
+     */
+    PRPackedBool mForceTransparentSurface;
   };
 
   /**
    * Grab the next recyclable ThebesLayer, or create one if there are no
    * more recyclable ThebesLayers. Does any necessary invalidation of
    * a recycled ThebesLayer, and sets up the transform on the ThebesLayer
    * to account for scrolling.
    */
@@ -856,17 +864,17 @@ ContainerState::PopThebesLayerData()
     if (userData->mForcedBackgroundColor != backgroundColor) {
       // Invalidate the entire target ThebesLayer since we're changing
       // the background color
       data->mLayer->InvalidateRegion(data->mLayer->GetValidRegion());
     }
     userData->mForcedBackgroundColor = backgroundColor;
   }
   PRUint32 flags =
-    (isOpaque ? Layer::CONTENT_OPAQUE : 0) |
+    ((isOpaque && !data->mForceTransparentSurface) ? Layer::CONTENT_OPAQUE : 0) |
     (data->mHasText ? 0 : Layer::CONTENT_NO_TEXT) |
     (data->mHasTextOverTransparent ? 0 : Layer::CONTENT_NO_TEXT_OVER_TRANSPARENT);
   layer->SetContentFlags(flags);
 
   if (lastIndex > 0) {
     // Since we're going to pop off the last ThebesLayerData, the
     // mVisibleAboveRegion of the second-to-last item will need to include
     // the regions of the last item.
@@ -907,33 +915,35 @@ ContainerState::ThebesLayerData::Accumul
     mIsSolidColorInVisibleRegion = PR_FALSE;
   }
 
   mVisibleRegion.Or(mVisibleRegion, aVisibleRect);
   mVisibleRegion.SimplifyOutward(4);
   mDrawRegion.Or(mDrawRegion, aDrawRect);
   mDrawRegion.SimplifyOutward(4);
 
-  if (aItem->IsOpaque(aBuilder)) {
+  PRBool forceTransparentSurface = PR_FALSE;
+  if (aItem->IsOpaque(aBuilder, &forceTransparentSurface)) {
     // We don't use SimplifyInward here since it's not defined exactly
     // what it will discard. For our purposes the most important case
     // is a large opaque background at the bottom of z-order (e.g.,
     // a canvas background), so we need to make sure that the first rect
     // we see doesn't get discarded.
     nsIntRegion tmp;
     tmp.Or(mOpaqueRegion, aDrawRect);
     if (tmp.GetNumRects() <= 4) {
       mOpaqueRegion = tmp;
     }
   } else if (aItem->HasText()) {
     mHasText = PR_TRUE;
     if (!mOpaqueRegion.Contains(aVisibleRect)) {
       mHasTextOverTransparent = PR_TRUE;
     }
   }
+  mForceTransparentSurface = mForceTransparentSurface || forceTransparentSurface;
 }
 
 already_AddRefed<ThebesLayer>
 ContainerState::FindThebesLayerFor(nsDisplayItem* aItem,
                                    const nsIntRect& aVisibleRect,
                                    const nsIntRect& aDrawRect,
                                    nsIFrame* aActiveScrolledRoot)
 {
@@ -1387,17 +1397,18 @@ FrameLayerBuilder::BuildContainerLayerFo
     }
     SetHasContainerLayer(aContainerFrame);
   }
 
   Clip clip;
   state.ProcessDisplayItems(aChildren, clip);
   state.Finish();
 
-  PRUint32 flags = aChildren.IsOpaque() ? Layer::CONTENT_OPAQUE : 0;
+  PRUint32 flags = aChildren.IsOpaque() && 
+                   !aChildren.NeedsTransparentSurface() ? Layer::CONTENT_OPAQUE : 0;
   containerLayer->SetContentFlags(flags);
   return containerLayer.forget();
 }
 
 Layer*
 FrameLayerBuilder::GetLeafLayerFor(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    nsDisplayItem* aItem)
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -315,16 +315,18 @@ nsDisplayList::ComputeVisibilityForSubli
                "bad aListVisibleBounds");
 #endif
   mVisibleRect = aListVisibleBounds;
   PRBool anyVisible = PR_FALSE;
 
   nsAutoTArray<nsDisplayItem*, 512> elements;
   FlattenTo(&elements);
 
+  PRBool forceTransparentSurface = PR_FALSE;
+
   for (PRInt32 i = elements.Length() - 1; i >= 0; --i) {
     nsDisplayItem* item = elements[i];
     nsDisplayItem* belowItem = i < 1 ? nsnull : elements[i - 1];
 
     if (belowItem && item->TryMerge(aBuilder, belowItem)) {
       belowItem->~nsDisplayItem();
       elements.ReplaceElementsAt(i - 1, 1, item);
       continue;
@@ -334,25 +336,28 @@ nsDisplayList::ComputeVisibilityForSubli
 
     nsRegion itemVisible;
     itemVisible.And(*aVisibleRegion, bounds);
     item->mVisibleRect = itemVisible.GetBounds();
 
     if (item->ComputeVisibility(aBuilder, aVisibleRegion)) {
       anyVisible = PR_TRUE;
       nsIFrame* f = item->GetUnderlyingFrame();
-      if (item->IsOpaque(aBuilder) && f) {
+      PRBool transparentBackground = PR_FALSE;
+      if (item->IsOpaque(aBuilder, &transparentBackground) && f) {
         // Subtract opaque item from the visible region
         aBuilder->SubtractFromVisibleRegion(aVisibleRegion, nsRegion(bounds));
       }
+      forceTransparentSurface = forceTransparentSurface || transparentBackground;
     }
     AppendToBottom(item);
   }
 
   mIsOpaque = !aVisibleRegion->Intersects(mVisibleRect);
+  mForceTransparentSurface = forceTransparentSurface;
 #ifdef DEBUG
   mDidComputeVisibility = PR_TRUE;
 #endif
   return anyVisible;
 }
 
 void nsDisplayList::PaintRoot(nsDisplayListBuilder* aBuilder,
                               nsIRenderingContext* aCtx,
@@ -840,20 +845,30 @@ nsDisplayBackground::ComputeVisibility(n
   // frame. We don't want this display item to show up and confuse
   // anything.
   nsStyleContext* bgSC;
   return mIsThemed ||
     nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC);
 }
 
 PRBool
-nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) {
+nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder,
+                              PRBool* aForceTransparentSurface) {
+  if (aForceTransparentSurface) {
+    *aForceTransparentSurface = PR_FALSE;
+  }
   // theme background overrides any other background
-  if (mIsThemed)
+  if (mIsThemed) {
+    if (aForceTransparentSurface) {
+      const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
+      *aForceTransparentSurface = disp->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS ||
+                                  disp->mAppearance == NS_THEME_WIN_GLASS;
+    }
     return mThemeTransparency == nsITheme::eOpaque;
+  }
 
   nsStyleContext* bgSC;
   if (!nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bgSC))
     return PR_FALSE;
   const nsStyleBackground* bg = bgSC->GetStyleBackground();
 
   const nsStyleBackground::Layer& bottomLayer = bg->BottomLayer();
 
@@ -1225,17 +1240,21 @@ nsDisplayWrapList::GetBounds(nsDisplayLi
 PRBool
 nsDisplayWrapList::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                      nsRegion* aVisibleRegion) {
   return mList.ComputeVisibilityForSublist(aBuilder, aVisibleRegion,
                                            mVisibleRect);
 }
 
 PRBool
-nsDisplayWrapList::IsOpaque(nsDisplayListBuilder* aBuilder) {
+nsDisplayWrapList::IsOpaque(nsDisplayListBuilder* aBuilder,
+                            PRBool* aForceTransparentSurface) {
+  if (aForceTransparentSurface) {
+    *aForceTransparentSurface = PR_FALSE;
+  }
   return mList.IsOpaque();
 }
 
 PRBool nsDisplayWrapList::IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) {
   // We could try to do something but let's conservatively just return PR_FALSE.
   return PR_FALSE;
 }
 
@@ -1364,17 +1383,21 @@ nsDisplayOpacity::nsDisplayOpacity(nsDis
 }
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplayOpacity::~nsDisplayOpacity() {
   MOZ_COUNT_DTOR(nsDisplayOpacity);
 }
 #endif
 
-PRBool nsDisplayOpacity::IsOpaque(nsDisplayListBuilder* aBuilder) {
+PRBool nsDisplayOpacity::IsOpaque(nsDisplayListBuilder* aBuilder,
+                                  PRBool* aForceTransparentSurface) {
+  if (aForceTransparentSurface) {
+    *aForceTransparentSurface = PR_FALSE;
+  }
   // We are never opaque, if our opacity was < 1 then we wouldn't have
   // been created.
   return PR_FALSE;
 }
 
 // nsDisplayOpacity uses layers for rendering
 already_AddRefed<Layer>
 nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
@@ -1534,18 +1557,22 @@ nsDisplayClipRoundedRect::nsDisplayClipR
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplayClipRoundedRect::~nsDisplayClipRoundedRect()
 {
   MOZ_COUNT_DTOR(nsDisplayClipRoundedRect);
 }
 #endif
 
-PRBool nsDisplayClipRoundedRect::IsOpaque(nsDisplayListBuilder* aBuilder)
+PRBool nsDisplayClipRoundedRect::IsOpaque(nsDisplayListBuilder* aBuilder,
+                                          PRBool* aForceTransparentSurface)
 {
+  if (aForceTransparentSurface) {
+    *aForceTransparentSurface = PR_FALSE;
+  }
   return PR_FALSE;
 }
 
 void
 nsDisplayClipRoundedRect::HitTest(nsDisplayListBuilder* aBuilder,
                                   const nsRect& aRect, HitTestState* aState,
                                   nsTArray<nsIFrame*> *aOutFrames)
 {
@@ -1943,18 +1970,22 @@ nsRect nsDisplayTransform::GetBounds(nsD
  * is of the form
  *
  * |a c e|
  * |b d f|
  * |0 0 1|
  *
  * We need b and c to be zero.
  */
-PRBool nsDisplayTransform::IsOpaque(nsDisplayListBuilder *aBuilder)
+PRBool nsDisplayTransform::IsOpaque(nsDisplayListBuilder *aBuilder,
+                                    PRBool* aForceTransparentSurface)
 {
+  if (aForceTransparentSurface) {
+    *aForceTransparentSurface = PR_FALSE;
+  }
   const nsStyleDisplay* disp = mFrame->GetStyleDisplay();
   return disp->mTransform.GetMainMatrixEntry(1) == 0.0f &&
     disp->mTransform.GetMainMatrixEntry(2) == 0.0f &&
     mStoredList.IsOpaque(aBuilder);
 }
 
 /* The transform is uniform if it fills the entire bounding rect and the
  * wrapped list is uniform.  See IsOpaque for discussion of why this
@@ -2073,18 +2104,22 @@ nsDisplaySVGEffects::nsDisplaySVGEffects
 
 #ifdef NS_BUILD_REFCNT_LOGGING
 nsDisplaySVGEffects::~nsDisplaySVGEffects()
 {
   MOZ_COUNT_DTOR(nsDisplaySVGEffects);
 }
 #endif
 
-PRBool nsDisplaySVGEffects::IsOpaque(nsDisplayListBuilder* aBuilder)
+PRBool nsDisplaySVGEffects::IsOpaque(nsDisplayListBuilder* aBuilder,
+                                     PRBool* aForceTransparentSurface)
 {
+  if (aForceTransparentSurface) {
+    *aForceTransparentSurface = PR_FALSE;
+  }
   return PR_FALSE;
 }
 
 void
 nsDisplaySVGEffects::HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                              HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames)
 {
   nsPoint rectCenter(aRect.x + aRect.width / 2, aRect.y + aRect.height / 2);
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -50,16 +50,17 @@
 #include "nsPoint.h"
 #include "nsRect.h"
 #include "nsISelection.h"
 #include "nsCaret.h"
 #include "plarena.h"
 #include "Layers.h"
 #include "nsRegion.h"
 #include "FrameLayerBuilder.h"
+#include "nsThemeConstants.h"
 
 #include <stdlib.h>
 
 class nsIPresShell;
 class nsIContent;
 class nsIRenderingContext;
 class nsIDeviceContext;
 class nsDisplayTableItem;
@@ -512,17 +513,24 @@ public:
    */
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
     return nsRect(ToReferenceFrame(), GetUnderlyingFrame()->GetSize());
   }
   /**
    * @return PR_TRUE if the item is definitely opaque --- i.e., paints
    * every pixel within its bounds opaquely
    */
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) { return PR_FALSE; }
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull)
+  {
+    if (aForceTransparentSurface) {
+      *aForceTransparentSurface = PR_FALSE;
+    }
+    return PR_FALSE;
+  }
   /**
    * If this returns true, then aColor is set to the uniform color
    * @return PR_TRUE if the item is guaranteed to paint every pixel in its
    * bounds with the same (possibly translucent) color
    */
   virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) { return PR_FALSE; }
   /**
    * @return PR_FALSE if the painting performed by the item is invariant
@@ -889,16 +897,25 @@ public:
   /**
    * Returns true if the visible region output from ComputeVisiblity was
    * empty, i.e. everything visible in this list is opaque.
    */
   PRBool IsOpaque() const {
     NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility");
     return mIsOpaque;
   }
+
+  /**
+   * Returns true if during ComputeVisibility any display item
+   * set the surface to be transparent.
+   */
+  PRBool NeedsTransparentSurface() const {
+    NS_ASSERTION(mDidComputeVisibility, "Need to have called ComputeVisibility");
+    return mForceTransparentSurface;
+  }
   /**
    * Paint the list to the rendering context. We assume that (0,0) in aCtx
    * corresponds to the origin of the reference frame. For best results,
    * aCtx's current transform should make (0,0) pixel-aligned. The
    * rectangle in aDirtyRect is painted, which *must* be contained in the
    * dirty rect used to construct the display list.
    * 
    * If aFlags contains PAINT_USE_WIDGET_LAYERS and
@@ -959,16 +976,20 @@ private:
   nsDisplayItemLink* mTop;
 
   // This is set by ComputeVisibility
   nsRect mVisibleRect;
   // This is set to true by ComputeVisibility if the final visible region
   // is empty (i.e. everything that was visible is covered by some
   // opaque content in this list).
   PRPackedBool mIsOpaque;
+  // This is set to true by ComputeVisibility if any display item in this
+  // list needs to force the surface to be transparent (e.g. if the
+  // item "punch holes" on the surface by clearing part of its area).
+  PRPackedBool mForceTransparentSurface;
 #ifdef DEBUG
   PRPackedBool mDidComputeVisibility;
 #endif
 };
 
 /**
  * This is passed as a parameter to nsIFrame::BuildDisplayList. That method
  * will put any generated items onto the appropriate list given here. It's
@@ -1286,33 +1307,38 @@ public:
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplaySolidColor() {
     MOZ_COUNT_DTOR(nsDisplaySolidColor);
   }
 #endif
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) { return mBounds; }
 
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) {
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aOutTransparentBackground = nsnull) {
+    if (aOutTransparentBackground) {
+      *aOutTransparentBackground = PR_FALSE;
+    }
     return (NS_GET_A(mColor) == 255);
   }
 
   virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
   {
     *aColor = mColor;
     return PR_TRUE;
   }
 
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
 
   NS_DISPLAY_DECL_NAME("SolidColor", TYPE_SOLID_COLOR)
 
 private:
   nsRect  mBounds;
   nscolor mColor;
+  PRBool  mTransparentBackground;
 };
 
 /**
  * The standard display item to paint the CSS background of a frame.
  */
 class nsDisplayBackground : public nsDisplayItem {
 public:
   nsDisplayBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame);
@@ -1321,17 +1347,18 @@ public:
     MOZ_COUNT_DTOR(nsDisplayBackground);
   }
 #endif
 
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
   virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion);
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull);
   virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
                                                 nsIFrame* aFrame);
   virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
   virtual PRBool IsFixedAndCoveringViewport(nsDisplayListBuilder* aBuilder);
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
   NS_DISPLAY_DECL_NAME("Background", TYPE_BACKGROUND)
 protected:
@@ -1456,17 +1483,18 @@ public:
   nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                     nsDisplayList* aList);
   nsDisplayWrapList(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                     nsDisplayItem* aItem);
   virtual ~nsDisplayWrapList();
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull);
   virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor);
   virtual PRBool IsVaryingRelativeToMovingFrame(nsDisplayListBuilder* aBuilder,
                                                 nsIFrame* aFrame);
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
   virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion);
   virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem) {
     NS_WARNING("This list should already have been flattened!!!");
@@ -1539,17 +1567,18 @@ protected:
 class nsDisplayOpacity : public nsDisplayWrapList {
 public:
   nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                    nsDisplayList* aList);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayOpacity();
 #endif
   
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull);
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager);
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager);
   virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion);  
   virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
   NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
@@ -1636,17 +1665,18 @@ public:
                            const nsRect& aRect, nscoord aRadii[8]);
   nsDisplayClipRoundedRect(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                            nsDisplayList* aList,
                            const nsRect& aRect, nscoord aRadii[8]);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayClipRoundedRect();
 #endif
 
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull);
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
   virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion);
   virtual PRBool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
   NS_DISPLAY_DECL_NAME("ClipRoundedRect", TYPE_CLIP_ROUNDED_RECT)
 
   virtual nsDisplayWrapList* WrapWithClone(nsDisplayListBuilder* aBuilder,
@@ -1705,17 +1735,18 @@ private:
 class nsDisplaySVGEffects : public nsDisplayWrapList {
 public:
   nsDisplaySVGEffects(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                       nsDisplayList* aList);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplaySVGEffects();
 #endif
   
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull);
   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
                        HitTestState* aState, nsTArray<nsIFrame*> *aOutFrames);
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
     return mBounds + aBuilder->ToReferenceFrame(mEffectsFrame);
   }
   virtual void Paint(nsDisplayListBuilder* aBuilder, nsIRenderingContext* aCtx);
   virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion);  
@@ -1763,17 +1794,18 @@ public:
 
 #ifdef NS_DEBUG
   nsDisplayWrapList* GetStoredList() { return &mStoredList; }
 #endif
 
   virtual void HitTest(nsDisplayListBuilder *aBuilder, const nsRect& aRect,
                        HitTestState *aState, nsTArray<nsIFrame*> *aOutFrames);
   virtual nsRect GetBounds(nsDisplayListBuilder *aBuilder);
-  virtual PRBool IsOpaque(nsDisplayListBuilder *aBuilder);
+  virtual PRBool IsOpaque(nsDisplayListBuilder *aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull);
   virtual PRBool IsUniform(nsDisplayListBuilder *aBuilder, nscolor* aColor);
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager);
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager);
   virtual PRBool ComputeVisibility(nsDisplayListBuilder *aBuilder,
                                    nsRegion *aVisibleRegion);
   virtual PRBool TryMerge(nsDisplayListBuilder *aBuilder, nsDisplayItem *aItem);
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3357,28 +3357,28 @@ nsLayoutUtils::HasNonZeroCornerOnSide(co
 nsLayoutUtils::GetFrameTransparency(nsIFrame* aBackgroundFrame,
                                     nsIFrame* aCSSRootFrame) {
   if (aCSSRootFrame->GetStyleContext()->GetStyleDisplay()->mOpacity < 1.0f)
     return eTransparencyTransparent;
 
   if (HasNonZeroCorner(aCSSRootFrame->GetStyleContext()->GetStyleBorder()->mBorderRadius))
     return eTransparencyTransparent;
 
+  if (aCSSRootFrame->GetStyleDisplay()->mAppearance == NS_THEME_WIN_GLASS)
+    return eTransparencyGlass;
+
+  if (aCSSRootFrame->GetStyleDisplay()->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS)
+    return eTransparencyBorderlessGlass;
+
   nsITheme::Transparency transparency;
   if (aCSSRootFrame->IsThemed(&transparency))
     return transparency == nsITheme::eTransparent
          ? eTransparencyTransparent
          : eTransparencyOpaque;
 
-  if (aCSSRootFrame->GetStyleDisplay()->mAppearance == NS_THEME_WIN_GLASS)
-    return eTransparencyGlass;
-
-  if (aCSSRootFrame->GetStyleDisplay()->mAppearance == NS_THEME_WIN_BORDERLESS_GLASS)
-    return eTransparencyBorderlessGlass;
-
   // We need an uninitialized window to be treated as opaque because
   // doing otherwise breaks window display effects on some platforms,
   // specifically Vista. (bug 450322)
   if (aBackgroundFrame->GetType() == nsGkAtoms::viewportFrame &&
       !aBackgroundFrame->GetFirstChild(nsnull)) {
     return eTransparencyOpaque;
   }
 
--- a/layout/generic/nsCanvasFrame.h
+++ b/layout/generic/nsCanvasFrame.h
@@ -172,18 +172,22 @@ public:
   }
 
   virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion)
   {
     return NS_GET_A(mExtraBackgroundColor) > 0 ||
            nsDisplayBackground::ComputeVisibility(aBuilder, aVisibleRegion);
   }
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder)
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull)
   {
+    if (aForceTransparentSurface) {
+      *aForceTransparentSurface = PR_FALSE;
+    }
     return NS_GET_A(mExtraBackgroundColor) == 255 ||
            nsDisplayBackground::IsOpaque(aBuilder);
   }
   virtual PRBool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor)
   {
     nscolor background;
     if (!nsDisplayBackground::IsUniform(aBuilder, &background))
       return PR_FALSE;
--- a/layout/generic/nsHTMLCanvasFrame.cpp
+++ b/layout/generic/nsHTMLCanvasFrame.cpp
@@ -72,17 +72,21 @@ public:
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayCanvas() {
     MOZ_COUNT_DTOR(nsDisplayCanvas);
   }
 #endif
 
   NS_DISPLAY_DECL_NAME("nsDisplayCanvas", TYPE_CANVAS)
 
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder) {
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull) {
+    if (aForceTransparentSurface) {
+      *aForceTransparentSurface = PR_FALSE;
+    }
     nsIFrame* f = GetUnderlyingFrame();
     nsHTMLCanvasElement *canvas = CanvasElementFromContent(f->GetContent());
     return canvas->GetIsOpaque();
   }
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder) {
     nsHTMLCanvasFrame* f = static_cast<nsHTMLCanvasFrame*>(GetUnderlyingFrame());
     return f->GetInnerArea() + ToReferenceFrame();
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1262,18 +1262,22 @@ PRBool
 nsDisplayPlugin::ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion)
 {
   mVisibleRegion.And(*aVisibleRegion, GetBounds(aBuilder));  
   return nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion);
 }
 
 PRBool
-nsDisplayPlugin::IsOpaque(nsDisplayListBuilder* aBuilder)
-{
+nsDisplayPlugin::IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface)
+{
+  if (aForceTransparentSurface) {
+    *aForceTransparentSurface = PR_FALSE;
+  }
   nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
   return f->IsOpaque();
 }
 
 void
 nsDisplayPlugin::GetWidgetConfiguration(nsDisplayListBuilder* aBuilder,
                                         nsTArray<nsIWidget::Configuration>* aConfigurations)
 {
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -310,17 +310,18 @@ public:
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayPlugin() {
     MOZ_COUNT_DTOR(nsDisplayPlugin);
   }
 #endif
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
-  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder);
+  virtual PRBool IsOpaque(nsDisplayListBuilder* aBuilder,
+                          PRBool* aForceTransparentSurface = nsnull);
   virtual void Paint(nsDisplayListBuilder* aBuilder,
                      nsIRenderingContext* aCtx);
   virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion);
 
   NS_DISPLAY_DECL_NAME("Plugin", TYPE_PLUGIN)
 
   // Compute the desired position and clip region of the plugin's widget.
--- a/widget/src/windows/nsNativeThemeWin.cpp
+++ b/widget/src/windows/nsNativeThemeWin.cpp
@@ -424,16 +424,18 @@ nsNativeThemeWin::GetTheme(PRUint8 aWidg
     case NS_THEME_WINDOW_FRAME_RIGHT:
     case NS_THEME_WINDOW_FRAME_BOTTOM:
     case NS_THEME_WINDOW_BUTTON_CLOSE:
     case NS_THEME_WINDOW_BUTTON_MINIMIZE:
     case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
     case NS_THEME_WINDOW_BUTTON_RESTORE:
     case NS_THEME_WINDOW_BUTTON_BOX:
     case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
+    case NS_THEME_WIN_GLASS:
+    case NS_THEME_WIN_BORDERLESS_GLASS:
       return nsUXThemeData::GetTheme(eUXWindowFrame);
   }
   return NULL;
 }
 
 PRInt32
 nsNativeThemeWin::StandardGetState(nsIFrame* aFrame, PRUint8 aWidgetType,
                                    PRBool wantFocused)
@@ -1085,16 +1087,18 @@ nsNativeThemeWin::GetThemePartAndState(n
       aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
       return NS_OK;
     case NS_THEME_WINDOW_BUTTON_RESTORE:
       aPart = mozilla::widget::themeconst::WP_RESTOREBUTTON;
       aState = GetWindowFrameButtonState(aFrame, GetContentState(aFrame, aWidgetType));
       return NS_OK;
     case NS_THEME_WINDOW_BUTTON_BOX:
     case NS_THEME_WINDOW_BUTTON_BOX_MAXIMIZED:
+    case NS_THEME_WIN_GLASS:
+    case NS_THEME_WIN_BORDERLESS_GLASS:
       aPart = -1;
       aState = 0;
       return NS_OK;
   }
 
   aPart = 0;
   aState = 0;
   return NS_ERROR_FAILURE;
@@ -1109,16 +1113,47 @@ nsNativeThemeWin::DrawWidgetBackground(n
 {
   HANDLE theme = GetTheme(aWidgetType);
   if (!theme)
     return ClassicDrawWidgetBackground(aContext, aFrame, aWidgetType, aRect, aDirtyRect); 
 
   if (!nsUXThemeData::drawThemeBG)
     return NS_ERROR_FAILURE;    
 
+#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
+  // ^^ without the right sdk, assume xp theming and fall through.
+  if (nsUXThemeData::CheckForCompositor()) {
+    switch (aWidgetType) {
+      case NS_THEME_WINDOW_TITLEBAR:
+      case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
+      case NS_THEME_WINDOW_FRAME_LEFT:
+      case NS_THEME_WINDOW_FRAME_RIGHT:
+      case NS_THEME_WINDOW_FRAME_BOTTOM:
+        // Nothing to draw, these areas are glass. Minimum dimensions
+        // should be set, so xul content should be layed out correctly.
+        return NS_OK;
+      break;
+      case NS_THEME_WINDOW_BUTTON_CLOSE:
+      case NS_THEME_WINDOW_BUTTON_MINIMIZE:
+      case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
+      case NS_THEME_WINDOW_BUTTON_RESTORE:
+        // Not conventional bitmaps, can't be retrieved. If we fall
+        // through here and call the theme library we'll get aero
+        // basic bitmaps. 
+        return NS_OK;
+      break;
+      case NS_THEME_WIN_GLASS:
+      case NS_THEME_WIN_BORDERLESS_GLASS:
+        // Nothing to draw, this is the glass background.
+        return NS_OK;
+      break;
+    }
+  }
+#endif // MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
+
   PRInt32 part, state;
   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
   if (NS_FAILED(rv))
     return rv;
 
   nsCOMPtr<nsIDeviceContext> dc;
   aContext->GetDeviceContext(*getter_AddRefs(dc));
   gfxFloat p2a = gfxFloat(dc->AppUnitsPerDevPixel());
@@ -1138,42 +1173,16 @@ nsNativeThemeWin::DrawWidgetBackground(n
     tr.size.width += 1.0;
     tr.size.height += 2.0;
 
     dr.pos.y -= 1.0;
     dr.size.width += 1.0;
     dr.size.height += 2.0;
   }
 
-#if MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
-  // ^^ without the right sdk, assume xp theming and fall through.
-  if (nsUXThemeData::CheckForCompositor()) {
-    switch (aWidgetType) {
-      case NS_THEME_WINDOW_TITLEBAR:
-      case NS_THEME_WINDOW_TITLEBAR_MAXIMIZED:
-      case NS_THEME_WINDOW_FRAME_LEFT:
-      case NS_THEME_WINDOW_FRAME_RIGHT:
-      case NS_THEME_WINDOW_FRAME_BOTTOM:
-        // Nothing to draw, these areas are glass. Minimum dimensions
-        // should be set, so xul content should be layed out correctly.
-        return NS_OK;
-      break;
-      case NS_THEME_WINDOW_BUTTON_CLOSE:
-      case NS_THEME_WINDOW_BUTTON_MINIMIZE:
-      case NS_THEME_WINDOW_BUTTON_MAXIMIZE:
-      case NS_THEME_WINDOW_BUTTON_RESTORE:
-        // Not conventional bitmaps, can't be retrieved. If we fall
-        // through here and call the theme library we'll get aero
-        // basic bitmaps. 
-        return NS_OK;
-      break;
-    }
-  }
-#endif // MOZ_WINSDK_TARGETVER >= MOZ_NTDDI_LONGHORN
-    
   nsRefPtr<gfxContext> ctx = aContext->ThebesContext();
 
   gfxWindowsNativeDrawing nativeDrawing(ctx, dr, GetWidgetNativeDrawingFlags(aWidgetType));
 
 RENDER_AGAIN:
 
   HDC hdc = nativeDrawing.BeginNativeDrawing();
   if (!hdc)
@@ -1484,17 +1493,18 @@ nsNativeThemeWin::GetWidgetBorder(nsIDev
       aWidgetType == NS_THEME_WIN_BROWSER_TAB_BAR_TOOLBOX ||
       aWidgetType == NS_THEME_STATUSBAR || 
       aWidgetType == NS_THEME_RESIZER || aWidgetType == NS_THEME_TAB_PANEL ||
       aWidgetType == NS_THEME_SCROLLBAR_TRACK_HORIZONTAL ||
       aWidgetType == NS_THEME_SCROLLBAR_TRACK_VERTICAL ||
       aWidgetType == NS_THEME_MENUITEM || aWidgetType == NS_THEME_CHECKMENUITEM ||
       aWidgetType == NS_THEME_RADIOMENUITEM || aWidgetType == NS_THEME_MENUPOPUP ||
       aWidgetType == NS_THEME_MENUIMAGE || aWidgetType == NS_THEME_MENUITEMTEXT ||
-      aWidgetType == NS_THEME_TOOLBAR_SEPARATOR)
+      aWidgetType == NS_THEME_TOOLBAR_SEPARATOR ||
+      aWidgetType == NS_THEME_WIN_GLASS || aWidgetType == NS_THEME_WIN_BORDERLESS_GLASS)
     return NS_OK; // Don't worry about it.
 
   if (!nsUXThemeData::getThemeContentRect)
     return NS_ERROR_FAILURE;
 
   PRInt32 part, state;
   nsresult rv = GetThemePartAndState(aFrame, aWidgetType, part, state);
   if (NS_FAILED(rv))
@@ -1764,16 +1774,18 @@ nsNativeThemeWin::GetMinimumWidgetSize(n
     case NS_THEME_STATUSBAR:
     case NS_THEME_PROGRESSBAR_CHUNK:
     case NS_THEME_PROGRESSBAR_CHUNK_VERTICAL:
     case NS_THEME_TAB_PANELS:
     case NS_THEME_TAB_PANEL:
     case NS_THEME_LISTBOX:
     case NS_THEME_TREEVIEW:
     case NS_THEME_MENUITEMTEXT:
+    case NS_THEME_WIN_GLASS:
+    case NS_THEME_WIN_BORDERLESS_GLASS:
       return NS_OK; // Don't worry about it.
   }
 
   if (aWidgetType == NS_THEME_MENUITEM && IsTopLevelMenu(aFrame))
       return NS_OK; // Don't worry about it for top level menus
 
   if (!nsUXThemeData::getThemePartSize)
     return NS_ERROR_FAILURE;
@@ -1985,17 +1997,19 @@ nsNativeThemeWin::WidgetStateChanged(nsI
       aWidgetType == NS_THEME_STATUSBAR_RESIZER_PANEL ||
       aWidgetType == NS_THEME_PROGRESSBAR_CHUNK ||
       aWidgetType == NS_THEME_PROGRESSBAR_CHUNK_VERTICAL ||
       aWidgetType == NS_THEME_PROGRESSBAR ||
       aWidgetType == NS_THEME_PROGRESSBAR_VERTICAL ||
       aWidgetType == NS_THEME_TOOLTIP ||
       aWidgetType == NS_THEME_TAB_PANELS ||
       aWidgetType == NS_THEME_TAB_PANEL ||
-      aWidgetType == NS_THEME_TOOLBAR_SEPARATOR) {
+      aWidgetType == NS_THEME_TOOLBAR_SEPARATOR ||
+      aWidgetType == NS_THEME_WIN_GLASS ||
+      aWidgetType == NS_THEME_WIN_BORDERLESS_GLASS) {
     *aShouldRepaint = PR_FALSE;
     return NS_OK;
   }
 
   if (aWidgetType == NS_THEME_WINDOW_TITLEBAR ||
       aWidgetType == NS_THEME_WINDOW_TITLEBAR_MAXIMIZED ||
       aWidgetType == NS_THEME_WINDOW_FRAME_LEFT ||
       aWidgetType == NS_THEME_WINDOW_FRAME_RIGHT ||
@@ -2113,16 +2127,19 @@ nsNativeThemeWin::GetWidgetTransparency(
   case NS_THEME_SCROLLBAR_SMALL:
   case NS_THEME_SCROLLBAR:
   case NS_THEME_STATUSBAR:
     // Knowing that scrollbars and statusbars are opaque improves
     // performance, because we create layers for them. This better be
     // true across all Windows themes! If it's not true, we should
     // paint an opaque background for them to make it true!
     return eOpaque;
+  case NS_THEME_WIN_GLASS:
+  case NS_THEME_WIN_BORDERLESS_GLASS:
+    return eTransparent;
   }
 
   HANDLE theme = GetTheme(aWidgetType);
   // For the classic theme we don't really have a way of knowing
   if (!theme)
     return eUnknownTransparency;
 
   PRInt32 part, state;