Fix classic scrollbars getting occluded with containerless scrolling. (bug 1100756, r=roc)

--HG--
extra : rebase_source : fcf95ab0c435d9c29a6a3552fe05d7f1ad3bc0ec
This commit is contained in:
David Anderson 2015-01-13 23:55:17 -08:00
parent b83d21c58c
commit 02248cee29
6 changed files with 48 additions and 13 deletions

View File

@ -208,6 +208,7 @@ Layer::Layer(LayerManager* aManager, void* aImplData) :
mStickyPositionData(nullptr),
mScrollbarTargetId(FrameMetrics::NULL_SCROLL_ID),
mScrollbarDirection(ScrollDirection::NONE),
mIsScrollbarContainer(false),
mDebugColorIndex(0),
mAnimationGeneration(0)
{}

View File

@ -1204,6 +1204,15 @@ public:
}
}
// Set during construction for the container layer of scrollbar components.
void SetIsScrollbarContainer()
{
if (!mIsScrollbarContainer) {
mIsScrollbarContainer = true;
Mutated();
}
}
// These getters can be used anytime.
float GetOpacity() { return mOpacity; }
gfx::CompositionOp GetMixBlendMode() const { return mMixBlendMode; }
@ -1238,6 +1247,7 @@ public:
const LayerRect& GetStickyScrollRangeInner() { return mStickyPositionData->mInner; }
FrameMetrics::ViewID GetScrollbarTargetContainerId() { return mScrollbarTargetId; }
ScrollDirection GetScrollbarDirection() { return mScrollbarDirection; }
bool IsScrollbarContainer() { return mIsScrollbarContainer; }
Layer* GetMaskLayer() const { return mMaskLayer; }
@ -1676,6 +1686,7 @@ protected:
nsAutoPtr<StickyPositionData> mStickyPositionData;
FrameMetrics::ViewID mScrollbarTargetId;
ScrollDirection mScrollbarDirection;
bool mIsScrollbarContainer;
DebugOnly<uint32_t> mDebugColorIndex;
// If this layer is used for OMTA, then this counter is used to ensure we
// stay in sync with the animation manager

View File

@ -3634,7 +3634,7 @@ ContainerState::PostprocessRetainedLayers(nsIntRegion* aOpaqueRegionForContainer
if (hideAll) {
e->mVisibleRegion.SetEmpty();
} else {
} else if (!e->mLayer->IsScrollbarContainer()) {
const nsIntRect* clipRect = e->mLayer->GetClipRect();
if (clipRect && opaqueRegionForContainer >= 0 &&
opaqueRegions[opaqueRegionForContainer].mOpaqueRegion.Contains(*clipRect)) {

View File

@ -3982,6 +3982,9 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
if (mFlags & HORIZONTAL_SCROLLBAR) {
layer->SetScrollbarData(mScrollTarget, Layer::ScrollDirection::HORIZONTAL);
}
if (mFlags & SCROLLBAR_CONTAINER) {
layer->SetIsScrollbarContainer();
}
if (mFlags & GENERATE_SUBDOC_INVALIDATIONS) {
mFrame->PresContext()->SetNotifySubDocInvalidationData(layer);

View File

@ -2955,7 +2955,8 @@ public:
GENERATE_SUBDOC_INVALIDATIONS = 0x01,
VERTICAL_SCROLLBAR = 0x02,
HORIZONTAL_SCROLLBAR = 0x04,
GENERATE_SCROLLABLE_LAYER = 0x08
GENERATE_SCROLLABLE_LAYER = 0x08,
SCROLLBAR_CONTAINER = 0x10
};
/**

View File

@ -2534,19 +2534,28 @@ MaxZIndexInListOfItemsContainedInFrame(nsDisplayList* aList, nsIFrame* aFrame)
return maxZIndex;
}
static const uint32_t APPEND_OWN_LAYER = 0x1;
static const uint32_t APPEND_POSITIONED = 0x2;
static const uint32_t APPEND_SCROLLBAR_CONTAINER = 0x4;
static void
AppendToTop(nsDisplayListBuilder* aBuilder, const nsDisplayListSet& aLists,
nsDisplayList* aSource, nsIFrame* aSourceFrame, bool aOwnLayer,
bool aPositioned)
nsDisplayList* aSource, nsIFrame* aSourceFrame, uint32_t aFlags)
{
if (aSource->IsEmpty())
return;
nsDisplayWrapList* newItem = aOwnLayer?
new (aBuilder) nsDisplayOwnLayer(aBuilder, aSourceFrame, aSource) :
new (aBuilder) nsDisplayWrapList(aBuilder, aSourceFrame, aSource);
nsDisplayWrapList* newItem;
if (aFlags & APPEND_OWN_LAYER) {
uint32_t flags = (aFlags & APPEND_SCROLLBAR_CONTAINER)
? nsDisplayOwnLayer::SCROLLBAR_CONTAINER
: 0;
newItem = new (aBuilder) nsDisplayOwnLayer(aBuilder, aSourceFrame, aSource, flags);
} else {
newItem = new (aBuilder) nsDisplayWrapList(aBuilder, aSourceFrame, aSource);
}
if (aPositioned) {
if (aFlags & APPEND_POSITIONED) {
// We want overlay scrollbars to always be on top of the scrolled content,
// but we don't want them to unnecessarily cover overlapping elements from
// outside our scroll frame.
@ -2629,11 +2638,14 @@ ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
for (uint32_t i = 0; i < scrollParts.Length(); ++i) {
uint32_t flags = 0;
uint32_t appendToTopFlags = 0;
if (scrollParts[i] == mVScrollbarBox) {
flags |= nsDisplayOwnLayer::VERTICAL_SCROLLBAR;
appendToTopFlags |= APPEND_SCROLLBAR_CONTAINER;
}
if (scrollParts[i] == mHScrollbarBox) {
flags |= nsDisplayOwnLayer::HORIZONTAL_SCROLLBAR;
appendToTopFlags |= APPEND_SCROLLBAR_CONTAINER;
}
// The display port doesn't necessarily include the scrollbars, so just
@ -2653,13 +2665,18 @@ ScrollFrameHelper::AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
// Always create layers for overlay scrollbars so that we don't create a
// giant layer covering the whole scrollport if both scrollbars are visible.
bool isOverlayScrollbar = (flags != 0) && overlayScrollbars;
bool createLayer = aCreateLayer || isOverlayScrollbar;
if (aCreateLayer || isOverlayScrollbar) {
appendToTopFlags |= APPEND_OWN_LAYER;
}
if (aPositioned) {
appendToTopFlags |= APPEND_POSITIONED;
}
// DISPLAY_CHILD_FORCE_STACKING_CONTEXT put everything into
// partList.PositionedDescendants().
::AppendToTop(aBuilder, aLists,
partList.PositionedDescendants(), scrollParts[i],
createLayer, aPositioned);
appendToTopFlags);
}
}
@ -3143,9 +3160,11 @@ ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer,
nsRect* aClipRect,
nsTArray<FrameMetrics>* aOutput) const
{
nsRect scrollport = mScrollPort +
mOuter->GetOffsetToCrossDoc(aContainerReferenceFrame);
if (mAddClipRectToLayer) {
nsPoint toReferenceFrame = mOuter->GetOffsetToCrossDoc(aContainerReferenceFrame);
nsRect scrollport = mScrollPort + toReferenceFrame;
if (!gfxPrefs::LayoutUseContainersForRootFrames() || mAddClipRectToLayer) {
// When using containers, the container layer contains the clip. Otherwise
// we always include the clip.
*aClipRect = scrollport;
}