mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1147673 - Make display items know about their scroll clips. r=tn, r=roc
This commit is contained in:
parent
e1465366a4
commit
0b59e1f795
42
layout/base/DisplayItemScrollClip.cpp
Normal file
42
layout/base/DisplayItemScrollClip.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "DisplayItemScrollClip.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/* static */ bool
|
||||
DisplayItemScrollClip::IsAncestor(const DisplayItemScrollClip* aAncestor,
|
||||
const DisplayItemScrollClip* aDescendant)
|
||||
{
|
||||
if (!aAncestor) {
|
||||
// null means root.
|
||||
return true;
|
||||
}
|
||||
|
||||
for (const DisplayItemScrollClip* sc = aDescendant; sc; sc = sc->mCrossStackingContextParent) {
|
||||
if (sc == aAncestor) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* static */ nsCString
|
||||
DisplayItemScrollClip::ToString(const DisplayItemScrollClip* aScrollClip)
|
||||
{
|
||||
nsAutoCString str;
|
||||
for (const DisplayItemScrollClip* scrollClip = aScrollClip;
|
||||
scrollClip; scrollClip = scrollClip->mParent) {
|
||||
str.AppendPrintf("<%s>", scrollClip->mClip ? scrollClip->mClip->ToString().get() : "null");
|
||||
if (scrollClip->mParent) {
|
||||
str.Append(" ");
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
123
layout/base/DisplayItemScrollClip.h
Normal file
123
layout/base/DisplayItemScrollClip.h
Normal file
@ -0,0 +1,123 @@
|
||||
/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef DISPLAYITEMSCROLLCLIP_H_
|
||||
#define DISPLAYITEMSCROLLCLIP_H_
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIScrollableFrame;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class DisplayItemClip;
|
||||
|
||||
/**
|
||||
* A DisplayItemScrollClip represents a DisplayItemClip from a scrollable
|
||||
* frame. This clip is stored on a display item separately from the item's
|
||||
* regular DisplayItemClip for async scrolling purposes: The item's regular
|
||||
* clip can be fused to the item's contents when drawing layer contents, but
|
||||
* scroll clips need to be kept separate so that they can be applied at
|
||||
* composition time, after any async scroll offsets have been applied.
|
||||
* Scroll clips are created during display list construction when
|
||||
* async-scrollable scroll frames are entered. At that point, the current
|
||||
* regular clip is cleared on the display list clip state. They are also
|
||||
* created for scroll frames that are inactivate and not async scrollable;
|
||||
* in that case, mIsAsyncScrollable on the scroll clip will be false.
|
||||
* When async-scrollable scroll frames are nested, the inner display items
|
||||
* can walk the whole chain of scroll clips via the DisplayItemScrollClip's
|
||||
* mParent pointer, or its mCrossStackingContextParent pointer if they need
|
||||
* access to the complete chain.
|
||||
* Storing scroll clips on display items allows easy access of all scroll
|
||||
* frames that affect a certain display item, and it allows some display list
|
||||
* operations to compute more accurate clips, for example when computing the
|
||||
* bounds of a container item for a frame that contains an async-scrollable
|
||||
* scroll frame.
|
||||
*/
|
||||
class DisplayItemScrollClip {
|
||||
public:
|
||||
DisplayItemScrollClip(const DisplayItemScrollClip* aParent,
|
||||
const DisplayItemScrollClip* aCrossStackingContextParent,
|
||||
nsIScrollableFrame* aScrollableFrame,
|
||||
const DisplayItemClip* aClip,
|
||||
bool aIsAsyncScrollable)
|
||||
: mParent(aParent)
|
||||
, mScrollableFrame(aScrollableFrame)
|
||||
, mClip(aClip)
|
||||
, mIsAsyncScrollable(aIsAsyncScrollable)
|
||||
, mCrossStackingContextParent(aCrossStackingContextParent)
|
||||
, mCrossStackingContextDepth(aCrossStackingContextParent ?
|
||||
aCrossStackingContextParent->mCrossStackingContextDepth + 1 : 1)
|
||||
{
|
||||
MOZ_ASSERT(mScrollableFrame);
|
||||
}
|
||||
|
||||
/**
|
||||
* "Pick innermost" is analogous to the intersection operation on regular
|
||||
* clips: In some cases, there are multiple candidate clips that can apply to
|
||||
* an item, one of them being the ancestor of the other. This method picks
|
||||
* the descendant.
|
||||
* Both aClip1 and aClip2 are allowed to be null.
|
||||
*/
|
||||
static const DisplayItemScrollClip*
|
||||
PickInnermost(const DisplayItemScrollClip* aClip1,
|
||||
const DisplayItemScrollClip* aClip2)
|
||||
{
|
||||
MOZ_ASSERT(IsAncestor(aClip1, aClip2) || IsAncestor(aClip2, aClip1),
|
||||
"one of the scroll clips must be an ancestor of the other");
|
||||
return Depth(aClip1) > Depth(aClip2) ? aClip1 : aClip2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether aAncestor is an ancestor scroll clip of aDescendant.
|
||||
* A scroll clip that's null is considered the root scroll clip.
|
||||
*/
|
||||
static bool IsAncestor(const DisplayItemScrollClip* aAncestor,
|
||||
const DisplayItemScrollClip* aDescendant);
|
||||
|
||||
/**
|
||||
* Return a string which contains the list of stringified clips for this
|
||||
* scroll clip and its ancestors. aScrollClip can be null.
|
||||
*/
|
||||
static nsCString ToString(const DisplayItemScrollClip* aScrollClip);
|
||||
|
||||
/**
|
||||
* The previous (outer) scroll clip, or null.
|
||||
*/
|
||||
const DisplayItemScrollClip* mParent;
|
||||
|
||||
/**
|
||||
* The scrollable frame that this scroll clip is for. Always non-null.
|
||||
*/
|
||||
nsIScrollableFrame* mScrollableFrame;
|
||||
|
||||
/**
|
||||
* The clip represented by this scroll clip, relative to mScrollableFrame's
|
||||
* reference frame. Can be null.
|
||||
*/
|
||||
const DisplayItemClip* mClip;
|
||||
|
||||
/**
|
||||
* Whether this scroll clip is for an async-scrollable scroll frame.
|
||||
* Can change during display list construction.
|
||||
*/
|
||||
bool mIsAsyncScrollable;
|
||||
|
||||
private:
|
||||
static uint32_t Depth(const DisplayItemScrollClip* aSC)
|
||||
{ return aSC ? aSC->mCrossStackingContextDepth : 0; }
|
||||
|
||||
/**
|
||||
* The previous (outer) scroll clip, across stacking contexts, or null.
|
||||
*/
|
||||
const DisplayItemScrollClip* mCrossStackingContextParent;
|
||||
|
||||
const uint32_t mCrossStackingContextDepth;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
#endif /* DISPLAYITEMSCROLLCLIP_H_ */
|
@ -5,6 +5,7 @@
|
||||
|
||||
#include "DisplayListClipState.h"
|
||||
|
||||
#include "DisplayItemScrollClip.h"
|
||||
#include "nsDisplayList.h"
|
||||
|
||||
namespace mozilla {
|
||||
@ -107,6 +108,99 @@ DisplayListClipState::ClipContainingBlockDescendantsToContentBox(nsDisplayListBu
|
||||
aClipOnStack);
|
||||
}
|
||||
|
||||
const DisplayItemScrollClip*
|
||||
DisplayListClipState::GetCurrentInnermostScrollClip()
|
||||
{
|
||||
return DisplayItemScrollClip::PickInnermost(
|
||||
mScrollClipContentDescendants, mScrollClipContainingBlockDescendants);
|
||||
}
|
||||
|
||||
void
|
||||
DisplayListClipState::TurnClipIntoScrollClipForContentDescendants(
|
||||
nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
const DisplayItemScrollClip* parent = GetCurrentInnermostScrollClip();
|
||||
const DisplayItemScrollClip* crossStackingContextParent = parent;
|
||||
if (!crossStackingContextParent) {
|
||||
crossStackingContextParent = mCrossStackingContextParentScrollClip;
|
||||
}
|
||||
mScrollClipContentDescendants =
|
||||
aBuilder->AllocateDisplayItemScrollClip(parent, crossStackingContextParent,
|
||||
aScrollableFrame,
|
||||
GetCurrentCombinedClip(aBuilder), true);
|
||||
Clear();
|
||||
}
|
||||
|
||||
void
|
||||
DisplayListClipState::TurnClipIntoScrollClipForContainingBlockDescendants(
|
||||
nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
const DisplayItemScrollClip* parent = GetCurrentInnermostScrollClip();
|
||||
const DisplayItemScrollClip* crossStackingContextParent = parent;
|
||||
if (!crossStackingContextParent) {
|
||||
crossStackingContextParent = mCrossStackingContextParentScrollClip;
|
||||
}
|
||||
mScrollClipContainingBlockDescendants =
|
||||
aBuilder->AllocateDisplayItemScrollClip(parent, crossStackingContextParent,
|
||||
aScrollableFrame,
|
||||
GetCurrentCombinedClip(aBuilder), true);
|
||||
Clear();
|
||||
}
|
||||
|
||||
const DisplayItemClip*
|
||||
WithoutRoundedCorners(nsDisplayListBuilder* aBuilder, const DisplayItemClip* aClip)
|
||||
{
|
||||
if (!aClip) {
|
||||
return nullptr;
|
||||
}
|
||||
DisplayItemClip rectClip(*aClip);
|
||||
rectClip.RemoveRoundedCorners();
|
||||
return aBuilder->AllocateDisplayItemClip(rectClip);
|
||||
}
|
||||
|
||||
DisplayItemScrollClip*
|
||||
DisplayListClipState::CreateInactiveScrollClip(
|
||||
nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
// We ignore the rounded corners on the current clip because we don't want
|
||||
// them to be double-applied (as scroll clip and as regular clip).
|
||||
// Double-applying rectangle clips doesn't make a visual difference so it's
|
||||
// fine.
|
||||
const DisplayItemClip* rectClip =
|
||||
WithoutRoundedCorners(aBuilder, GetCurrentCombinedClip(aBuilder));
|
||||
|
||||
const DisplayItemScrollClip* parent = GetCurrentInnermostScrollClip();
|
||||
const DisplayItemScrollClip* crossStackingContextParent = parent;
|
||||
if (!crossStackingContextParent) {
|
||||
crossStackingContextParent = mCrossStackingContextParentScrollClip;
|
||||
}
|
||||
DisplayItemScrollClip* scrollClip =
|
||||
aBuilder->AllocateDisplayItemScrollClip(parent, crossStackingContextParent,
|
||||
aScrollableFrame,
|
||||
rectClip, false);
|
||||
return scrollClip;
|
||||
}
|
||||
|
||||
DisplayItemScrollClip*
|
||||
DisplayListClipState::InsertInactiveScrollClipForContentDescendants(
|
||||
nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
DisplayItemScrollClip* scrollClip =
|
||||
CreateInactiveScrollClip(aBuilder, aScrollableFrame);
|
||||
mScrollClipContentDescendants = scrollClip;
|
||||
return scrollClip;
|
||||
}
|
||||
|
||||
DisplayItemScrollClip*
|
||||
DisplayListClipState::InsertInactiveScrollClipForContainingBlockDescendants(
|
||||
nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
DisplayItemScrollClip* scrollClip =
|
||||
CreateInactiveScrollClip(aBuilder, aScrollableFrame);
|
||||
mScrollClipContainingBlockDescendants = scrollClip;
|
||||
return scrollClip;
|
||||
}
|
||||
|
||||
DisplayListClipState::AutoSaveRestore::AutoSaveRestore(nsDisplayListBuilder* aBuilder)
|
||||
: mState(aBuilder->ClipState())
|
||||
, mSavedState(aBuilder->ClipState())
|
||||
|
@ -11,10 +11,13 @@
|
||||
#include "mozilla/DebugOnly.h"
|
||||
|
||||
class nsIFrame;
|
||||
class nsIScrollableFrame;
|
||||
class nsDisplayListBuilder;
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
class DisplayItemScrollClip;
|
||||
|
||||
/**
|
||||
* All clip coordinates are in appunits relative to the reference frame
|
||||
* for the display item we're building.
|
||||
@ -25,6 +28,9 @@ public:
|
||||
: mClipContentDescendants(nullptr)
|
||||
, mClipContainingBlockDescendants(nullptr)
|
||||
, mCurrentCombinedClip(nullptr)
|
||||
, mScrollClipContentDescendants(nullptr)
|
||||
, mScrollClipContainingBlockDescendants(nullptr)
|
||||
, mCrossStackingContextParentScrollClip(nullptr)
|
||||
{}
|
||||
|
||||
/**
|
||||
@ -42,6 +48,8 @@ public:
|
||||
return mClipContentDescendants;
|
||||
}
|
||||
|
||||
const DisplayItemScrollClip* GetCurrentInnermostScrollClip();
|
||||
|
||||
class AutoSaveRestore;
|
||||
friend class AutoSaveRestore;
|
||||
|
||||
@ -62,13 +70,62 @@ private:
|
||||
mCurrentCombinedClip = nullptr;
|
||||
}
|
||||
|
||||
void SetScrollClipForContainingBlockDescendants(const DisplayItemScrollClip* aScrollClip)
|
||||
{
|
||||
mScrollClipContainingBlockDescendants = aScrollClip;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
mClipContentDescendants = nullptr;
|
||||
mClipContainingBlockDescendants = nullptr;
|
||||
mCurrentCombinedClip = nullptr;
|
||||
// We do not clear scroll clips.
|
||||
}
|
||||
|
||||
void ClearForStackingContextContents()
|
||||
{
|
||||
mClipContentDescendants = nullptr;
|
||||
mClipContainingBlockDescendants = nullptr;
|
||||
mCurrentCombinedClip = nullptr;
|
||||
mCrossStackingContextParentScrollClip = GetCurrentInnermostScrollClip();
|
||||
mScrollClipContentDescendants = nullptr;
|
||||
mScrollClipContainingBlockDescendants = nullptr;
|
||||
}
|
||||
|
||||
void ClearIncludingScrollClip()
|
||||
{
|
||||
mClipContentDescendants = nullptr;
|
||||
mClipContainingBlockDescendants = nullptr;
|
||||
mCurrentCombinedClip = nullptr;
|
||||
mCrossStackingContextParentScrollClip = nullptr;
|
||||
mScrollClipContentDescendants = nullptr;
|
||||
mScrollClipContainingBlockDescendants = nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the current clip, and instead add it as a scroll clip to the current
|
||||
* scroll clip chain.
|
||||
*/
|
||||
void TurnClipIntoScrollClipForContentDescendants(nsDisplayListBuilder* aBuilder,
|
||||
nsIScrollableFrame* aScrollableFrame);
|
||||
void TurnClipIntoScrollClipForContainingBlockDescendants(nsDisplayListBuilder* aBuilder,
|
||||
nsIScrollableFrame* aScrollableFrame);
|
||||
|
||||
/**
|
||||
* Insert a scroll clip without clearing the current clip.
|
||||
* The returned DisplayItemScrollClip will have mIsAsyncScrollable == false,
|
||||
* and it can be activated once the scroll frame knows that it needs to be
|
||||
* async scrollable.
|
||||
*/
|
||||
DisplayItemScrollClip* InsertInactiveScrollClipForContentDescendants(nsDisplayListBuilder* aBuilder,
|
||||
nsIScrollableFrame* aScrollableFrame);
|
||||
DisplayItemScrollClip* InsertInactiveScrollClipForContainingBlockDescendants(nsDisplayListBuilder* aBuilder,
|
||||
nsIScrollableFrame* aScrollableFrame);
|
||||
|
||||
DisplayItemScrollClip* CreateInactiveScrollClip(nsDisplayListBuilder* aBuilder,
|
||||
nsIScrollableFrame* aScrollableFrame);
|
||||
|
||||
/**
|
||||
* Intersects the given clip rect (with optional aRadii) with the current
|
||||
* mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
|
||||
@ -120,6 +177,13 @@ private:
|
||||
* are null.
|
||||
*/
|
||||
const DisplayItemClip* mCurrentCombinedClip;
|
||||
|
||||
/**
|
||||
* The same for scroll clips.
|
||||
*/
|
||||
const DisplayItemScrollClip* mScrollClipContentDescendants;
|
||||
const DisplayItemScrollClip* mScrollClipContainingBlockDescendants;
|
||||
const DisplayItemScrollClip* mCrossStackingContextParentScrollClip;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -149,6 +213,51 @@ public:
|
||||
mClipUsed = false;
|
||||
}
|
||||
|
||||
void ClearForStackingContextContents()
|
||||
{
|
||||
NS_ASSERTION(!mRestored, "Already restored!");
|
||||
mState.ClearForStackingContextContents();
|
||||
mClipUsed = false;
|
||||
}
|
||||
|
||||
|
||||
void ClearIncludingScrollClip()
|
||||
{
|
||||
NS_ASSERTION(!mRestored, "Already restored!");
|
||||
mState.ClearIncludingScrollClip();
|
||||
mClipUsed = false;
|
||||
}
|
||||
|
||||
void TurnClipIntoScrollClipForContentDescendants(nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
NS_ASSERTION(!mRestored, "Already restored!");
|
||||
mState.TurnClipIntoScrollClipForContentDescendants(aBuilder, aScrollableFrame);
|
||||
mClipUsed = true;
|
||||
}
|
||||
|
||||
void TurnClipIntoScrollClipForContainingBlockDescendants(nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
NS_ASSERTION(!mRestored, "Already restored!");
|
||||
mState.TurnClipIntoScrollClipForContainingBlockDescendants(aBuilder, aScrollableFrame);
|
||||
mClipUsed = true;
|
||||
}
|
||||
|
||||
DisplayItemScrollClip* InsertInactiveScrollClipForContentDescendants(nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
NS_ASSERTION(!mRestored, "Already restored!");
|
||||
DisplayItemScrollClip* scrollClip = mState.InsertInactiveScrollClipForContentDescendants(aBuilder, aScrollableFrame);
|
||||
mClipUsed = true;
|
||||
return scrollClip;
|
||||
}
|
||||
|
||||
DisplayItemScrollClip* InsertInactiveScrollClipForContainingBlockDescendants(nsDisplayListBuilder* aBuilder, nsIScrollableFrame* aScrollableFrame)
|
||||
{
|
||||
NS_ASSERTION(!mRestored, "Already restored!");
|
||||
DisplayItemScrollClip* scrollClip = mState.InsertInactiveScrollClipForContainingBlockDescendants(aBuilder, aScrollableFrame);
|
||||
mClipUsed = true;
|
||||
return scrollClip;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersects the given clip rect (with optional aRadii) with the current
|
||||
* mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
|
||||
@ -240,6 +349,11 @@ public:
|
||||
mState.SetClipForContainingBlockDescendants(aClip);
|
||||
}
|
||||
|
||||
void SetScrollClipForContainingBlockDescendants(const DisplayItemScrollClip* aScrollClip)
|
||||
{
|
||||
mState.SetScrollClipForContainingBlockDescendants(aScrollClip);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intersects the given clip rect (with optional aRadii) with the current
|
||||
* mClipContainingBlockDescendants and sets mClipContainingBlockDescendants to
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "mozilla/gfx/Matrix.h"
|
||||
#include "ActiveLayerTracker.h"
|
||||
#include "BasicLayers.h"
|
||||
#include "DisplayItemScrollClip.h"
|
||||
#include "ImageContainer.h"
|
||||
#include "ImageLayers.h"
|
||||
#include "LayerTreeInvalidation.h"
|
||||
@ -408,6 +409,7 @@ class PaintedLayerData {
|
||||
public:
|
||||
PaintedLayerData() :
|
||||
mAnimatedGeometryRoot(nullptr),
|
||||
mScrollClip(nullptr),
|
||||
mFixedPosFrameForLayerData(nullptr),
|
||||
mReferenceFrame(nullptr),
|
||||
mLayer(nullptr),
|
||||
@ -541,9 +543,9 @@ public:
|
||||
*/
|
||||
AnimatedGeometryRoot* mAnimatedGeometryRoot;
|
||||
/**
|
||||
* See NewLayerEntry::mAnimatedGeometryRootForScrollMetadata.
|
||||
* The scroll clip for this layer.
|
||||
*/
|
||||
AnimatedGeometryRoot* mAnimatedGeometryRootForScrollMetadata;
|
||||
const DisplayItemScrollClip* mScrollClip;
|
||||
/**
|
||||
* The offset between mAnimatedGeometryRoot and the reference frame.
|
||||
*/
|
||||
@ -669,7 +671,7 @@ public:
|
||||
struct NewLayerEntry {
|
||||
NewLayerEntry()
|
||||
: mAnimatedGeometryRoot(nullptr)
|
||||
, mAnimatedGeometryRootForScrollMetadata(nullptr)
|
||||
, mScrollClip(nullptr)
|
||||
, mFixedPosFrameForLayerData(nullptr)
|
||||
, mLayerContentsVisibleRect(0, 0, -1, -1)
|
||||
, mHideAllLayersBelow(false)
|
||||
@ -683,12 +685,7 @@ struct NewLayerEntry {
|
||||
// been optimized to some other form (yet).
|
||||
RefPtr<Layer> mLayer;
|
||||
AnimatedGeometryRoot* mAnimatedGeometryRoot;
|
||||
// For fixed background layers, mAnimatedGeometryRoot is the animated geometry
|
||||
// root of the viewport frame it's fixed to, but we need to annotate it with
|
||||
// scroll metadata starting from the animated geometry root of the element
|
||||
// it's the background of, so that during async scrolling we can correctly
|
||||
// transform the fixed layer's clip.
|
||||
AnimatedGeometryRoot* mAnimatedGeometryRootForScrollMetadata;
|
||||
const DisplayItemScrollClip* mScrollClip;
|
||||
const nsIFrame* mFixedPosFrameForLayerData;
|
||||
// If non-null, this FrameMetrics is set to the be the first FrameMetrics
|
||||
// on the layer.
|
||||
@ -775,6 +772,7 @@ public:
|
||||
template<typename NewPaintedLayerCallbackType>
|
||||
PaintedLayerData* FindPaintedLayerFor(const nsIntRect& aVisibleRect,
|
||||
bool aBackfaceHidden,
|
||||
const DisplayItemScrollClip* aScrollClip,
|
||||
NewPaintedLayerCallbackType aNewPaintedLayerCallback);
|
||||
|
||||
/**
|
||||
@ -948,6 +946,7 @@ public:
|
||||
*/
|
||||
template<typename NewPaintedLayerCallbackType>
|
||||
PaintedLayerData* FindPaintedLayerFor(AnimatedGeometryRoot* aAnimatedGeometryRoot,
|
||||
const DisplayItemScrollClip* aScrollClip,
|
||||
const nsIntRect& aVisibleRect,
|
||||
bool aForceOwnLayer,
|
||||
bool aBackfaceidden,
|
||||
@ -1046,12 +1045,14 @@ public:
|
||||
ContainerLayer* aContainerLayer,
|
||||
const ContainerLayerParameters& aParameters,
|
||||
bool aFlattenToSingleLayer,
|
||||
nscolor aBackgroundColor) :
|
||||
nscolor aBackgroundColor,
|
||||
const DisplayItemScrollClip* aContainerScrollClip) :
|
||||
mBuilder(aBuilder), mManager(aManager),
|
||||
mLayerBuilder(aLayerBuilder),
|
||||
mContainerFrame(aContainerFrame),
|
||||
mContainerLayer(aContainerLayer),
|
||||
mContainerBounds(aContainerBounds),
|
||||
mContainerScrollClip(aContainerScrollClip),
|
||||
mParameters(aParameters),
|
||||
mPaintedLayerDataTree(*this, aBackgroundColor),
|
||||
mFlattenToSingleLayer(aFlattenToSingleLayer)
|
||||
@ -1334,10 +1335,7 @@ protected:
|
||||
* @param aItem The item that is going to be added.
|
||||
* @param aVisibleRect The visible rect of the item.
|
||||
* @param aAnimatedGeometryRoot The item's animated geometry root.
|
||||
* @param aAnimatedGeometryRootForScrollMetadata
|
||||
* The animated geometry root to be used as
|
||||
* the starting point in SetupScrollMetadata().
|
||||
* See NewLayerEntry::mAnimatedGeometryRootForScrollMetadata.
|
||||
* @param aScrollClip The scroll clip for this PaintedLayer.
|
||||
* @param aTopLeft The offset between aAnimatedGeometryRoot and
|
||||
* the reference frame.
|
||||
* @param aShouldFixToViewport If true, aAnimatedGeometryRoot is the
|
||||
@ -1348,7 +1346,7 @@ protected:
|
||||
PaintedLayerData NewPaintedLayerData(nsDisplayItem* aItem,
|
||||
const nsIntRect& aVisibleRect,
|
||||
AnimatedGeometryRoot* aAnimatedGeometryRoot,
|
||||
AnimatedGeometryRoot* aAnimatedGeometryRootForScrollMetadata,
|
||||
const DisplayItemScrollClip* aScrollClip,
|
||||
const nsPoint& aTopLeft,
|
||||
bool aShouldFixToViewport);
|
||||
|
||||
@ -1385,6 +1383,7 @@ protected:
|
||||
const nsIFrame* mContainerFixedPosFrame;
|
||||
ContainerLayer* mContainerLayer;
|
||||
nsRect mContainerBounds;
|
||||
const DisplayItemScrollClip* mContainerScrollClip;
|
||||
DebugOnly<nsRect> mAccumulatedChildBounds;
|
||||
ContainerLayerParameters mParameters;
|
||||
/**
|
||||
@ -2671,6 +2670,7 @@ template<typename NewPaintedLayerCallbackType>
|
||||
PaintedLayerData*
|
||||
PaintedLayerDataNode::FindPaintedLayerFor(const nsIntRect& aVisibleRect,
|
||||
bool aBackfaceHidden,
|
||||
const DisplayItemScrollClip* aScrollClip,
|
||||
NewPaintedLayerCallbackType aNewPaintedLayerCallback)
|
||||
{
|
||||
if (!mPaintedLayerDataStack.IsEmpty()) {
|
||||
@ -2685,7 +2685,8 @@ PaintedLayerDataNode::FindPaintedLayerFor(const nsIntRect& aVisibleRect,
|
||||
break;
|
||||
}
|
||||
MOZ_ASSERT(!data.mExclusiveToOneItem);
|
||||
if (data.mBackfaceHidden == aBackfaceHidden) {
|
||||
if (data.mBackfaceHidden == aBackfaceHidden &&
|
||||
data.mScrollClip == aScrollClip) {
|
||||
lowestUsableLayer = &data;
|
||||
}
|
||||
nsIntRegion visibleRegion = data.mVisibleRegion;
|
||||
@ -2832,6 +2833,7 @@ PaintedLayerDataTree::AddingOwnLayer(AnimatedGeometryRoot* aAnimatedGeometryRoot
|
||||
template<typename NewPaintedLayerCallbackType>
|
||||
PaintedLayerData*
|
||||
PaintedLayerDataTree::FindPaintedLayerFor(AnimatedGeometryRoot* aAnimatedGeometryRoot,
|
||||
const DisplayItemScrollClip* aScrollClip,
|
||||
const nsIntRect& aVisibleRect,
|
||||
bool aForceOwnLayer,
|
||||
bool aBackfaceHidden,
|
||||
@ -2844,7 +2846,7 @@ PaintedLayerDataTree::FindPaintedLayerFor(AnimatedGeometryRoot* aAnimatedGeometr
|
||||
node->SetAllDrawingAbove();
|
||||
}
|
||||
PaintedLayerData* data =
|
||||
node->FindPaintedLayerFor(aVisibleRect, aBackfaceHidden,
|
||||
node->FindPaintedLayerFor(aVisibleRect, aBackfaceHidden, aScrollClip,
|
||||
aNewPaintedLayerCallback);
|
||||
data->mExclusiveToOneItem = aForceOwnLayer;
|
||||
return data;
|
||||
@ -3175,7 +3177,7 @@ void ContainerState::FinishPaintedLayerData(PaintedLayerData& aData, FindOpaqueB
|
||||
NS_ASSERTION(!newLayerEntry->mLayer, "Slot already occupied?");
|
||||
newLayerEntry->mLayer = layer;
|
||||
newLayerEntry->mAnimatedGeometryRoot = data->mAnimatedGeometryRoot;
|
||||
newLayerEntry->mAnimatedGeometryRootForScrollMetadata = data->mAnimatedGeometryRootForScrollMetadata;
|
||||
newLayerEntry->mScrollClip = data->mScrollClip;
|
||||
newLayerEntry->mFixedPosFrameForLayerData = data->mFixedPosFrameForLayerData;
|
||||
newLayerEntry->mIsCaret = data->mIsCaret;
|
||||
|
||||
@ -3571,13 +3573,13 @@ PaintedLayerData
|
||||
ContainerState::NewPaintedLayerData(nsDisplayItem* aItem,
|
||||
const nsIntRect& aVisibleRect,
|
||||
AnimatedGeometryRoot* aAnimatedGeometryRoot,
|
||||
AnimatedGeometryRoot* aAnimatedGeometryRootForScrollMetadata,
|
||||
const DisplayItemScrollClip* aScrollClip,
|
||||
const nsPoint& aTopLeft,
|
||||
bool aShouldFixToViewport)
|
||||
{
|
||||
PaintedLayerData data;
|
||||
data.mAnimatedGeometryRoot = aAnimatedGeometryRoot;
|
||||
data.mAnimatedGeometryRootForScrollMetadata = aAnimatedGeometryRootForScrollMetadata;
|
||||
data.mScrollClip = aScrollClip;
|
||||
data.mAnimatedGeometryRootOffset = aTopLeft;
|
||||
data.mFixedPosFrameForLayerData =
|
||||
FindFixedPosFrameForLayerData(aAnimatedGeometryRoot, aShouldFixToViewport);
|
||||
@ -3589,7 +3591,7 @@ ContainerState::NewPaintedLayerData(nsDisplayItem* aItem,
|
||||
data.mNewChildLayersIndex = mNewChildLayers.Length();
|
||||
NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
|
||||
newLayerEntry->mAnimatedGeometryRoot = aAnimatedGeometryRoot;
|
||||
newLayerEntry->mAnimatedGeometryRootForScrollMetadata = aAnimatedGeometryRootForScrollMetadata;
|
||||
newLayerEntry->mScrollClip = aScrollClip;
|
||||
newLayerEntry->mFixedPosFrameForLayerData = data.mFixedPosFrameForLayerData;
|
||||
newLayerEntry->mIsCaret = data.mIsCaret;
|
||||
// newLayerEntry->mOpaqueRegion is filled in later from
|
||||
@ -3752,41 +3754,25 @@ ContainerState::ComputeOpaqueRect(nsDisplayItem* aItem,
|
||||
return opaquePixels;
|
||||
}
|
||||
|
||||
static bool
|
||||
IsCaretWithCustomClip(nsDisplayItem* aItem, nsDisplayItem::Type aItemType)
|
||||
static const DisplayItemScrollClip*
|
||||
InnermostScrollClipApplicableToAGR(const DisplayItemScrollClip* aItemScrollClip,
|
||||
AnimatedGeometryRoot* aAnimatedGeometryRoot)
|
||||
{
|
||||
return aItemType == nsDisplayItem::TYPE_CARET &&
|
||||
static_cast<nsDisplayCaret*>(aItem)->NeedsCustomScrollClip();
|
||||
}
|
||||
|
||||
static DisplayItemClip
|
||||
GetScrollClipIntersection(nsDisplayListBuilder* aBuilder, AnimatedGeometryRoot* aAnimatedGeometryRoot,
|
||||
AnimatedGeometryRoot* aStopAtAnimatedGeometryRoot, bool aIsCaret)
|
||||
{
|
||||
DisplayItemClip resultClip;
|
||||
for (AnimatedGeometryRoot* agr = aAnimatedGeometryRoot;
|
||||
agr != aStopAtAnimatedGeometryRoot;
|
||||
agr = agr->mParentAGR) {
|
||||
if (!agr) {
|
||||
// This means aStopAtAnimatedGeometryRoot was not an ancestor
|
||||
// of aAnimatedGeometryRoot. This is a weird case but it
|
||||
// can happen, e.g. when a scrolled frame contains a frame with opacity
|
||||
// which contains a frame that is not scrolled by the scrolled frame.
|
||||
// For now, we just don't apply any specific scroll clip to this layer.
|
||||
return DisplayItemClip();
|
||||
}
|
||||
|
||||
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(*agr);
|
||||
if (!scrollFrame) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Maybe<DisplayItemClip> clip = scrollFrame->ComputeScrollClip(aIsCaret);
|
||||
if (clip) {
|
||||
resultClip.IntersectWith(*clip);
|
||||
// "Applicable" scroll clips are those that are for nsIScrollableFrames
|
||||
// that are ancestors of aAnimatedGeometryRoot or ancestors of aContainerScrollClip.
|
||||
// They can be applied to all items sharing this animated geometry root, so
|
||||
// instead of applying to the items individually, they can be applied to the
|
||||
// whole layer.
|
||||
for (const DisplayItemScrollClip* scrollClip = aItemScrollClip;
|
||||
scrollClip;
|
||||
scrollClip = scrollClip->mParent) {
|
||||
nsIFrame* scrolledFrame = scrollClip->mScrollableFrame->GetScrolledFrame();
|
||||
if (nsLayoutUtils::IsAncestorFrameCrossDoc(scrolledFrame, *aAnimatedGeometryRoot)) {
|
||||
// scrollClip and all its ancestors are applicable.
|
||||
return scrollClip;
|
||||
}
|
||||
}
|
||||
return resultClip;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3872,16 +3858,15 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
|
||||
bool forceInactive;
|
||||
AnimatedGeometryRoot* animatedGeometryRoot;
|
||||
AnimatedGeometryRoot* animatedGeometryRootForScrollMetadata = nullptr;
|
||||
AnimatedGeometryRoot* realAnimatedGeometryRootOfItem = item->GetAnimatedGeometryRoot();
|
||||
AnimatedGeometryRoot* animatedGeometryRootForClip = nullptr;
|
||||
if (mFlattenToSingleLayer) {
|
||||
forceInactive = true;
|
||||
animatedGeometryRoot = lastAnimatedGeometryRoot;
|
||||
} else {
|
||||
forceInactive = false;
|
||||
if (mManager->IsWidgetLayerManager()) {
|
||||
animatedGeometryRoot = realAnimatedGeometryRootOfItem;
|
||||
animatedGeometryRootForScrollMetadata = item->AnimatedGeometryRootForScrollMetadata();
|
||||
animatedGeometryRoot = item->GetAnimatedGeometryRoot();
|
||||
animatedGeometryRootForClip = item->AnimatedGeometryRootForScrollMetadata();
|
||||
} else {
|
||||
// For inactive layer subtrees, splitting content into PaintedLayers
|
||||
// based on animated geometry roots is pointless. It's more efficient
|
||||
@ -3891,17 +3876,42 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
}
|
||||
topLeft = (*animatedGeometryRoot)->GetOffsetToCrossDoc(mContainerReferenceFrame);
|
||||
}
|
||||
if (!animatedGeometryRootForScrollMetadata) {
|
||||
animatedGeometryRootForScrollMetadata = animatedGeometryRoot;
|
||||
if (!animatedGeometryRootForClip) {
|
||||
animatedGeometryRootForClip = animatedGeometryRoot;
|
||||
}
|
||||
|
||||
if (animatedGeometryRoot != realAnimatedGeometryRootOfItem) {
|
||||
const DisplayItemScrollClip* itemScrollClip = item->ScrollClip();
|
||||
if (itemType == nsDisplayItem::TYPE_OPACITY && layerState == LAYER_INACTIVE) {
|
||||
// This is an unfortunate hack. For opacity items, we usually want to
|
||||
// apply clips and scroll transforms to their descendants. However, if
|
||||
// an opacity is inactive and gets painted into a PaintedLayer, we can't
|
||||
// apply async scrolling offsets to the inactive layer manager contents;
|
||||
// instead, we need to move the opacity item itself, by moving the
|
||||
// PaintedLayer that it gets painted into.
|
||||
itemScrollClip = InnermostScrollClipApplicableToAGR(
|
||||
static_cast<nsDisplayOpacity*>(item)->ScrollClipForSameAGRChildren(),
|
||||
animatedGeometryRootForClip);
|
||||
item->SetScrollClip(itemScrollClip);
|
||||
item->UpdateBounds(mBuilder);
|
||||
}
|
||||
// Now we need to separate the item's scroll clip chain into those scroll
|
||||
// clips that can be applied to the whole layer (i.e. to all items
|
||||
// sharing the item's animated geometry root), and those that need to be
|
||||
// applied to the item itself.
|
||||
const DisplayItemScrollClip* agrScrollClip =
|
||||
InnermostScrollClipApplicableToAGR(itemScrollClip, animatedGeometryRootForClip);
|
||||
MOZ_ASSERT(DisplayItemScrollClip::IsAncestor(agrScrollClip, itemScrollClip));
|
||||
|
||||
if (agrScrollClip != itemScrollClip) {
|
||||
// Pick up any scroll clips that should apply to the item and apply them.
|
||||
DisplayItemClip clip =
|
||||
GetScrollClipIntersection(mBuilder, realAnimatedGeometryRootOfItem,
|
||||
animatedGeometryRoot,
|
||||
IsCaretWithCustomClip(item, itemType));
|
||||
clip.IntersectWith(item->GetClip());
|
||||
DisplayItemClip clip = item->GetClip();
|
||||
for (const DisplayItemScrollClip* scrollClip = itemScrollClip;
|
||||
scrollClip && scrollClip != agrScrollClip && scrollClip != mContainerScrollClip;
|
||||
scrollClip = scrollClip->mParent) {
|
||||
if (scrollClip->mClip) {
|
||||
clip.IntersectWith(*scrollClip->mClip);
|
||||
}
|
||||
}
|
||||
item->SetClip(mBuilder, clip);
|
||||
}
|
||||
|
||||
@ -3948,6 +3958,13 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
}
|
||||
}
|
||||
bounds = fixedToViewportClip.ApplyNonRoundedIntersection(bounds);
|
||||
for (const DisplayItemScrollClip* scrollClip = itemScrollClip;
|
||||
scrollClip && scrollClip != mContainerScrollClip;
|
||||
scrollClip = scrollClip->mParent) {
|
||||
if (scrollClip->mClip) {
|
||||
bounds = scrollClip->mClip->ApplyNonRoundedIntersection(bounds);
|
||||
}
|
||||
}
|
||||
((nsRect&)mAccumulatedChildBounds).UnionRect(mAccumulatedChildBounds, bounds);
|
||||
#endif
|
||||
|
||||
@ -4049,6 +4066,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
}
|
||||
|
||||
mParameters.mBackgroundColor = uniformColor;
|
||||
mParameters.mScrollClip = DisplayItemScrollClip::PickInnermost(agrScrollClip, mContainerScrollClip);
|
||||
|
||||
// Just use its layer.
|
||||
// Set layerContentsVisibleRect.width/height to -1 to indicate we
|
||||
@ -4118,7 +4136,7 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
NewLayerEntry* newLayerEntry = mNewChildLayers.AppendElement();
|
||||
newLayerEntry->mLayer = ownLayer;
|
||||
newLayerEntry->mAnimatedGeometryRoot = animatedGeometryRoot;
|
||||
newLayerEntry->mAnimatedGeometryRootForScrollMetadata = animatedGeometryRootForScrollMetadata;
|
||||
newLayerEntry->mScrollClip = agrScrollClip;
|
||||
newLayerEntry->mFixedPosFrameForLayerData = fixedPosFrame;
|
||||
if (itemType == nsDisplayItem::TYPE_PERSPECTIVE) {
|
||||
newLayerEntry->mIsPerspectiveItem = true;
|
||||
@ -4190,15 +4208,14 @@ ContainerState::ProcessDisplayItems(nsDisplayList* aList)
|
||||
layerState,
|
||||
topLeft, nullptr);
|
||||
} else {
|
||||
bool forceOwnLayer = shouldFixToViewport || IsCaretWithCustomClip(item, itemType);
|
||||
bool forceOwnLayer = shouldFixToViewport;
|
||||
PaintedLayerData* paintedLayerData =
|
||||
mPaintedLayerDataTree.FindPaintedLayerFor(animatedGeometryRoot, itemVisibleRect,
|
||||
forceOwnLayer,
|
||||
mPaintedLayerDataTree.FindPaintedLayerFor(animatedGeometryRoot, agrScrollClip,
|
||||
itemVisibleRect, forceOwnLayer,
|
||||
item->Frame()->BackfaceIsHidden(),
|
||||
[&]() {
|
||||
return NewPaintedLayerData(item, itemVisibleRect, animatedGeometryRoot,
|
||||
animatedGeometryRootForScrollMetadata,
|
||||
topLeft, shouldFixToViewport);
|
||||
agrScrollClip, topLeft, shouldFixToViewport);
|
||||
});
|
||||
|
||||
if (itemType == nsDisplayItem::TYPE_LAYER_EVENT_REGIONS) {
|
||||
@ -4732,43 +4749,29 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry)
|
||||
// should not have a mask layer.
|
||||
MOZ_ASSERT(!aEntry->mBaseFrameMetrics->GetMaskLayerIndex());
|
||||
}
|
||||
uint32_t baseLength = metricsArray.Length();
|
||||
|
||||
// Any extra mask layers we need to attach to FrameMetrics.
|
||||
nsTArray<RefPtr<Layer>> maskLayers;
|
||||
|
||||
nsIFrame* fParent;
|
||||
for (AnimatedGeometryRoot* agr = aEntry->mAnimatedGeometryRootForScrollMetadata;
|
||||
agr != mContainerAnimatedGeometryRoot;
|
||||
agr = agr->mParentAGR) {
|
||||
fParent = nsLayoutUtils::GetCrossDocParentFrame(*agr);
|
||||
if (!fParent) {
|
||||
// This means mContainerAnimatedGeometryRoot was not an ancestor
|
||||
// of aEntry->mAnimatedGeometryRoot. This is a weird case but it
|
||||
// can happen, e.g. when a scrolled frame contains a frame with opacity
|
||||
// which contains a frame that is not scrolled by the scrolled frame.
|
||||
// For now, we just don't apply any specific async scrolling to this layer.
|
||||
// It will async-scroll with mContainerAnimatedGeometryRoot, which
|
||||
// is substandard but not fatal.
|
||||
metricsArray.SetLength(baseLength);
|
||||
aEntry->mLayer->SetFrameMetrics(metricsArray);
|
||||
return;
|
||||
}
|
||||
|
||||
nsIScrollableFrame* scrollFrame = nsLayoutUtils::GetScrollableFrameFor(*agr);
|
||||
if (!scrollFrame) {
|
||||
for (const DisplayItemScrollClip* scrollClip = aEntry->mScrollClip;
|
||||
scrollClip && scrollClip != mContainerScrollClip;
|
||||
scrollClip = scrollClip->mParent) {
|
||||
if (!scrollClip->mIsAsyncScrollable) {
|
||||
// This scroll clip was created for a scroll frame that didn't know
|
||||
// whether it needs to be async scrollable for scroll handoff. It was
|
||||
// not activated, so we don't need to create a frame metrics for it.
|
||||
continue;
|
||||
}
|
||||
|
||||
Maybe<FrameMetricsAndClip> info =
|
||||
scrollFrame->ComputeFrameMetrics(aEntry->mLayer, mContainerReferenceFrame, mParameters, aEntry->mIsCaret);
|
||||
if (!info) {
|
||||
nsIScrollableFrame* scrollFrame = scrollClip->mScrollableFrame;
|
||||
const DisplayItemClip* clip = scrollClip->mClip;
|
||||
|
||||
Maybe<FrameMetrics> metrics =
|
||||
scrollFrame->ComputeFrameMetrics(aEntry->mLayer, mContainerReferenceFrame, mParameters, clip);
|
||||
if (!metrics) {
|
||||
continue;
|
||||
}
|
||||
|
||||
FrameMetrics& metrics = info->metrics;
|
||||
Maybe<DisplayItemClip> clip = info->clip;
|
||||
|
||||
if (clip &&
|
||||
clip->HasClip() &&
|
||||
clip->GetRoundedRectCount() > 0)
|
||||
@ -4781,12 +4784,12 @@ ContainerState::SetupScrollingMetadata(NewLayerEntry* aEntry)
|
||||
RefPtr<Layer> maskLayer =
|
||||
CreateMaskLayer(aEntry->mLayer, *clip, aEntry->mVisibleRegion, nextIndex, clip->GetRoundedRectCount());
|
||||
if (maskLayer) {
|
||||
metrics.SetMaskLayerIndex(nextIndex);
|
||||
metrics->SetMaskLayerIndex(nextIndex);
|
||||
maskLayers.AppendElement(maskLayer);
|
||||
}
|
||||
}
|
||||
|
||||
metricsArray.AppendElement(metrics);
|
||||
metricsArray.AppendElement(*metrics);
|
||||
}
|
||||
|
||||
// Watch out for FrameMetrics copies in profiles
|
||||
@ -4940,8 +4943,10 @@ ContainerState::Finish(uint32_t* aTextContentFlags, LayerManagerData* aData,
|
||||
{
|
||||
mPaintedLayerDataTree.Finish();
|
||||
|
||||
NS_ASSERTION(mContainerBounds.Contains(mAccumulatedChildBounds),
|
||||
"Bounds computation mismatch");
|
||||
if (!mParameters.mForEventsOnly) {
|
||||
NS_ASSERTION(mContainerBounds.IsEqualInterior(mAccumulatedChildBounds),
|
||||
"Bounds computation mismatch");
|
||||
}
|
||||
|
||||
if (mLayerBuilder->IsBuildingRetainedLayers()) {
|
||||
nsIntRegion containerOpaqueRegion;
|
||||
@ -5279,8 +5284,10 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
return containerLayer.forget();
|
||||
}
|
||||
|
||||
const DisplayItemScrollClip* containerScrollClip = aParameters.mScrollClip;
|
||||
|
||||
ContainerLayerParameters scaleParameters;
|
||||
nsRect bounds = aChildren->GetBounds(aBuilder);
|
||||
nsRect bounds = aChildren->GetClippedBoundsUpTo(aBuilder, containerScrollClip);
|
||||
nsRect childrenVisible =
|
||||
aContainerItem ? aContainerItem->GetVisibleRectForChildren() :
|
||||
aContainerFrame->GetVisualOverflowRectRelativeToSelf();
|
||||
@ -5328,7 +5335,7 @@ FrameLayerBuilder::BuildContainerLayerFor(nsDisplayListBuilder* aBuilder,
|
||||
ContainerState state(aBuilder, aManager, aManager->GetLayerBuilder(),
|
||||
aContainerFrame, aContainerItem, bounds,
|
||||
containerLayer, scaleParameters, flattenToSingleLayer,
|
||||
backgroundColor);
|
||||
backgroundColor, containerScrollClip);
|
||||
|
||||
state.ProcessDisplayItems(aChildren);
|
||||
|
||||
|
@ -24,6 +24,7 @@ class gfxContext;
|
||||
class nsDisplayItemGeometry;
|
||||
|
||||
namespace mozilla {
|
||||
class DisplayItemScrollClip;
|
||||
namespace layers {
|
||||
class ContainerLayer;
|
||||
class LayerManager;
|
||||
@ -54,6 +55,7 @@ struct ContainerLayerParameters {
|
||||
, mYScale(1)
|
||||
, mLayerContentsVisibleRect(nullptr)
|
||||
, mBackgroundColor(NS_RGBA(0,0,0,0))
|
||||
, mScrollClip(nullptr)
|
||||
, mInTransformedSubtree(false)
|
||||
, mInActiveTransformedSubtree(false)
|
||||
, mDisableSubpixelAntialiasingInDescendants(false)
|
||||
@ -65,6 +67,7 @@ struct ContainerLayerParameters {
|
||||
, mYScale(aYScale)
|
||||
, mLayerContentsVisibleRect(nullptr)
|
||||
, mBackgroundColor(NS_RGBA(0,0,0,0))
|
||||
, mScrollClip(nullptr)
|
||||
, mInTransformedSubtree(false)
|
||||
, mInActiveTransformedSubtree(false)
|
||||
, mDisableSubpixelAntialiasingInDescendants(false)
|
||||
@ -79,6 +82,7 @@ struct ContainerLayerParameters {
|
||||
, mLayerContentsVisibleRect(nullptr)
|
||||
, mOffset(aOffset)
|
||||
, mBackgroundColor(aParent.mBackgroundColor)
|
||||
, mScrollClip(aParent.mScrollClip)
|
||||
, mInTransformedSubtree(aParent.mInTransformedSubtree)
|
||||
, mInActiveTransformedSubtree(aParent.mInActiveTransformedSubtree)
|
||||
, mDisableSubpixelAntialiasingInDescendants(aParent.mDisableSubpixelAntialiasingInDescendants)
|
||||
@ -108,6 +112,7 @@ struct ContainerLayerParameters {
|
||||
}
|
||||
|
||||
nscolor mBackgroundColor;
|
||||
const DisplayItemScrollClip* mScrollClip;
|
||||
bool mInTransformedSubtree;
|
||||
bool mInActiveTransformedSubtree;
|
||||
bool mDisableSubpixelAntialiasingInDescendants;
|
||||
|
@ -44,6 +44,7 @@
|
||||
#include "nsSMILAnimationController.h"
|
||||
#include "nsCSSRuleProcessor.h"
|
||||
#include "ChildIterator.h"
|
||||
#include "Layers.h"
|
||||
|
||||
#ifdef ACCESSIBILITY
|
||||
#include "nsAccessibilityService.h"
|
||||
@ -52,6 +53,7 @@
|
||||
namespace mozilla {
|
||||
|
||||
using namespace layers;
|
||||
using namespace dom;
|
||||
|
||||
#define LOG_RESTYLE_CONTINUE(reason_, ...) \
|
||||
LOG_RESTYLE("continuing restyle since " reason_, ##__VA_ARGS__)
|
||||
|
@ -58,6 +58,7 @@ EXPORTS += [
|
||||
'ActiveLayerTracker.h',
|
||||
'CaretAssociationHint.h',
|
||||
'DisplayItemClip.h',
|
||||
'DisplayItemScrollClip.h',
|
||||
'DisplayListClipState.h',
|
||||
'FrameLayerBuilder.h',
|
||||
'FramePropertyTable.h',
|
||||
@ -112,6 +113,7 @@ UNIFIED_SOURCES += [
|
||||
'AccessibleCaretManager.cpp',
|
||||
'ActiveLayerTracker.cpp',
|
||||
'DisplayItemClip.cpp',
|
||||
'DisplayItemScrollClip.cpp',
|
||||
'DisplayListClipState.cpp',
|
||||
'FrameLayerBuilder.cpp',
|
||||
'FramePropertyTable.cpp',
|
||||
|
@ -75,6 +75,7 @@
|
||||
#include "mozilla/RuleNodeCacheConditions.h"
|
||||
#include "nsCSSProps.h"
|
||||
#include "nsPluginFrame.h"
|
||||
#include "DisplayItemScrollClip.h"
|
||||
|
||||
// GetCurrentTime is defined in winbase.h as zero argument macro forwarding to
|
||||
// GetTickCount().
|
||||
@ -746,36 +747,6 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
|
||||
const nsRect& aDirtyRect)
|
||||
{
|
||||
nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect;
|
||||
DisplayItemClip clip;
|
||||
const DisplayItemClip* clipPtr = nullptr;
|
||||
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
|
||||
IsPaintingToWindow()) {
|
||||
NS_ASSERTION(aDirtyFrame == aFrame->GetParent(), "Dirty frame should be viewport frame");
|
||||
// position: fixed items are reflowed into and only drawn inside the
|
||||
// viewport, or the scroll position clamping scrollport size, if one is
|
||||
// set.
|
||||
nsIPresShell* ps = aFrame->PresContext()->PresShell();
|
||||
dirtyRectRelativeToDirtyFrame.MoveTo(0, 0);
|
||||
if (ps->IsScrollPositionClampingScrollPortSizeSet()) {
|
||||
dirtyRectRelativeToDirtyFrame.SizeTo(ps->GetScrollPositionClampingScrollPortSize());
|
||||
} else {
|
||||
dirtyRectRelativeToDirtyFrame.SizeTo(aDirtyFrame->GetSize());
|
||||
}
|
||||
|
||||
// Always clip fixed items to the root scroll frame's scrollport, because
|
||||
// we skip setting the clip in ScrollFrameHelper if we have a displayport.
|
||||
nsIFrame* rootScroll = aFrame->PresContext()->PresShell()->GetRootScrollFrame();
|
||||
if (rootScroll) {
|
||||
nsIScrollableFrame* scrollable = do_QueryFrame(rootScroll);
|
||||
|
||||
nsRect clipRect = scrollable->GetScrollPortRect() + ToReferenceFrame(rootScroll);
|
||||
nscoord radii[8];
|
||||
bool haveRadii = rootScroll->GetPaddingBoxBorderRadii(radii);
|
||||
clip.SetTo(clipRect, haveRadii ? radii : nullptr);
|
||||
clipPtr = &clip;
|
||||
}
|
||||
}
|
||||
|
||||
nsRect dirty = dirtyRectRelativeToDirtyFrame - aFrame->GetOffsetTo(aDirtyFrame);
|
||||
nsRect overflowRect = aFrame->GetVisualOverflowRect();
|
||||
|
||||
@ -793,16 +764,9 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
|
||||
if (!dirty.IntersectRect(dirty, overflowRect))
|
||||
return;
|
||||
|
||||
// Combine clips if necessary
|
||||
const DisplayItemClip* oldClip = mClipState.GetClipForContainingBlockDescendants();
|
||||
if (clipPtr && oldClip) {
|
||||
clip.IntersectWith(*oldClip);
|
||||
} else if (oldClip) {
|
||||
clipPtr = oldClip;
|
||||
}
|
||||
|
||||
OutOfFlowDisplayData* data = clipPtr ? new OutOfFlowDisplayData(*clipPtr, dirty)
|
||||
: new OutOfFlowDisplayData(dirty);
|
||||
const DisplayItemScrollClip* sc = mClipState.GetCurrentInnermostScrollClip();
|
||||
OutOfFlowDisplayData* data = new OutOfFlowDisplayData(oldClip, sc, dirty);
|
||||
aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDisplayDataProperty(), data);
|
||||
|
||||
MarkFrameForDisplay(aFrame, aDirtyFrame);
|
||||
@ -830,8 +794,11 @@ nsDisplayListBuilder::~nsDisplayListBuilder() {
|
||||
|
||||
nsCSSRendering::EndFrameTreesLocked();
|
||||
|
||||
for (uint32_t i = 0; i < mDisplayItemClipsToDestroy.Length(); ++i) {
|
||||
mDisplayItemClipsToDestroy[i]->DisplayItemClip::~DisplayItemClip();
|
||||
for (DisplayItemClip* c : mDisplayItemClipsToDestroy) {
|
||||
c->DisplayItemClip::~DisplayItemClip();
|
||||
}
|
||||
for (DisplayItemScrollClip* c : mScrollClipsToDestroy) {
|
||||
c->DisplayItemScrollClip::~DisplayItemScrollClip();
|
||||
}
|
||||
|
||||
PL_FinishArenaPool(&mPool);
|
||||
@ -1033,6 +1000,20 @@ nsDisplayListBuilder::AllocateDisplayItemClip(const DisplayItemClip& aOriginal)
|
||||
return c;
|
||||
}
|
||||
|
||||
DisplayItemScrollClip*
|
||||
nsDisplayListBuilder::AllocateDisplayItemScrollClip(const DisplayItemScrollClip* aParent,
|
||||
const DisplayItemScrollClip* aCrossStackingContextParent,
|
||||
nsIScrollableFrame* aScrollableFrame,
|
||||
const DisplayItemClip* aClip,
|
||||
bool aIsAsyncScrollable)
|
||||
{
|
||||
void* p = Allocate(sizeof(DisplayItemScrollClip));
|
||||
DisplayItemScrollClip* c =
|
||||
new (p) DisplayItemScrollClip(aParent, aCrossStackingContextParent, aScrollableFrame, aClip, aIsAsyncScrollable);
|
||||
mScrollClipsToDestroy.AppendElement(c);
|
||||
return c;
|
||||
}
|
||||
|
||||
const nsIFrame*
|
||||
nsDisplayListBuilder::FindReferenceFrameFor(const nsIFrame *aFrame,
|
||||
nsPoint* aOffset)
|
||||
@ -1400,6 +1381,16 @@ nsDisplayList::GetBounds(nsDisplayListBuilder* aBuilder) const {
|
||||
return bounds;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayList::GetClippedBoundsUpTo(nsDisplayListBuilder* aBuilder,
|
||||
const DisplayItemScrollClip* aIncludeScrollClipsUpTo) const {
|
||||
nsRect bounds;
|
||||
for (nsDisplayItem* i = GetBottom(); i != nullptr; i = i->GetAbove()) {
|
||||
bounds.UnionRect(bounds, i->GetClippedBoundsUpTo(aBuilder, aIncludeScrollClipsUpTo));
|
||||
}
|
||||
return bounds;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayList::GetVisibleRect() const {
|
||||
nsRect result;
|
||||
@ -2081,6 +2072,7 @@ void nsDisplayList::Sort(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem::nsDisplayItem(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
, mClip(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder))
|
||||
, mScrollClip(aBuilder->ClipState().GetCurrentInnermostScrollClip())
|
||||
, mAnimatedGeometryRoot(nullptr)
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
, mPainted(false)
|
||||
@ -2180,6 +2172,21 @@ nsDisplayItem::GetClippedBounds(nsDisplayListBuilder* aBuilder)
|
||||
return GetClip().ApplyNonRoundedIntersection(r);
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplayItem::GetClippedBoundsUpTo(nsDisplayListBuilder* aBuilder,
|
||||
const DisplayItemScrollClip* aIncludeScrollClipsUpTo)
|
||||
{
|
||||
nsRect r = GetClippedBounds(aBuilder);
|
||||
for (const DisplayItemScrollClip* sc = mScrollClip;
|
||||
sc && sc != aIncludeScrollClipsUpTo;
|
||||
sc = sc->mParent) {
|
||||
if (sc->mClip) {
|
||||
r = sc->mClip->ApplyNonRoundedIntersection(r);
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
nsRect
|
||||
nsDisplaySolidColor::GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap)
|
||||
{
|
||||
@ -3434,7 +3441,6 @@ nsDisplayCaret::nsDisplayCaret(nsDisplayListBuilder* aBuilder,
|
||||
: nsDisplayItem(aBuilder, aCaretFrame)
|
||||
, mCaret(aBuilder->GetCaret())
|
||||
, mBounds(aBuilder->GetCaretRect() + ToReferenceFrame())
|
||||
, mNeedsCustomScrollClip(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(nsDisplayCaret);
|
||||
}
|
||||
@ -4012,8 +4018,10 @@ nsresult nsDisplayWrapper::WrapListsInPlace(nsDisplayListBuilder* aBuilder,
|
||||
|
||||
nsDisplayOpacity::nsDisplayOpacity(nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aFrame, nsDisplayList* aList,
|
||||
const DisplayItemScrollClip* aScrollClipForSameAGRChildren,
|
||||
bool aForEventsOnly)
|
||||
: nsDisplayWrapList(aBuilder, aFrame, aList)
|
||||
, mScrollClipForSameAGRChildren(aScrollClipForSameAGRChildren)
|
||||
, mOpacity(aFrame->StyleDisplay()->mOpacity)
|
||||
, mForEventsOnly(aForEventsOnly)
|
||||
{
|
||||
@ -4198,6 +4206,8 @@ bool nsDisplayOpacity::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* a
|
||||
return false;
|
||||
if (aItem->GetClip() != GetClip())
|
||||
return false;
|
||||
if (aItem->ScrollClip() != ScrollClip())
|
||||
return false;
|
||||
MergeFromTrackingMergedFrames(static_cast<nsDisplayOpacity*>(aItem));
|
||||
return true;
|
||||
}
|
||||
@ -4283,6 +4293,8 @@ bool nsDisplayMixBlendMode::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayIt
|
||||
return false;
|
||||
if (aItem->GetClip() != GetClip())
|
||||
return false;
|
||||
if (aItem->ScrollClip() != ScrollClip())
|
||||
return false;
|
||||
MergeFromTrackingMergedFrames(static_cast<nsDisplayMixBlendMode*>(aItem));
|
||||
return true;
|
||||
}
|
||||
@ -4353,6 +4365,8 @@ bool nsDisplayBlendContainer::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplay
|
||||
return false;
|
||||
if (aItem->GetClip() != GetClip())
|
||||
return false;
|
||||
if (aItem->ScrollClip() != ScrollClip())
|
||||
return false;
|
||||
MergeFromTrackingMergedFrames(static_cast<nsDisplayBlendContainer*>(aItem));
|
||||
return true;
|
||||
}
|
||||
@ -4678,6 +4692,8 @@ bool nsDisplayStickyPosition::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplay
|
||||
return false;
|
||||
if (aItem->GetClip() != GetClip())
|
||||
return false;
|
||||
if (aItem->ScrollClip() != ScrollClip())
|
||||
return false;
|
||||
MergeFromTrackingMergedFrames(other);
|
||||
return true;
|
||||
}
|
||||
@ -5957,6 +5973,9 @@ nsDisplayTransform::TryMerge(nsDisplayListBuilder *aBuilder,
|
||||
if (aItem->GetClip() != GetClip())
|
||||
return false;
|
||||
|
||||
if (aItem->ScrollClip() != ScrollClip())
|
||||
return false;
|
||||
|
||||
/* Now, move everything over to this frame and signal that
|
||||
* we merged things!
|
||||
*/
|
||||
@ -6310,6 +6329,8 @@ bool nsDisplaySVGEffects::TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem
|
||||
return false;
|
||||
if (aItem->GetClip() != GetClip())
|
||||
return false;
|
||||
if (aItem->ScrollClip() != ScrollClip())
|
||||
return false;
|
||||
nsDisplaySVGEffects* other = static_cast<nsDisplaySVGEffects*>(aItem);
|
||||
MergeFromTrackingMergedFrames(other);
|
||||
mEffectsBounds.UnionRect(mEffectsBounds,
|
||||
|
@ -40,12 +40,14 @@ class nsRenderingContext;
|
||||
class nsDisplayList;
|
||||
class nsDisplayTableItem;
|
||||
class nsISelection;
|
||||
class nsIScrollableFrame;
|
||||
class nsDisplayLayerEventRegions;
|
||||
class nsDisplayScrollInfoLayer;
|
||||
class nsCaret;
|
||||
|
||||
namespace mozilla {
|
||||
class FrameLayerBuilder;
|
||||
class DisplayItemScrollClip;
|
||||
namespace layers {
|
||||
class Layer;
|
||||
class ImageLayer;
|
||||
@ -204,6 +206,7 @@ public:
|
||||
typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
|
||||
typedef mozilla::DisplayItemClip DisplayItemClip;
|
||||
typedef mozilla::DisplayListClipState DisplayListClipState;
|
||||
typedef mozilla::DisplayItemScrollClip DisplayItemScrollClip;
|
||||
typedef nsIWidget::ThemeGeometry ThemeGeometry;
|
||||
typedef mozilla::layers::Layer Layer;
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
@ -625,11 +628,21 @@ public:
|
||||
void* Allocate(size_t aSize);
|
||||
|
||||
/**
|
||||
* Allocate a new DisplayListClip in the arena. Will be cleaned up
|
||||
* Allocate a new DisplayItemClip in the arena. Will be cleaned up
|
||||
* automatically when the arena goes away.
|
||||
*/
|
||||
const DisplayItemClip* AllocateDisplayItemClip(const DisplayItemClip& aOriginal);
|
||||
|
||||
/**
|
||||
* Allocate a new DisplayItemScrollClip in the arena. Will be cleaned up
|
||||
* automatically when the arena goes away.
|
||||
*/
|
||||
DisplayItemScrollClip* AllocateDisplayItemScrollClip(const DisplayItemScrollClip* aParent,
|
||||
const DisplayItemScrollClip* aCrossStackingContextParent,
|
||||
nsIScrollableFrame* aScrollableFrame,
|
||||
const DisplayItemClip* aClip,
|
||||
bool aIsAsyncScrollable);
|
||||
|
||||
/**
|
||||
* Transfer off main thread animations to the layer. May be called
|
||||
* with aBuilder and aItem both null, but only if the caller has
|
||||
@ -933,15 +946,15 @@ public:
|
||||
void SetCurrentTableItem(nsDisplayTableItem* aTableItem) { mCurrentTableItem = aTableItem; }
|
||||
|
||||
struct OutOfFlowDisplayData {
|
||||
OutOfFlowDisplayData(const DisplayItemClip& aContainingBlockClip,
|
||||
OutOfFlowDisplayData(const DisplayItemClip* aContainingBlockClip,
|
||||
const DisplayItemScrollClip* aContainingBlockScrollClip,
|
||||
const nsRect &aDirtyRect)
|
||||
: mContainingBlockClip(aContainingBlockClip)
|
||||
: mContainingBlockClip(aContainingBlockClip ? *aContainingBlockClip : DisplayItemClip())
|
||||
, mContainingBlockScrollClip(aContainingBlockScrollClip)
|
||||
, mDirtyRect(aDirtyRect)
|
||||
{}
|
||||
explicit OutOfFlowDisplayData(const nsRect &aDirtyRect)
|
||||
: mDirtyRect(aDirtyRect)
|
||||
{}
|
||||
DisplayItemClip mContainingBlockClip;
|
||||
const DisplayItemScrollClip* mContainingBlockScrollClip;
|
||||
nsRect mDirtyRect;
|
||||
};
|
||||
|
||||
@ -1223,6 +1236,7 @@ private:
|
||||
// info items until the end of display list building.
|
||||
nsDisplayList* mPendingScrollInfoItems;
|
||||
nsDisplayList* mCommittedScrollInfoItems;
|
||||
nsTArray<DisplayItemScrollClip*> mScrollClipsToDestroy;
|
||||
nsTArray<DisplayItemClip*> mDisplayItemClipsToDestroy;
|
||||
Mode mMode;
|
||||
ViewID mCurrentScrollParentId;
|
||||
@ -1298,6 +1312,7 @@ class nsDisplayItem : public nsDisplayItemLink {
|
||||
public:
|
||||
typedef mozilla::ContainerLayerParameters ContainerLayerParameters;
|
||||
typedef mozilla::DisplayItemClip DisplayItemClip;
|
||||
typedef mozilla::DisplayItemScrollClip DisplayItemScrollClip;
|
||||
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
||||
typedef mozilla::layers::FrameMetrics::ViewID ViewID;
|
||||
typedef mozilla::layers::Layer Layer;
|
||||
@ -1314,6 +1329,7 @@ public:
|
||||
explicit nsDisplayItem(nsIFrame* aFrame)
|
||||
: mFrame(aFrame)
|
||||
, mClip(nullptr)
|
||||
, mScrollClip(nullptr)
|
||||
, mReferenceFrame(nullptr)
|
||||
, mAnimatedGeometryRoot(nullptr)
|
||||
#ifdef MOZ_DUMP_PAINTING
|
||||
@ -1413,6 +1429,17 @@ public:
|
||||
* account.
|
||||
*/
|
||||
nsRect GetClippedBounds(nsDisplayListBuilder* aBuilder);
|
||||
/**
|
||||
* Returns the result of GetClippedBounds, intersected with the item's
|
||||
* scroll clips. The item walks up its chain of scroll clips, *not* crossing
|
||||
* stacking contexts, applying each scroll clip until aIncludeScrollClipsUpTo
|
||||
* is reached. aIncludeScrollClipsUpTo is *not* applied.
|
||||
* The intersection is approximate since rounded corners are not taking into
|
||||
* account.
|
||||
*/
|
||||
nsRect GetClippedBoundsUpTo(nsDisplayListBuilder* aBuilder,
|
||||
const DisplayItemScrollClip* aIncludeScrollClipsUpTo);
|
||||
|
||||
nsRect GetBorderRect() {
|
||||
return nsRect(ToReferenceFrame(), Frame()->GetSize());
|
||||
}
|
||||
@ -1834,6 +1861,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void SetScrollClip(const DisplayItemScrollClip* aScrollClip) { mScrollClip = aScrollClip; }
|
||||
const DisplayItemScrollClip* ScrollClip() const { return mScrollClip; }
|
||||
|
||||
bool BackfaceIsHidden() {
|
||||
return mFrame->StyleDisplay()->BackfaceIsHidden();
|
||||
}
|
||||
@ -1845,6 +1875,7 @@ protected:
|
||||
|
||||
nsIFrame* mFrame;
|
||||
const DisplayItemClip* mClip;
|
||||
const DisplayItemScrollClip* mScrollClip;
|
||||
// Result of FindReferenceFrameFor(mFrame), if mFrame is non-null
|
||||
const nsIFrame* mReferenceFrame;
|
||||
struct AnimatedGeometryRoot* mAnimatedGeometryRoot;
|
||||
@ -1880,6 +1911,7 @@ protected:
|
||||
*/
|
||||
class nsDisplayList {
|
||||
public:
|
||||
typedef mozilla::DisplayItemScrollClip DisplayItemScrollClip;
|
||||
typedef mozilla::layers::Layer Layer;
|
||||
typedef mozilla::layers::LayerManager LayerManager;
|
||||
typedef mozilla::layers::PaintedLayer PaintedLayer;
|
||||
@ -2130,6 +2162,8 @@ public:
|
||||
* The result is not cached.
|
||||
*/
|
||||
nsRect GetBounds(nsDisplayListBuilder* aBuilder) const;
|
||||
nsRect GetClippedBoundsUpTo(nsDisplayListBuilder* aBuilder,
|
||||
const DisplayItemScrollClip* aIncludeScrollClipsUpTo) const;
|
||||
/**
|
||||
* Find the topmost display item that returns a non-null frame, and return
|
||||
* the frame.
|
||||
@ -2477,13 +2511,9 @@ public:
|
||||
virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) override;
|
||||
NS_DISPLAY_DECL_NAME("Caret", TYPE_CARET)
|
||||
|
||||
bool NeedsCustomScrollClip() { return mNeedsCustomScrollClip; }
|
||||
void SetNeedsCustomScrollClip() { mNeedsCustomScrollClip = true; }
|
||||
|
||||
protected:
|
||||
RefPtr<nsCaret> mCaret;
|
||||
nsRect mBounds;
|
||||
bool mNeedsCustomScrollClip;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -3157,7 +3187,7 @@ public:
|
||||
*/
|
||||
virtual void UpdateBounds(nsDisplayListBuilder* aBuilder) override
|
||||
{
|
||||
mBounds = mList.GetBounds(aBuilder);
|
||||
mBounds = mList.GetClippedBoundsUpTo(aBuilder, mScrollClip);
|
||||
// The display list may contain content that's visible outside the visible
|
||||
// rect (i.e. the current dirty rect) passed in when the item was created.
|
||||
// This happens when the dirty rect has been restricted to the visual
|
||||
@ -3300,7 +3330,9 @@ protected:
|
||||
class nsDisplayOpacity : public nsDisplayWrapList {
|
||||
public:
|
||||
nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
|
||||
nsDisplayList* aList, bool aForEventsOnly);
|
||||
nsDisplayList* aList,
|
||||
const DisplayItemScrollClip* aScrollClipForSameAGRChildren,
|
||||
bool aForEventsOnly);
|
||||
#ifdef NS_BUILD_REFCNT_LOGGING
|
||||
virtual ~nsDisplayOpacity();
|
||||
#endif
|
||||
@ -3333,7 +3365,11 @@ public:
|
||||
|
||||
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) override;
|
||||
|
||||
const DisplayItemScrollClip* ScrollClipForSameAGRChildren() const
|
||||
{ return mScrollClipForSameAGRChildren; }
|
||||
|
||||
private:
|
||||
const DisplayItemScrollClip* mScrollClipForSameAGRChildren;
|
||||
float mOpacity;
|
||||
bool mForEventsOnly;
|
||||
};
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "nsDisplayList.h"
|
||||
#include "FrameLayerBuilder.h"
|
||||
#include "nsPrintfCString.h"
|
||||
#include "DisplayItemScrollClip.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@ -177,7 +178,7 @@ PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
|
||||
aStream << nsPrintfCString("<a href=\"javascript:ViewImage('%s')\">", string.BeginReading());
|
||||
}
|
||||
#endif
|
||||
aStream << nsPrintfCString("%s p=0x%p f=0x%p(%s) %sbounds(%d,%d,%d,%d) layerBounds(%d,%d,%d,%d) visible(%d,%d,%d,%d) componentAlpha(%d,%d,%d,%d) clip(%s) %s ref=0x%p agr=0x%p",
|
||||
aStream << nsPrintfCString("%s p=0x%p f=0x%p(%s) %sbounds(%d,%d,%d,%d) layerBounds(%d,%d,%d,%d) visible(%d,%d,%d,%d) componentAlpha(%d,%d,%d,%d) clip(%s) scrollClip(%s)%s ref=0x%p agr=0x%p",
|
||||
aItem->Name(), aItem, (void*)f, NS_ConvertUTF16toUTF8(contentData).get(),
|
||||
(aItem->ZIndex() ? nsPrintfCString("z=%d ", aItem->ZIndex()).get() : ""),
|
||||
rect.x, rect.y, rect.width, rect.height,
|
||||
@ -185,6 +186,7 @@ PrintDisplayItemTo(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem,
|
||||
vis.x, vis.y, vis.width, vis.height,
|
||||
component.x, component.y, component.width, component.height,
|
||||
clip.ToString().get(),
|
||||
DisplayItemScrollClip::ToString(aItem->ScrollClip()).get(),
|
||||
aItem->IsUniform(aBuilder, &color) ? " uniform" : "",
|
||||
aItem->ReferenceFrame(), *aItem->GetAnimatedGeometryRoot());
|
||||
|
||||
|
@ -2058,7 +2058,11 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
// item itself will be clipped.
|
||||
// For transforms we also need to clear ancestor clipping because it's
|
||||
// relative to the wrong display item reference frame anyway.
|
||||
clipState.Clear();
|
||||
// We clear both regular and scroll clips here. Our content needs to be
|
||||
// able to walk up the complete cross stacking context scroll clip chain,
|
||||
// so we call a special method on the clip state that keeps the ancestor
|
||||
// scroll clip around.
|
||||
clipState.ClearForStackingContextContents();
|
||||
}
|
||||
|
||||
nsDisplayListCollection set;
|
||||
@ -2175,10 +2179,19 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
|
||||
// Don't clip nsDisplayOpacity items. We clip their descendants instead.
|
||||
// The clip we would set on an element with opacity would clip
|
||||
// all descendant content, but some should not be clipped.
|
||||
// We clear both regular clips and scroll clips. If this item's animated
|
||||
// geometry root has async scrolling, then the async scroll transform will
|
||||
// be applied on the opacity's descendants (because that's where the
|
||||
// scroll clip will be). However, this won't work if the opacity item is
|
||||
// inactive, which is why we record the pre-clear scroll clip here.
|
||||
const DisplayItemScrollClip* scrollClipForSameAGRChildren =
|
||||
aBuilder->ClipState().GetCurrentInnermostScrollClip();
|
||||
DisplayListClipState::AutoSaveRestore opacityClipState(aBuilder);
|
||||
opacityClipState.Clear();
|
||||
opacityClipState.ClearIncludingScrollClip();
|
||||
resultList.AppendNewToTop(
|
||||
new (aBuilder) nsDisplayOpacity(aBuilder, this, &resultList, opacityItemForEventsOnly));
|
||||
new (aBuilder) nsDisplayOpacity(aBuilder, this, &resultList,
|
||||
scrollClipForSameAGRChildren,
|
||||
opacityItemForEventsOnly));
|
||||
}
|
||||
|
||||
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
|
||||
@ -2495,6 +2508,8 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||
if (savedOutOfFlowData) {
|
||||
clipState.SetClipForContainingBlockDescendants(
|
||||
&savedOutOfFlowData->mContainingBlockClip);
|
||||
clipState.SetScrollClipForContainingBlockDescendants(
|
||||
savedOutOfFlowData->mContainingBlockScrollClip);
|
||||
}
|
||||
|
||||
// Setup clipping for the parent's overflow:-moz-hidden-unscrollable,
|
||||
|
@ -9,6 +9,7 @@
|
||||
|
||||
#include "base/compiler_specific.h"
|
||||
#include "DisplayItemClip.h"
|
||||
#include "DisplayItemScrollClip.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsPresContext.h"
|
||||
#include "nsView.h"
|
||||
@ -2832,32 +2833,42 @@ static void
|
||||
ClipItemsExceptCaret(nsDisplayList* aList,
|
||||
nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aClipFrame,
|
||||
const DisplayItemClip& aNonCaretClip,
|
||||
bool aUsingDisplayPort)
|
||||
const DisplayItemClip* aNonCaretClip,
|
||||
const DisplayItemScrollClip* aNonCaretScrollClip)
|
||||
{
|
||||
for (nsDisplayItem* i = aList->GetBottom(); i; i = i->GetAbove()) {
|
||||
if (!ShouldBeClippedByFrame(aClipFrame, i->Frame())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool isCaret = i->GetType() == nsDisplayItem::TYPE_CARET;
|
||||
if (aUsingDisplayPort && isCaret) {
|
||||
static_cast<nsDisplayCaret*>(i)->SetNeedsCustomScrollClip();
|
||||
}
|
||||
if (!aUsingDisplayPort && !isCaret) {
|
||||
if (i->GetType() != nsDisplayItem::TYPE_CARET) {
|
||||
bool unused;
|
||||
nsRect bounds = i->GetBounds(aBuilder, &unused);
|
||||
if (aNonCaretClip.IsRectAffectedByClip(bounds)) {
|
||||
if (aNonCaretClip && aNonCaretClip->IsRectAffectedByClip(bounds)) {
|
||||
DisplayItemClip newClip;
|
||||
newClip.IntersectWith(i->GetClip());
|
||||
newClip.IntersectWith(aNonCaretClip);
|
||||
newClip.IntersectWith(*aNonCaretClip);
|
||||
i->SetClip(aBuilder, newClip);
|
||||
}
|
||||
|
||||
if (aNonCaretScrollClip) {
|
||||
const DisplayItemScrollClip* currentScrollClip = i->ScrollClip();
|
||||
MOZ_ASSERT(DisplayItemScrollClip::IsAncestor(aNonCaretScrollClip->mParent,
|
||||
currentScrollClip));
|
||||
|
||||
// Overwrite the existing scroll clip with aNonCaretScrollClip, unless
|
||||
// the current scroll clip is deeper than aNonCaretScrollClip (which
|
||||
// means that the display item is nested inside another scroll frame).
|
||||
if (!currentScrollClip ||
|
||||
currentScrollClip->mParent == aNonCaretScrollClip->mParent) {
|
||||
i->SetScrollClip(aNonCaretScrollClip);
|
||||
}
|
||||
}
|
||||
}
|
||||
nsDisplayList* children = i->GetSameCoordinateSystemChildren();
|
||||
if (children) {
|
||||
ClipItemsExceptCaret(children, aBuilder, aClipFrame, aNonCaretClip,
|
||||
aUsingDisplayPort);
|
||||
aNonCaretScrollClip);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2866,17 +2877,15 @@ static void
|
||||
ClipListsExceptCaret(nsDisplayListCollection* aLists,
|
||||
nsDisplayListBuilder* aBuilder,
|
||||
nsIFrame* aClipFrame,
|
||||
const nsRect& aNonCaretClip,
|
||||
bool aUsingDisplayPort)
|
||||
const DisplayItemClip* aNonCaretClip,
|
||||
const DisplayItemScrollClip* aNonCaretScrollClip)
|
||||
{
|
||||
DisplayItemClip clip;
|
||||
clip.SetTo(aNonCaretClip);
|
||||
ClipItemsExceptCaret(aLists->BorderBackground(), aBuilder, aClipFrame, clip, aUsingDisplayPort);
|
||||
ClipItemsExceptCaret(aLists->BlockBorderBackgrounds(), aBuilder, aClipFrame, clip, aUsingDisplayPort);
|
||||
ClipItemsExceptCaret(aLists->Floats(), aBuilder, aClipFrame, clip, aUsingDisplayPort);
|
||||
ClipItemsExceptCaret(aLists->PositionedDescendants(), aBuilder, aClipFrame, clip, aUsingDisplayPort);
|
||||
ClipItemsExceptCaret(aLists->Outlines(), aBuilder, aClipFrame, clip, aUsingDisplayPort);
|
||||
ClipItemsExceptCaret(aLists->Content(), aBuilder, aClipFrame, clip, aUsingDisplayPort);
|
||||
ClipItemsExceptCaret(aLists->BorderBackground(), aBuilder, aClipFrame, aNonCaretClip, aNonCaretScrollClip);
|
||||
ClipItemsExceptCaret(aLists->BlockBorderBackgrounds(), aBuilder, aClipFrame, aNonCaretClip, aNonCaretScrollClip);
|
||||
ClipItemsExceptCaret(aLists->Floats(), aBuilder, aClipFrame, aNonCaretClip, aNonCaretScrollClip);
|
||||
ClipItemsExceptCaret(aLists->PositionedDescendants(), aBuilder, aClipFrame, aNonCaretClip, aNonCaretScrollClip);
|
||||
ClipItemsExceptCaret(aLists->Outlines(), aBuilder, aClipFrame, aNonCaretClip, aNonCaretScrollClip);
|
||||
ClipItemsExceptCaret(aLists->Content(), aBuilder, aClipFrame, aNonCaretClip, aNonCaretScrollClip);
|
||||
}
|
||||
|
||||
void
|
||||
@ -2904,10 +2913,6 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
}
|
||||
|
||||
// Clear the scroll port clip that was set during the last paint.
|
||||
mAncestorClip = Nothing();
|
||||
mAncestorClipForCaret = Nothing();
|
||||
|
||||
// We put non-overlay scrollbars in their own layers when this is the root
|
||||
// scroll frame and we are a toplevel content document. In this situation,
|
||||
// the scrollbar(s) would normally be assigned their own layer anyway, since
|
||||
@ -3044,6 +3049,9 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
}
|
||||
|
||||
nsIScrollableFrame* sf = do_QueryFrame(mOuter);
|
||||
MOZ_ASSERT(sf);
|
||||
|
||||
nsDisplayListCollection scrolledContent;
|
||||
{
|
||||
// Note that setting the current scroll parent id here means that positioned children
|
||||
@ -3057,12 +3065,6 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
? nsLayoutUtils::FindOrCreateIDFor(mScrolledFrame->GetContent())
|
||||
: aBuilder->GetCurrentScrollParentId());
|
||||
|
||||
// We need to apply at least one clip, potentially more, and each needs to be applied
|
||||
// through a separate DisplayListClipState::AutoSaveRestore object.
|
||||
// clipStatePtr will always point to the innermost used one.
|
||||
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
||||
DisplayListClipState::AutoSaveRestore* clipStatePtr = &clipState;
|
||||
|
||||
nsRect clipRect = mScrollPort + aBuilder->ToReferenceFrame(mOuter);
|
||||
// Our override of GetBorderRadii ensures we never have a radius at
|
||||
// the corners where we have a scrollbar.
|
||||
@ -3077,60 +3079,67 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
}
|
||||
|
||||
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
|
||||
if (mClipAllDescendants) {
|
||||
clipState.ClipContentDescendants(clipRect, haveRadii ? radii : nullptr);
|
||||
} else {
|
||||
clipState.ClipContainingBlockDescendants(clipRect, haveRadii ? radii : nullptr);
|
||||
}
|
||||
|
||||
Maybe<DisplayListClipState::AutoSaveRestore> clipStateCaret;
|
||||
if (contentBoxClipForCaret) {
|
||||
clipStateCaret.emplace(aBuilder);
|
||||
clipStatePtr = &*clipStateCaret;
|
||||
if (mClipAllDescendants) {
|
||||
clipStateCaret->ClipContentDescendants(*contentBoxClipForCaret);
|
||||
} else {
|
||||
clipStateCaret->ClipContainingBlockDescendants(*contentBoxClipForCaret);
|
||||
}
|
||||
}
|
||||
DisplayItemScrollClip* inactiveScrollClip = nullptr;
|
||||
|
||||
Maybe<DisplayListClipState::AutoSaveRestore> clipStateNonCaret;
|
||||
if (usingDisplayPort) {
|
||||
// Capture the clip state of the parent scroll frame. This will be saved
|
||||
// on FrameMetrics for layers with this frame as their animated geoemetry
|
||||
// root.
|
||||
mAncestorClipForCaret = ToMaybe(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder));
|
||||
|
||||
// Add the non-caret content box clip here so that it gets picked up by
|
||||
// mAncestorClip.
|
||||
if (contentBoxClipForNonCaretContent) {
|
||||
clipStateNonCaret.emplace(aBuilder);
|
||||
clipStatePtr = &*clipStateNonCaret;
|
||||
{
|
||||
DisplayListClipState::AutoSaveRestore contentBoxClipState(aBuilder);
|
||||
if (contentBoxClipForCaret) {
|
||||
if (mClipAllDescendants) {
|
||||
clipStateNonCaret->ClipContentDescendants(*contentBoxClipForNonCaretContent);
|
||||
contentBoxClipState.ClipContentDescendants(*contentBoxClipForCaret);
|
||||
} else {
|
||||
clipStateNonCaret->ClipContainingBlockDescendants(*contentBoxClipForNonCaretContent);
|
||||
contentBoxClipState.ClipContainingBlockDescendants(*contentBoxClipForCaret);
|
||||
}
|
||||
}
|
||||
mAncestorClip = ToMaybe(aBuilder->ClipState().GetCurrentCombinedClip(aBuilder));
|
||||
|
||||
// If we are using a display port, then ignore any pre-existing clip
|
||||
// passed down from our parents. The pre-existing clip would just defeat
|
||||
// the purpose of a display port which is to paint regions that are not
|
||||
// currently visible so that they can be brought into view asynchronously.
|
||||
// Notes:
|
||||
// - The pre-existing clip state will be restored when the
|
||||
// AutoSaveRestore goes out of scope, so there is no permanent change
|
||||
// to this clip state.
|
||||
// - We still set a clip to the scroll port further below where we
|
||||
// build the scroll wrapper. This doesn't prevent us from painting
|
||||
// the entire displayport, but it lets the compositor know to
|
||||
// clip to the scroll port after compositing.
|
||||
clipStatePtr->Clear();
|
||||
DisplayListClipState::AutoSaveRestore clipStateForScrollClip(aBuilder);
|
||||
if (usingDisplayPort) {
|
||||
if (mClipAllDescendants) {
|
||||
clipStateForScrollClip.TurnClipIntoScrollClipForContentDescendants(aBuilder, sf);
|
||||
} else {
|
||||
clipStateForScrollClip.TurnClipIntoScrollClipForContainingBlockDescendants(aBuilder, sf);
|
||||
}
|
||||
} else {
|
||||
// Create a scroll clip anyway because we might need to activate for scroll handoff.
|
||||
if (mClipAllDescendants) {
|
||||
inactiveScrollClip = clipStateForScrollClip.InsertInactiveScrollClipForContentDescendants(aBuilder, sf);
|
||||
} else {
|
||||
inactiveScrollClip = clipStateForScrollClip.InsertInactiveScrollClipForContainingBlockDescendants(aBuilder, sf);
|
||||
}
|
||||
MOZ_ASSERT(!inactiveScrollClip->mIsAsyncScrollable);
|
||||
}
|
||||
|
||||
aBuilder->StoreDirtyRectForScrolledContents(mOuter, dirtyRect);
|
||||
mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent);
|
||||
}
|
||||
|
||||
aBuilder->StoreDirtyRectForScrolledContents(mOuter, dirtyRect);
|
||||
mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, scrolledContent);
|
||||
if (contentBoxClipForNonCaretContent) {
|
||||
DisplayListClipState::AutoSaveRestore contentBoxClipState(aBuilder);
|
||||
if (mClipAllDescendants) {
|
||||
contentBoxClipState.ClipContentDescendants(*contentBoxClipForNonCaretContent);
|
||||
} else {
|
||||
contentBoxClipState.ClipContainingBlockDescendants(*contentBoxClipForNonCaretContent);
|
||||
}
|
||||
|
||||
DisplayListClipState::AutoSaveRestore clipStateForScrollClip(aBuilder);
|
||||
if (usingDisplayPort) {
|
||||
if (mClipAllDescendants) {
|
||||
clipStateForScrollClip.TurnClipIntoScrollClipForContentDescendants(aBuilder, sf);
|
||||
} else {
|
||||
clipStateForScrollClip.TurnClipIntoScrollClipForContainingBlockDescendants(aBuilder, sf);
|
||||
}
|
||||
}
|
||||
const DisplayItemClip* clipNonCaret = aBuilder->ClipState().GetCurrentCombinedClip(aBuilder);
|
||||
const DisplayItemScrollClip* scrollClipNonCaret = aBuilder->ClipState().GetCurrentInnermostScrollClip();
|
||||
ClipListsExceptCaret(&scrolledContent, aBuilder, mScrolledFrame,
|
||||
clipNonCaret, scrollClipNonCaret);
|
||||
}
|
||||
|
||||
if (idSetter.ShouldForceLayerForScrollParent() &&
|
||||
!gfxPrefs::LayoutUseContainersForRootFrames())
|
||||
@ -3141,6 +3150,9 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
//
|
||||
// This is not compatible when using containes for root scrollframes.
|
||||
MOZ_ASSERT(couldBuildLayer && mScrolledFrame->GetContent());
|
||||
if (inactiveScrollClip) {
|
||||
inactiveScrollClip->mIsAsyncScrollable = true;
|
||||
}
|
||||
if (!mWillBuildScrollableLayer) {
|
||||
// Set a displayport so next paint we don't have to force layerization
|
||||
// after the fact.
|
||||
@ -3163,11 +3175,6 @@ ScrollFrameHelper::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
aBuilder->ForceLayerForScrollParent();
|
||||
}
|
||||
|
||||
if (contentBoxClipForNonCaretContent) {
|
||||
ClipListsExceptCaret(&scrolledContent, aBuilder, mScrolledFrame,
|
||||
*contentBoxClipForNonCaretContent, usingDisplayPort);
|
||||
}
|
||||
|
||||
if (couldBuildLayer) {
|
||||
// Make sure that APZ will dispatch events back to content so we can create
|
||||
// a displayport for this frame. We'll add the item later on.
|
||||
@ -3267,36 +3274,23 @@ ScrollFrameHelper::DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
|
||||
}
|
||||
|
||||
|
||||
Maybe<DisplayItemClip>
|
||||
ScrollFrameHelper::ComputeScrollClip(bool aIsForCaret) const
|
||||
{
|
||||
const Maybe<DisplayItemClip>& ancestorClip = aIsForCaret ? mAncestorClipForCaret : mAncestorClip;
|
||||
if (!mWillBuildScrollableLayer || mIsScrollableLayerInRootContainer) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
return ancestorClip;
|
||||
}
|
||||
|
||||
Maybe<FrameMetricsAndClip>
|
||||
Maybe<FrameMetrics>
|
||||
ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer,
|
||||
nsIFrame* aContainerReferenceFrame,
|
||||
const ContainerLayerParameters& aParameters,
|
||||
bool aIsForCaret) const
|
||||
const DisplayItemClip* aClip) const
|
||||
{
|
||||
if (!mWillBuildScrollableLayer || mIsScrollableLayerInRootContainer) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
const Maybe<DisplayItemClip>& ancestorClip = aIsForCaret ? mAncestorClipForCaret : mAncestorClip;
|
||||
|
||||
nsPoint toReferenceFrame = mOuter->GetOffsetToCrossDoc(aContainerReferenceFrame);
|
||||
|
||||
Maybe<nsRect> parentLayerClip;
|
||||
// For containerful frames, the clip is on the container layer.
|
||||
if (ancestorClip &&
|
||||
if (aClip &&
|
||||
(!gfxPrefs::LayoutUseContainersForRootFrames() || mAddClipRectToLayer)) {
|
||||
parentLayerClip = Some(ancestorClip->GetClipRect());
|
||||
parentLayerClip = Some(aClip->GetClipRect());
|
||||
}
|
||||
|
||||
bool isRootContent = mIsRoot && mOuter->PresContext()->IsRootContentDocument();
|
||||
@ -3334,16 +3328,12 @@ ScrollFrameHelper::ComputeFrameMetrics(Layer* aLayer,
|
||||
|
||||
MOZ_ASSERT(mScrolledFrame->GetContent());
|
||||
|
||||
FrameMetricsAndClip result;
|
||||
|
||||
nsRect scrollport = mScrollPort + toReferenceFrame;
|
||||
result.metrics = nsLayoutUtils::ComputeFrameMetrics(
|
||||
|
||||
return Some(nsLayoutUtils::ComputeFrameMetrics(
|
||||
mScrolledFrame, mOuter, mOuter->GetContent(),
|
||||
aContainerReferenceFrame, aLayer, mScrollParentID,
|
||||
scrollport, parentLayerClip, isRootContent, aParameters);
|
||||
result.clip = ancestorClip;
|
||||
|
||||
return Some(result);
|
||||
scrollport, parentLayerClip, isRootContent, aParameters));
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -387,11 +387,10 @@ public:
|
||||
}
|
||||
}
|
||||
bool WantAsyncScroll() const;
|
||||
Maybe<FrameMetricsAndClip> ComputeFrameMetrics(
|
||||
Maybe<mozilla::layers::FrameMetrics> ComputeFrameMetrics(
|
||||
Layer* aLayer, nsIFrame* aContainerReferenceFrame,
|
||||
const ContainerLayerParameters& aParameters,
|
||||
bool aIsForCaret) const;
|
||||
mozilla::Maybe<mozilla::DisplayItemClip> ComputeScrollClip(bool aIsForCaret) const;
|
||||
const mozilla::DisplayItemClip* aClip) const;
|
||||
|
||||
// nsIScrollbarMediator
|
||||
void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection,
|
||||
@ -468,10 +467,6 @@ public:
|
||||
|
||||
FrameMetrics::ViewID mScrollParentID;
|
||||
|
||||
// The scroll port clip.
|
||||
Maybe<DisplayItemClip> mAncestorClip;
|
||||
Maybe<DisplayItemClip> mAncestorClipForCaret;
|
||||
|
||||
bool mNeverHasVerticalScrollbar:1;
|
||||
bool mNeverHasHorizontalScrollbar:1;
|
||||
bool mHasVerticalScrollbar:1;
|
||||
@ -836,16 +831,12 @@ public:
|
||||
virtual bool WantAsyncScroll() const override {
|
||||
return mHelper.WantAsyncScroll();
|
||||
}
|
||||
virtual mozilla::Maybe<mozilla::FrameMetricsAndClip> ComputeFrameMetrics(
|
||||
virtual mozilla::Maybe<mozilla::layers::FrameMetrics> ComputeFrameMetrics(
|
||||
Layer* aLayer, nsIFrame* aContainerReferenceFrame,
|
||||
const ContainerLayerParameters& aParameters,
|
||||
bool aIsForCaret) const override
|
||||
const mozilla::DisplayItemClip* aClip) const override
|
||||
{
|
||||
return mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, aParameters, aIsForCaret);
|
||||
}
|
||||
virtual mozilla::Maybe<mozilla::DisplayItemClip> ComputeScrollClip(bool aIsForCaret) const override
|
||||
{
|
||||
return mHelper.ComputeScrollClip(aIsForCaret);
|
||||
return mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, aParameters, aClip);
|
||||
}
|
||||
virtual bool IsIgnoringViewportClipping() const override {
|
||||
return mHelper.IsIgnoringViewportClipping();
|
||||
@ -1232,16 +1223,12 @@ public:
|
||||
virtual bool WantAsyncScroll() const override {
|
||||
return mHelper.WantAsyncScroll();
|
||||
}
|
||||
virtual mozilla::Maybe<mozilla::FrameMetricsAndClip> ComputeFrameMetrics(
|
||||
virtual mozilla::Maybe<mozilla::layers::FrameMetrics> ComputeFrameMetrics(
|
||||
Layer* aLayer, nsIFrame* aContainerReferenceFrame,
|
||||
const ContainerLayerParameters& aParameters,
|
||||
bool aIsForCaret) const override
|
||||
const mozilla::DisplayItemClip* aClip) const override
|
||||
{
|
||||
return mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, aParameters, aIsForCaret);
|
||||
}
|
||||
virtual mozilla::Maybe<mozilla::DisplayItemClip> ComputeScrollClip(bool aIsForCaret) const override
|
||||
{
|
||||
return mHelper.ComputeScrollClip(aIsForCaret);
|
||||
return mHelper.ComputeFrameMetrics(aLayer, aContainerReferenceFrame, aParameters, aClip);
|
||||
}
|
||||
virtual bool IsIgnoringViewportClipping() const override {
|
||||
return mHelper.IsIgnoringViewportClipping();
|
||||
|
@ -36,13 +36,6 @@ struct ContainerLayerParameters;
|
||||
namespace layers {
|
||||
class Layer;
|
||||
} // namespace layers
|
||||
|
||||
struct FrameMetricsAndClip
|
||||
{
|
||||
layers::FrameMetrics metrics;
|
||||
mozilla::Maybe<DisplayItemClip> clip;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
/**
|
||||
@ -407,11 +400,11 @@ public:
|
||||
* aLayer's animated geometry root is this frame. If there needs to be a
|
||||
* FrameMetrics contributed by this frame, append it to aOutput.
|
||||
*/
|
||||
virtual mozilla::Maybe<mozilla::FrameMetricsAndClip> ComputeFrameMetrics(
|
||||
virtual mozilla::Maybe<mozilla::layers::FrameMetrics> ComputeFrameMetrics(
|
||||
mozilla::layers::Layer* aLayer,
|
||||
nsIFrame* aContainerReferenceFrame,
|
||||
const ContainerLayerParameters& aParameters,
|
||||
bool aIsForCaret) const = 0;
|
||||
const mozilla::DisplayItemClip* aClip) const = 0;
|
||||
|
||||
/**
|
||||
* If this scroll frame is ignoring viewporting clipping
|
||||
@ -436,8 +429,6 @@ public:
|
||||
*/
|
||||
virtual bool UsesContainerScrolling() const = 0;
|
||||
|
||||
virtual mozilla::Maybe<mozilla::DisplayItemClip> ComputeScrollClip(bool aIsForCaret) const = 0;
|
||||
|
||||
/**
|
||||
* Determine if we should build a scrollable layer for this scroll frame and
|
||||
* return the result. It will also record this result on the scroll frame.
|
||||
|
@ -483,7 +483,7 @@ nsSubDocumentFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
||||
// the layer we will construct will be clipped by the current clip.
|
||||
// In fact for nsDisplayZoom propagating it down would be incorrect since
|
||||
// nsDisplayZoom changes the meaning of appunits.
|
||||
nestedClipState.Clear();
|
||||
nestedClipState.ClearForStackingContextContents();
|
||||
}
|
||||
|
||||
if (subdocRootFrame) {
|
||||
|
@ -21,7 +21,7 @@ skip-if(!asyncPan) == position-fixed-cover-3.html position-fixed-cover-3-ref.htm
|
||||
skip-if(!asyncPan) == position-fixed-transformed-1.html position-fixed-transformed-1-ref.html
|
||||
skip-if(!asyncPan) == split-layers-1.html split-layers-1-ref.html
|
||||
skip-if(!asyncPan) == split-layers-multi-scrolling-1.html split-layers-multi-scrolling-1-ref.html
|
||||
fails skip-if(!asyncPan) == split-opacity-layers-1.html split-opacity-layers-1-ref.html
|
||||
skip-if(!asyncPan) == split-opacity-layers-1.html split-opacity-layers-1-ref.html
|
||||
skip-if(!asyncPan) == sticky-pos-scrollable-1.html sticky-pos-scrollable-1-ref.html
|
||||
skip-if(!asyncPan) == fixed-pos-scrollable-1.html fixed-pos-scrollable-1-ref.html
|
||||
skip-if(!asyncPan) == culling-1.html culling-1-ref.html
|
||||
|
@ -1672,7 +1672,7 @@ skip-if(B2G||Mulet) == 641770-1.html 641770-1-ref.html # Initial mulet triage: p
|
||||
== 641856-1.html 641856-1-ref.html
|
||||
== 645491-1.html 645491-1-ref.html
|
||||
== 645768-1.html 645768-1-ref.html
|
||||
fails-if(layersGPUAccelerated&&cocoaWidget) fails-if(Android&&AndroidVersion<15&&AndroidVersion!=10) fuzzy-if(asyncPan&&!layersGPUAccelerated,41,260) == 650228-1.html 650228-1-ref.html # Quartz alpha blending doesn't match GL alpha blending
|
||||
fails-if(layersGPUAccelerated&&cocoaWidget) fails-if(Android&&AndroidVersion<15&&AndroidVersion!=10) fuzzy-if(!layersGPUAccelerated,41,260) == 650228-1.html 650228-1-ref.html # Quartz alpha blending doesn't match GL alpha blending
|
||||
needs-focus == 652301-1a.html 652301-1-ref.html
|
||||
needs-focus == 652301-1b.html 652301-1-ref.html
|
||||
== 652775-1.html 652775-1-ref.html
|
||||
|
@ -16,6 +16,6 @@ skip-if(!asyncPan) != pull-background-displayport-1.html about:blank
|
||||
skip-if(!asyncPan) != pull-background-displayport-2.html about:blank
|
||||
skip-if(!asyncPan) != pull-background-displayport-3.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
|
||||
skip-if(!asyncPan) != pull-background-displayport-4.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
|
||||
fails skip-if(!asyncPan) != pull-background-displayport-5.html about:blank # bug 1147673
|
||||
skip-if(!asyncPan) != pull-background-displayport-5.html about:blank
|
||||
skip-if(!asyncPan) != pull-background-displayport-6.html about:blank # fails with non-overlay scrollbars and event regions due to bug 1148515
|
||||
fuzzy(2,30150) == opacity-blending.html opacity-blending-ref.html
|
||||
|
@ -58,5 +58,5 @@ skip-if(B2G||Mulet) == border-separate-opacity-table.html border-separate-opacit
|
||||
== scrollable-rowgroup-separate-border.html scrollable-rowgroup-separate-notref.html # scrolling rowgroups were removed in bug 28800
|
||||
== empty-cells-default-1.html empty-cells-default-1-ref.html
|
||||
== empty-cells-default-2.html empty-cells-default-2-ref.html
|
||||
fuzzy-if(OSX,1,113) fuzzy-if(winWidget,1,12) fuzzy-if(Android,1,39) == table-row-opacity-dynamic-1.html table-row-opacity-dynamic-1-ref.html
|
||||
fuzzy-if(OSX,1,113) fuzzy-if(winWidget,1,12) fuzzy-if(Android,1,39) fuzzy-if(winWidget&&!layersGPUAccelerated,82,116) == table-row-opacity-dynamic-1.html table-row-opacity-dynamic-1-ref.html
|
||||
== table-row-opacity-dynamic-2.html table-row-opacity-dynamic-2-ref.html
|
||||
|
Loading…
Reference in New Issue
Block a user