Bug 165149. Make children of a scrolled element inherit style directly from the element instead of via the scrolled frames. Add a new view property to indicate that the view is painted on a uniform background and use it to optimize scrolling, so that a scrolled element with a uniform background color can still be scrolled using bitblits. r+sr=dbaron

This commit is contained in:
uid502 2003-10-11 12:00:05 +00:00
parent 886718db18
commit 7eecd9a0ef
11 changed files with 160 additions and 20 deletions

View File

@ -6617,6 +6617,15 @@ nsCSSFrameConstructor::ResolveStyleContext(nsIPresContext* aPresContext,
// Resolve the style context based on the content object and the parent
// style context
nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
// skip past any parents that are scrolled-content. We want to inherit directly
// from the outer scroll frame.
nsCOMPtr<nsIAtom> pseudo;
while (parentStyleContext && (pseudo = parentStyleContext->GetPseudoType()) ==
nsCSSAnonBoxes::scrolledContent) {
parentStyleContext = parentStyleContext->GetParent();
}
if (aContent->IsContentOfType(nsIContent::eELEMENT)) {
return aPresContext->ResolveStyleContextFor(aContent, parentStyleContext);
} else {

View File

@ -548,11 +548,41 @@ SyncFrameViewGeometryDependentProperties(nsIPresContext* aPresContext,
// view's contents should be repainted and not bitblt'd
vm->SetViewBitBltEnabled(aView, !fixedBackground);
nsCOMPtr<nsIAtom> pseudo = aFrame->GetStyleContext()->GetPseudoType();
// If the frame has a solid background color, 'background-clip:border',
// and it's a kind of frame that paints its background, and rounded borders aren't
// clipping the background, then it's opaque.
PRBool viewHasTransparentContent =
!hasBG ||
(bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) ||
!aFrame->CanPaintBackground() ||
HasNonZeroBorderRadius(aStyleContext);
!(hasBG && !(bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) &&
bg->mBackgroundClip == NS_STYLE_BG_CLIP_BORDER &&
aFrame->CanPaintBackground() &&
!HasNonZeroBorderRadius(aStyleContext));
PRBool drawnOnUniformField = PR_FALSE;
if (pseudo == nsCSSAnonBoxes::scrolledContent) {
// If the nsGfxScrollFrame draws a solid unclipped background
// color, and nothing else, then tell the view system that we're
// drawn on a uniform field. Note that it's OK if the background
// is clipped to the padding area, since the scrollport is within
// the borders.
nsIFrame* scrollFrame = aFrame->GetParent();
nsCOMPtr<nsIAtom> parentPseudo;
while ((parentPseudo = scrollFrame->GetStyleContext()->GetPseudoType())
== nsCSSAnonBoxes::scrolledContent) {
scrollFrame = scrollFrame->GetParent();
}
PRBool scrollFrameIsCanvas;
const nsStyleBackground* scrollFrameBG;
PRBool scrollFrameHasBG =
nsCSSRendering::FindBackground(aPresContext, scrollFrame, &scrollFrameBG,
&scrollFrameIsCanvas);
drawnOnUniformField = scrollFrameHasBG &&
!(scrollFrameBG->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) &&
(scrollFrameBG->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) &&
!HasNonZeroBorderRadius(scrollFrame->GetStyleContext());
}
aView->SetHasUniformBackground(drawnOnUniformField);
if (isCanvas) {
nsIView* rootView;

View File

@ -4437,6 +4437,9 @@ GetNextSiblingAcrossLines(nsIPresContext *aPresContext, nsIFrame *aFrame)
*
* Also correct for the frame tree mangling that happens when we create
* wrappers for :before/:after.
*
* Also skip anonymous scrolled-content parents; inherit directly from the
* outer scroll frame.
*/
static nsresult
GetCorrectedParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
@ -4462,6 +4465,19 @@ GetCorrectedParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
} else {
parent = parent->GetParent();
}
parentPseudo = parent->GetStyleContext()->GetPseudoType();
}
// if this frame itself is not scrolled-content, then skip any scrolled-content
// parents since they're basically anonymous as far as the style system goes
if (parentPseudo == nsCSSAnonBoxes::scrolledContent) {
nsCOMPtr<nsIAtom> pseudo = aFrame->GetStyleContext()->GetPseudoType();
if (pseudo != nsCSSAnonBoxes::scrolledContent) {
do {
parent = parent->GetParent();
parentPseudo = parent->GetStyleContext()->GetPseudoType();
} while (parentPseudo == nsCSSAnonBoxes::scrolledContent);
}
}
if (parent->GetStateBits() & NS_FRAME_IS_SPECIAL) {

View File

@ -548,11 +548,41 @@ SyncFrameViewGeometryDependentProperties(nsIPresContext* aPresContext,
// view's contents should be repainted and not bitblt'd
vm->SetViewBitBltEnabled(aView, !fixedBackground);
nsCOMPtr<nsIAtom> pseudo = aFrame->GetStyleContext()->GetPseudoType();
// If the frame has a solid background color, 'background-clip:border',
// and it's a kind of frame that paints its background, and rounded borders aren't
// clipping the background, then it's opaque.
PRBool viewHasTransparentContent =
!hasBG ||
(bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) ||
!aFrame->CanPaintBackground() ||
HasNonZeroBorderRadius(aStyleContext);
!(hasBG && !(bg->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) &&
bg->mBackgroundClip == NS_STYLE_BG_CLIP_BORDER &&
aFrame->CanPaintBackground() &&
!HasNonZeroBorderRadius(aStyleContext));
PRBool drawnOnUniformField = PR_FALSE;
if (pseudo == nsCSSAnonBoxes::scrolledContent) {
// If the nsGfxScrollFrame draws a solid unclipped background
// color, and nothing else, then tell the view system that we're
// drawn on a uniform field. Note that it's OK if the background
// is clipped to the padding area, since the scrollport is within
// the borders.
nsIFrame* scrollFrame = aFrame->GetParent();
nsCOMPtr<nsIAtom> parentPseudo;
while ((parentPseudo = scrollFrame->GetStyleContext()->GetPseudoType())
== nsCSSAnonBoxes::scrolledContent) {
scrollFrame = scrollFrame->GetParent();
}
PRBool scrollFrameIsCanvas;
const nsStyleBackground* scrollFrameBG;
PRBool scrollFrameHasBG =
nsCSSRendering::FindBackground(aPresContext, scrollFrame, &scrollFrameBG,
&scrollFrameIsCanvas);
drawnOnUniformField = scrollFrameHasBG &&
!(scrollFrameBG->mBackgroundFlags & NS_STYLE_BG_COLOR_TRANSPARENT) &&
(scrollFrameBG->mBackgroundFlags & NS_STYLE_BG_IMAGE_NONE) &&
!HasNonZeroBorderRadius(scrollFrame->GetStyleContext());
}
aView->SetHasUniformBackground(drawnOnUniformField);
if (isCanvas) {
nsIView* rootView;

View File

@ -4437,6 +4437,9 @@ GetNextSiblingAcrossLines(nsIPresContext *aPresContext, nsIFrame *aFrame)
*
* Also correct for the frame tree mangling that happens when we create
* wrappers for :before/:after.
*
* Also skip anonymous scrolled-content parents; inherit directly from the
* outer scroll frame.
*/
static nsresult
GetCorrectedParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
@ -4462,6 +4465,19 @@ GetCorrectedParent(nsIPresContext* aPresContext, nsIFrame* aFrame,
} else {
parent = parent->GetParent();
}
parentPseudo = parent->GetStyleContext()->GetPseudoType();
}
// if this frame itself is not scrolled-content, then skip any scrolled-content
// parents since they're basically anonymous as far as the style system goes
if (parentPseudo == nsCSSAnonBoxes::scrolledContent) {
nsCOMPtr<nsIAtom> pseudo = aFrame->GetStyleContext()->GetPseudoType();
if (pseudo != nsCSSAnonBoxes::scrolledContent) {
do {
parent = parent->GetParent();
parentPseudo = parent->GetStyleContext()->GetPseudoType();
} while (parentPseudo == nsCSSAnonBoxes::scrolledContent);
}
}
if (parent->GetStateBits() & NS_FRAME_IS_SPECIAL) {

View File

@ -141,7 +141,6 @@
*|*::-moz-scrolled-content {
/* e.g., text inputs, select boxes */
background: inherit;
padding: inherit;
display: inherit;
-moz-box-orient: inherit;

View File

@ -6617,6 +6617,15 @@ nsCSSFrameConstructor::ResolveStyleContext(nsIPresContext* aPresContext,
// Resolve the style context based on the content object and the parent
// style context
nsStyleContext* parentStyleContext = aParentFrame->GetStyleContext();
// skip past any parents that are scrolled-content. We want to inherit directly
// from the outer scroll frame.
nsCOMPtr<nsIAtom> pseudo;
while (parentStyleContext && (pseudo = parentStyleContext->GetPseudoType()) ==
nsCSSAnonBoxes::scrolledContent) {
parentStyleContext = parentStyleContext->GetParent();
}
if (aContent->IsContentOfType(nsIContent::eELEMENT)) {
return aPresContext->ResolveStyleContextFor(aContent, parentStyleContext);
} else {

View File

@ -141,7 +141,6 @@
*|*::-moz-scrolled-content {
/* e.g., text inputs, select boxes */
background: inherit;
padding: inherit;
display: inherit;
-moz-box-orient: inherit;

View File

@ -74,6 +74,10 @@ enum nsViewVisibility {
//the view is transparent
#define NS_VIEW_FLAG_TRANSPARENT 0x0004
// The view is always painted onto a background consisting
// of a uniform field of opaque pixels.
#define NS_VIEW_FLAG_UNIFORM_BACKGROUND 0x0008
//indicates that the view should not be bitblt'd when moved
//or scrolled and instead must be repainted
#define NS_VIEW_FLAG_DONT_BITBLT 0x0010
@ -244,6 +248,23 @@ public:
*/
float GetOpacity() const { return mOpacity; }
/**
* Indicate that this view is always painted onto a uniform field of pixels. Thus,
* even if the view is transparent, it may still be bitblit scrollable because
* the background that shines through does not vary with position.
*/
void SetHasUniformBackground(PRBool aUniform) {
if (aUniform) {
mVFlags |= NS_VIEW_FLAG_UNIFORM_BACKGROUND;
} else {
mVFlags &= ~NS_VIEW_FLAG_UNIFORM_BACKGROUND;
}
}
PRBool HasUniformBackground() {
return mVFlags & NS_VIEW_FLAG_UNIFORM_BACKGROUND;
}
/**
* Set the view's link to client owned data.
* @param aData - data to associate with view. nsnull to disassociate

View File

@ -1135,7 +1135,7 @@ void nsViewManager::RenderViews(nsView *aRootView, nsIRenderingContext& aRC,
AddCoveringWidgetsToOpaqueRegion(opaqueRgn, mContext, aRootView);
nsRect finalTransparentRect;
OptimizeDisplayList(&displayList, aRegion, finalTransparentRect, opaqueRgn);
OptimizeDisplayList(&displayList, aRegion, finalTransparentRect, opaqueRgn, PR_FALSE);
#ifdef DEBUG_roc
// ShowDisplayList(&displayList);
@ -2867,13 +2867,22 @@ PRBool nsViewManager::CanScrollWithBitBlt(nsView* aView)
}
}
// We DO need to use OptimizeDisplayList here to eliminate views that are covered by views we know
// are opaque. Typically aView itself is opaque and we want to eliminate views behind aView, such as
// aView's parent, that aren't being scrolled and would otherwise cause us to decide not to blit.
// We DO need to use OptimizeDisplayList here to eliminate views
// that are covered by views we know are opaque. Typically aView's
// scrolled view is opaque and we want to eliminate views behind it,
// such as aView itself, that aren't being moved and would otherwise
// cause us to decide not to blit. Note that if for some view,
// view->HasUniformBackground(), that's also sufficient to ignore
// views behind 'view'; we've been promised that they produce only a
// uniform background, which is still blittable. So we can treat
// 'view' as opaque.
// (Of course it's possible that aView's parent is actually in front of aView (if aView has a negative
// z-index) but if so, this code still does the right thing. Yay for the display list based approach!)
OptimizeDisplayList(&displayList, nsRegion(r), finalTransparentRect, opaqueRegion);
// (Note that it's possible for aView's parent to actually be in
// front of aView (if aView has a negative z-index) but if so, this
// code still does the right thing. Yay for the display list based
// approach!)
OptimizeDisplayList(&displayList, nsRegion(r), finalTransparentRect, opaqueRegion, PR_TRUE);
PRBool anyUnscrolledViews = PR_FALSE;
PRBool anyUnblittableViews = PR_FALSE;
@ -3613,7 +3622,7 @@ PRBool nsViewManager::AddToDisplayList(nsView *aView,
*/
void nsViewManager::OptimizeDisplayList(nsAutoVoidArray* aDisplayList, const nsRegion& aDamageRegion,
nsRect& aFinalTransparentRect,
nsRegion &aOpaqueRegion)
nsRegion &aOpaqueRegion, PRBool aTreatUniformAsOpaque)
{
for (PRInt32 i = aDisplayList->Count() - 1; i >= 0; i--) {
DisplayListElement2* element = NS_STATIC_CAST(DisplayListElement2*, aDisplayList->ElementAt(i));
@ -3628,7 +3637,8 @@ void nsViewManager::OptimizeDisplayList(nsAutoVoidArray* aDisplayList, const nsR
element->mBounds = tmpRgn.GetBounds();
// a view is opaque if it is neither transparent nor transluscent
if (!(element->mFlags & (VIEW_TRANSPARENT | VIEW_TRANSLUCENT))) {
if (!(element->mFlags & (VIEW_TRANSPARENT | VIEW_TRANSLUCENT))
|| (element->mView->HasUniformBackground() && aTreatUniformAsOpaque)) {
aOpaqueRegion.Or(aOpaqueRegion, element->mBounds);
}
}

View File

@ -282,7 +282,8 @@ private:
nsRect& aDirtyRect, PRUint32 aFlags, nscoord aAbsX, nscoord aAbsY,
PRBool aAssumeIntersection);
void OptimizeDisplayList(nsAutoVoidArray* aDisplayList, const nsRegion& aDirtyRegion,
nsRect& aFinalTransparentRect, nsRegion& aOpaqueRgn);
nsRect& aFinalTransparentRect, nsRegion& aOpaqueRgn,
PRBool aTreatUniformAsOpaque);
// Remove redundant PUSH/POP_CLIP pairs.
void ComputeViewOffset(nsView *aView, nsPoint *aOrigin);