зеркало из https://github.com/mozilla/gecko-dev.git
Bug 897105 - Part 4: Build display items and layers for sticky positioned elements. r=roc
This commit is contained in:
Родитель
5eef149568
Коммит
d5b2deaa8e
|
@ -44,6 +44,7 @@
|
|||
#include "ImageLayers.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "nsCanvasFrame.h"
|
||||
#include "StickyScrollContainer.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
@ -3133,42 +3134,29 @@ nsDisplayFixedPosition::~nsDisplayFixedPosition() {
|
|||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
void nsDisplayFixedPosition::SetFixedPositionLayerData(Layer* const aLayer,
|
||||
nsIFrame* aViewportFrame,
|
||||
nsSize aViewportSize,
|
||||
nsPresContext* aPresContext,
|
||||
const ContainerParameters& aContainerParameters) {
|
||||
nsRefPtr<Layer> layer =
|
||||
nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters);
|
||||
// Find out the rect of the viewport frame relative to the reference frame.
|
||||
// This, in conjunction with the container scale, will correspond to the
|
||||
// coordinate-space of the built layer.
|
||||
float factor = aPresContext->AppUnitsPerDevPixel();
|
||||
nsPoint origin = aViewportFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
||||
LayerRect anchorRect(NSAppUnitsToFloatPixels(origin.x, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(origin.y, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(aViewportSize.width, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(aViewportSize.height, factor) *
|
||||
aContainerParameters.mYScale);
|
||||
|
||||
// Work out the anchor point for this fixed position layer. We assume that
|
||||
// any positioning set (left/top/right/bottom) indicates that the
|
||||
// corresponding side of its container should be the anchor point,
|
||||
// defaulting to top-left.
|
||||
nsIFrame* viewportFrame = mFixedPosFrame->GetParent();
|
||||
nsPresContext *presContext = viewportFrame->PresContext();
|
||||
|
||||
// Fixed position frames are reflowed into the scroll-port size if one has
|
||||
// been set.
|
||||
nsSize containingBlockSize = viewportFrame->GetSize();
|
||||
if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
containingBlockSize = presContext->PresShell()->
|
||||
GetScrollPositionClampingScrollPortSize();
|
||||
}
|
||||
|
||||
// Find out the rect of the viewport frame relative to the reference frame.
|
||||
// This, in conjunction with the container scale, will correspond to the
|
||||
// coordinate-space of the built layer.
|
||||
float factor = presContext->AppUnitsPerDevPixel();
|
||||
nsPoint origin = viewportFrame->GetOffsetToCrossDoc(ReferenceFrame());
|
||||
LayerRect anchorRect(NSAppUnitsToFloatPixels(origin.x, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(origin.y, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(containingBlockSize.width, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(containingBlockSize.height, factor) *
|
||||
aContainerParameters.mYScale);
|
||||
|
||||
LayerPoint anchor = anchorRect.TopLeft();
|
||||
|
||||
const nsStylePosition* position = mFixedPosFrame->StylePosition();
|
||||
|
@ -3177,11 +3165,11 @@ nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
if (position->mOffset.GetBottomUnit() != eStyleUnit_Auto)
|
||||
anchor.y = anchorRect.YMost();
|
||||
|
||||
layer->SetFixedPositionAnchor(anchor);
|
||||
aLayer->SetFixedPositionAnchor(anchor);
|
||||
|
||||
// Also make sure the layer is aware of any fixed position margins that have
|
||||
// been set.
|
||||
nsMargin fixedMargins = presContext->PresShell()->GetContentDocumentFixedPositionMargins();
|
||||
nsMargin fixedMargins = aPresContext->PresShell()->GetContentDocumentFixedPositionMargins();
|
||||
LayerMargin fixedLayerMargins(NSAppUnitsToFloatPixels(fixedMargins.top, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(fixedMargins.right, factor) *
|
||||
|
@ -3203,7 +3191,29 @@ nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
|||
fixedLayerMargins.top = -1;
|
||||
}
|
||||
|
||||
layer->SetFixedPositionMargins(fixedLayerMargins);
|
||||
aLayer->SetFixedPositionMargins(fixedLayerMargins);
|
||||
}
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplayFixedPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters) {
|
||||
nsRefPtr<Layer> layer =
|
||||
nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters);
|
||||
|
||||
nsIFrame* viewportFrame = mFixedPosFrame->GetParent();
|
||||
nsPresContext *presContext = viewportFrame->PresContext();
|
||||
|
||||
// Fixed position frames are reflowed into the scroll-port size if one has
|
||||
// been set.
|
||||
nsSize viewportSize = viewportFrame->GetSize();
|
||||
if (presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
viewportSize = presContext->PresShell()->
|
||||
GetScrollPositionClampingScrollPortSize();
|
||||
}
|
||||
|
||||
SetFixedPositionLayerData(layer, viewportFrame, viewportSize, presContext,
|
||||
aContainerParameters);
|
||||
|
||||
return layer.forget();
|
||||
}
|
||||
|
@ -3221,6 +3231,76 @@ bool nsDisplayFixedPosition::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayI
|
|||
return true;
|
||||
}
|
||||
|
||||
nsDisplayStickyPosition::nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame,
|
||||
nsIFrame* aStickyPosFrame,
|
||||
nsDisplayList* aList)
|
||||
: nsDisplayFixedPosition(aBuilder, aFrame, aStickyPosFrame, aList) {
|
||||
MOZ_COUNT_CTOR(nsDisplayStickyPosition);
|
||||
}
|
||||
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
nsDisplayStickyPosition::~nsDisplayStickyPosition() {
|
||||
MOZ_COUNT_DTOR(nsDisplayStickyPosition);
|
||||
}
|
||||
#endif
|
||||
|
||||
already_AddRefed<Layer>
|
||||
nsDisplayStickyPosition::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters) {
|
||||
nsRefPtr<Layer> layer =
|
||||
nsDisplayOwnLayer::BuildLayer(aBuilder, aManager, aContainerParameters);
|
||||
|
||||
StickyScrollContainer* stickyScrollContainer = StickyScrollContainer::
|
||||
GetStickyScrollContainerForFrame(mFrame);
|
||||
if (!stickyScrollContainer) {
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
nsIFrame* scrollFrame = do_QueryFrame(stickyScrollContainer->ScrollFrame());
|
||||
nsPresContext* presContext = scrollFrame->PresContext();
|
||||
|
||||
// Sticky position frames whose scroll frame is the root scroll frame are
|
||||
// reflowed into the scroll-port size if one has been set.
|
||||
nsSize scrollFrameSize = scrollFrame->GetSize();
|
||||
if (scrollFrame == presContext->PresShell()->GetRootScrollFrame() &&
|
||||
presContext->PresShell()->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
scrollFrameSize = presContext->PresShell()->
|
||||
GetScrollPositionClampingScrollPortSize();
|
||||
}
|
||||
|
||||
SetFixedPositionLayerData(layer, scrollFrame, scrollFrameSize, presContext,
|
||||
aContainerParameters);
|
||||
|
||||
ViewID scrollId = nsLayoutUtils::FindOrCreateIDFor(
|
||||
stickyScrollContainer->ScrollFrame()->GetScrolledFrame()->GetContent());
|
||||
|
||||
float factor = presContext->AppUnitsPerDevPixel();
|
||||
nsRect outer;
|
||||
nsRect inner;
|
||||
stickyScrollContainer->GetScrollRanges(mFrame, &outer, &inner);
|
||||
LayerRect stickyOuter(NSAppUnitsToFloatPixels(outer.x, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(outer.y, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(outer.width, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(outer.height, factor) *
|
||||
aContainerParameters.mYScale);
|
||||
LayerRect stickyInner(NSAppUnitsToFloatPixels(inner.x, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(inner.y, factor) *
|
||||
aContainerParameters.mYScale,
|
||||
NSAppUnitsToFloatPixels(inner.width, factor) *
|
||||
aContainerParameters.mXScale,
|
||||
NSAppUnitsToFloatPixels(inner.height, factor) *
|
||||
aContainerParameters.mYScale);
|
||||
layer->SetStickyPositionData(scrollId, stickyOuter, stickyInner);
|
||||
|
||||
return layer.forget();
|
||||
}
|
||||
|
||||
nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayList* aList,
|
||||
nsIFrame* aForFrame,
|
||||
|
|
|
@ -2569,9 +2569,30 @@ public:
|
|||
NS_DISPLAY_DECL_NAME("FixedPosition", TYPE_FIXED_POSITION)
|
||||
|
||||
protected:
|
||||
void SetFixedPositionLayerData(Layer* const aLayer, nsIFrame* aViewportFrame,
|
||||
nsSize aViewportSize, nsPresContext* aPresContext,
|
||||
const ContainerParameters& aContainerParameters);
|
||||
nsIFrame* mFixedPosFrame;
|
||||
};
|
||||
|
||||
/**
|
||||
* A display item used to represent sticky position elements. The contents
|
||||
* gets its own layer and creates a stacking context, and the layer will have
|
||||
* position-related metadata set on it.
|
||||
*/
|
||||
class nsDisplayStickyPosition : public nsDisplayFixedPosition {
|
||||
public:
|
||||
nsDisplayStickyPosition(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsIFrame* aStickyPosFrame, nsDisplayList* aList);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayStickyPosition();
|
||||
#endif
|
||||
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters) MOZ_OVERRIDE;
|
||||
};
|
||||
|
||||
/**
|
||||
* This potentially creates a layer for the given list of items, whose
|
||||
* visibility is determined by the displayport for the given frame instead of
|
||||
|
|
|
@ -1736,6 +1736,12 @@ WrapPreserve3DListInternal(nsIFrame* aFrame, nsDisplayListBuilder *aBuilder, nsD
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsScrollFrameActive(nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
return aScrollableFrame && aScrollableFrame->IsScrollingActive();
|
||||
}
|
||||
|
||||
static nsresult
|
||||
WrapPreserve3DList(nsIFrame* aFrame, nsDisplayListBuilder* aBuilder, nsDisplayList *aList)
|
||||
{
|
||||
|
@ -1813,10 +1819,14 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
|
||||
bool useOpacity = HasOpacity() && !nsSVGUtils::CanOptimizeOpacity(this);
|
||||
bool usingSVGEffects = nsSVGIntegrationUtils::UsingEffectsForFrame(this);
|
||||
bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
|
||||
IsScrollFrameActive(nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
|
||||
nsLayoutUtils::SCROLLABLE_SAME_DOC |
|
||||
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
|
||||
|
||||
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
||||
|
||||
if (isTransformed || useOpacity || usingSVGEffects) {
|
||||
if (isTransformed || useOpacity || usingSVGEffects || useStickyPosition) {
|
||||
// We don't need to pass ancestor clipping down to our children;
|
||||
// everything goes inside a display item's child list, and the display
|
||||
// item itself will be clipped.
|
||||
|
@ -1935,6 +1945,13 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayOpacity(aBuilder, this, &resultList));
|
||||
}
|
||||
/* If we have sticky positioning, wrap it in a sticky position item.
|
||||
*/
|
||||
if (useStickyPosition) {
|
||||
resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayStickyPosition(aBuilder, this, this,
|
||||
&resultList));
|
||||
}
|
||||
|
||||
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
|
||||
* everything in an nsDisplayTransform. If there's nothing in the list, don't add
|
||||
|
@ -1962,13 +1979,6 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
|||
aList->AppendToTop(&resultList);
|
||||
}
|
||||
|
||||
static bool
|
||||
IsRootScrollFrameActive(nsIPresShell* aPresShell)
|
||||
{
|
||||
nsIScrollableFrame* sf = aPresShell->GetRootScrollFrameAsScrollable();
|
||||
return sf && sf->IsScrollingActive();
|
||||
}
|
||||
|
||||
static nsDisplayItem*
|
||||
WrapInWrapList(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList)
|
||||
|
@ -2127,7 +2137,8 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
|||
// active, that's pointless and the extra layer(s) created may be wasteful.
|
||||
bool buildFixedPositionItem = disp->mPosition == NS_STYLE_POSITION_FIXED &&
|
||||
!child->GetParent()->GetParent() && !aBuilder->IsInFixedPosition() &&
|
||||
IsRootScrollFrameActive(PresContext()->PresShell()) && !isSVG;
|
||||
IsScrollFrameActive(PresContext()->PresShell()->GetRootScrollFrameAsScrollable()) &&
|
||||
!isSVG;
|
||||
|
||||
nsDisplayListBuilder::AutoBuildingDisplayList
|
||||
buildingForChild(aBuilder, child, pseudoStackingContext, buildFixedPositionItem);
|
||||
|
|
|
@ -30,14 +30,14 @@ fuzzy-if(Android,2,4) == right-3.html right-3-ref.html
|
|||
== scrollframe-reflow-1.html scrollframe-reflow-1-ref.html
|
||||
== scrollframe-reflow-2.html scrollframe-reflow-2-ref.html
|
||||
== scrollframe-auto-1.html scrollframe-auto-1-ref.html
|
||||
== stacking-context-1.html stacking-context-1-ref.html
|
||||
fuzzy-if(Android,1,3) == stacking-context-1.html stacking-context-1-ref.html
|
||||
== top-bottom-1.html top-bottom-1-ref.html
|
||||
== top-bottom-2.html top-bottom-2-ref.html
|
||||
== top-bottom-3.html top-bottom-3-ref.html
|
||||
== left-right-1.html left-right-1-ref.html
|
||||
== left-right-2.html left-right-2-ref.html
|
||||
== left-right-3.html left-right-3-ref.html
|
||||
== containing-block-1.html containing-block-1-ref.html
|
||||
fuzzy-if(Android,4,1) == containing-block-1.html containing-block-1-ref.html
|
||||
== overconstrained-1.html overconstrained-1-ref.html
|
||||
== overconstrained-2.html overconstrained-2-ref.html
|
||||
== overconstrained-3.html overconstrained-3-ref.html
|
||||
|
|
Загрузка…
Ссылка в новой задаче