From fe64e07564dacf147fb3205b9efdce7827121ec9 Mon Sep 17 00:00:00 2001 From: "neil%parkwaycc.co.uk" Date: Thu, 10 May 2007 15:46:42 +0000 Subject: [PATCH] Bug 375403 originally started off as a simple request to enable window translucency when windows or popups use opacity, alpha transparent background or non-zero border radius but mutated to include refactoring non zero side testing r+sr=roc --- layout/base/nsDisplayList.cpp | 37 ++-------------- layout/base/nsLayoutUtils.cpp | 55 ++++++++++++++++++++++++ layout/base/nsLayoutUtils.h | 14 ++++++ layout/generic/nsContainerFrame.cpp | 31 +------------ layout/xul/base/src/nsMenuPopupFrame.cpp | 10 +---- 5 files changed, 77 insertions(+), 70 deletions(-) diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 96bcdbabd89..79d8a94aada 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -465,35 +465,6 @@ void nsDisplayList::Sort(nsDisplayListBuilder* aBuilder, ::Sort(this, Count(), aCmp, aClosure); } -static PRBool -NonZeroStyleCoord(const nsStyleCoord& aCoord) { - switch (aCoord.GetUnit()) { - case eStyleUnit_Percent: - return aCoord.GetPercentValue() > 0; - case eStyleUnit_Coord: - return aCoord.GetCoordValue() > 0; - case eStyleUnit_Null: - return PR_FALSE; - default: - return PR_TRUE; - } -} - -static PRBool -HasNonZeroSide(const nsStyleSides& aSides) { - nsStyleCoord coord; - aSides.GetTop(coord); - if (NonZeroStyleCoord(coord)) return PR_TRUE; - aSides.GetRight(coord); - if (NonZeroStyleCoord(coord)) return PR_TRUE; - aSides.GetBottom(coord); - if (NonZeroStyleCoord(coord)) return PR_TRUE; - aSides.GetLeft(coord); - if (NonZeroStyleCoord(coord)) return PR_TRUE; - - return PR_FALSE; -} - PRBool nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) { // theme background overrides any other background @@ -506,7 +477,7 @@ nsDisplayBackground::IsOpaque(nsDisplayListBuilder* aBuilder) { nsCSSRendering::FindBackground(mFrame->PresContext(), mFrame, &bg, &isCanvas); if (!hasBG || (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) || bg->mBackgroundClip != NS_STYLE_BG_CLIP_BORDER || - HasNonZeroSide(mFrame->GetStyleBorder()->mBorderRadius) || + nsLayoutUtils::HasNonZeroSide(mFrame->GetStyleBorder()->mBorderRadius) || NS_GET_A(bg->mBackgroundColor) < 255) return PR_FALSE; return PR_TRUE; @@ -525,7 +496,7 @@ nsDisplayBackground::IsUniform(nsDisplayListBuilder* aBuilder) { if (!hasBG) return PR_TRUE; if ((bg->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) && - !HasNonZeroSide(mFrame->GetStyleBorder()->mBorderRadius) && + !nsLayoutUtils::HasNonZeroSide(mFrame->GetStyleBorder()->mBorderRadius) && bg->mBackgroundClip == NS_STYLE_BG_CLIP_BORDER) return PR_TRUE; return PR_FALSE; @@ -594,7 +565,7 @@ nsDisplayOutline::OptimizeVisibility(nsDisplayListBuilder* aBuilder, const nsStyleOutline* outline = mFrame->GetStyleOutline(); nsPoint origin = aBuilder->ToReferenceFrame(mFrame); if (nsRect(origin, mFrame->GetSize()).Contains(aVisibleRegion->GetBounds()) && - !HasNonZeroSide(outline->mOutlineRadius)) { + !nsLayoutUtils::HasNonZeroSide(outline->mOutlineRadius)) { nscoord outlineOffset; outline->GetOutlineOffset(outlineOffset); if (outlineOffset >= 0) { @@ -626,7 +597,7 @@ nsDisplayBorder::OptimizeVisibility(nsDisplayListBuilder* aBuilder, nsRect contentRect = GetBounds(aBuilder); contentRect.Deflate(border->GetBorder()); if (contentRect.Contains(aVisibleRegion->GetBounds()) && - !HasNonZeroSide(border->mBorderRadius)) { + !nsLayoutUtils::HasNonZeroSide(border->mBorderRadius)) { // the visible region is entirely inside the content rect, and no part // of the border is rendered inside the content rect, so we are not // visible diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 6d9d80ca27a..639861238c3 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -65,6 +65,7 @@ #include "gfxRect.h" #include "nsIImage.h" #include "nsIInterfaceRequestorUtils.h" +#include "nsCSSRendering.h" #ifdef MOZ_SVG_FOREIGNOBJECT #include "nsSVGForeignObjectFrame.h" @@ -2176,3 +2177,57 @@ nsLayoutUtils::CharsToCoord(const nsStyleCoord& aStyle, aRenderingContext->GetWidth('M', fontWidth); return aStyle.GetIntValue() * fontWidth; } + +static PRBool NonZeroStyleCoord(const nsStyleCoord& aCoord) +{ + switch (aCoord.GetUnit()) { + case eStyleUnit_Percent: + return aCoord.GetPercentValue() > 0; + case eStyleUnit_Coord: + return aCoord.GetCoordValue() > 0; + case eStyleUnit_Null: + return PR_FALSE; + default: + return PR_TRUE; + } +} + +/* static */ PRBool +nsLayoutUtils::HasNonZeroSide(const nsStyleSides& aSides) +{ + nsStyleCoord coord; + aSides.GetTop(coord); + if (NonZeroStyleCoord(coord)) return PR_TRUE; + aSides.GetRight(coord); + if (NonZeroStyleCoord(coord)) return PR_TRUE; + aSides.GetBottom(coord); + if (NonZeroStyleCoord(coord)) return PR_TRUE; + aSides.GetLeft(coord); + if (NonZeroStyleCoord(coord)) return PR_TRUE; + return PR_FALSE; +} + +/* static */ PRBool +nsLayoutUtils::FrameHasTransparency(nsIFrame* aFrame) { + if (aFrame->GetStyleContext()->GetStyleDisplay()->mOpacity < 1.0f) + return PR_TRUE; + + const nsStyleBorder* border = aFrame->GetStyleContext()->GetStyleBorder(); + if (HasNonZeroSide(border->mBorderRadius)) + return PR_TRUE; + + if (aFrame->IsThemed()) + return PR_FALSE; + + PRBool isCanvas; + const nsStyleBackground* bg; + if (!nsCSSRendering::FindBackground(aFrame->PresContext(), aFrame, &bg, &isCanvas)) + return PR_TRUE; + if (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) + return PR_TRUE; + if (NS_GET_A(bg->mBackgroundColor) < 255) + return PR_TRUE; + if (bg->mBackgroundClip != NS_STYLE_BG_CLIP_BORDER) + return PR_TRUE; + return PR_FALSE; +} diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 34bffd98ec9..126ad2cbb48 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -676,6 +676,20 @@ public: static nscoord CharsToCoord(const nsStyleCoord& aStyle, nsIRenderingContext* aRenderingContext, nsStyleContext* aStyleContext); + + /** + * Determine if any style coordinate is nonzero + * @param aCoord the style sides + * @return PR_TRUE unless all the coordinates are 0%, 0 or null. + */ + static PRBool HasNonZeroSide(const nsStyleSides& aSides); + + /** + * Determine if a widget is likely to require transparency or translucency. + * @param aFrame the frame of a , or element. + * @return a value suitable for passing to SetWindowTranslucency + */ + static PRBool FrameHasTransparency(nsIFrame* aFrame); }; #endif // nsLayoutUtils_h__ diff --git a/layout/generic/nsContainerFrame.cpp b/layout/generic/nsContainerFrame.cpp index 816aaacee79..2339aa4c5bb 100644 --- a/layout/generic/nsContainerFrame.cpp +++ b/layout/generic/nsContainerFrame.cpp @@ -394,37 +394,10 @@ nsContainerFrame::PositionFrameView(nsIFrame* aKidFrame) vm->MoveViewTo(view, pt.x, pt.y); } -// This code is duplicated in nsDisplayList.cpp. We'll remove the duplication -// when we remove all this view sync code. -static PRBool -NonZeroStyleCoord(const nsStyleCoord& aCoord) { - switch (aCoord.GetUnit()) { - case eStyleUnit_Percent: - return aCoord.GetPercentValue() > 0; - case eStyleUnit_Coord: - return aCoord.GetCoordValue() > 0; - case eStyleUnit_Null: - return PR_FALSE; - default: - return PR_TRUE; - } -} - static PRBool HasNonZeroBorderRadius(nsStyleContext* aStyleContext) { const nsStyleBorder* border = aStyleContext->GetStyleBorder(); - - nsStyleCoord coord; - border->mBorderRadius.GetTop(coord); - if (NonZeroStyleCoord(coord)) return PR_TRUE; - border->mBorderRadius.GetRight(coord); - if (NonZeroStyleCoord(coord)) return PR_TRUE; - border->mBorderRadius.GetBottom(coord); - if (NonZeroStyleCoord(coord)) return PR_TRUE; - border->mBorderRadius.GetLeft(coord); - if (NonZeroStyleCoord(coord)) return PR_TRUE; - - return PR_FALSE; + return nsLayoutUtils::HasNonZeroSide(border->mBorderRadius); } static void @@ -473,7 +446,7 @@ SyncFrameViewGeometryDependentProperties(nsPresContext* aPresContext, // don't proceed unless this is the root view // (sometimes the non-root-view is a canvas) if (aView->HasWidget() && aView == rootView) { - viewHasTransparentContent = hasBG && (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT); + viewHasTransparentContent = nsLayoutUtils::FrameHasTransparency(aFrame); aView->GetWidget()->SetWindowTranslucency(viewHasTransparentContent); } } diff --git a/layout/xul/base/src/nsMenuPopupFrame.cpp b/layout/xul/base/src/nsMenuPopupFrame.cpp index ed980585fa4..4708db528f8 100644 --- a/layout/xul/base/src/nsMenuPopupFrame.cpp +++ b/layout/xul/base/src/nsMenuPopupFrame.cpp @@ -220,14 +220,8 @@ nsMenuPopupFrame::CreateWidgetForView(nsIView* aView) widgetData.mBorderStyle = eBorderStyle_default; widgetData.clipSiblings = PR_TRUE; - PRBool isCanvas; - const nsStyleBackground* bg; - PRBool hasBG = - nsCSSRendering::FindBackground(PresContext(), this, &bg, &isCanvas); - PRBool viewHasTransparentContent = hasBG && - (bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) && - !GetStyleDisplay()->mAppearance && !mInContentShell; - + PRBool viewHasTransparentContent = !mInContentShell && + nsLayoutUtils::FrameHasTransparency(this); nsIContent* parentContent = GetContent()->GetParent(); nsIAtom *tag = nsnull; if (parentContent)