mirror of
https://github.com/classilla/tenfourfox.git
synced 2024-06-16 14:29:46 +00:00
#396: M1342009, plus refactor to PLDHashTable a la M1352888
This commit is contained in:
parent
6dc5f54dcd
commit
06fcc091fc
|
@ -694,7 +694,7 @@ AnimatedGeometryRoot*
|
||||||
nsDisplayListBuilder::WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
|
nsDisplayListBuilder::WrapAGRForFrame(nsIFrame* aAnimatedGeometryRoot,
|
||||||
AnimatedGeometryRoot* aParent /* = nullptr */)
|
AnimatedGeometryRoot* aParent /* = nullptr */)
|
||||||
{
|
{
|
||||||
MOZ_ASSERT(IsAnimatedGeometryRoot(aAnimatedGeometryRoot));
|
MOZ_ASSERT(IsAnimatedGeometryRoot(aAnimatedGeometryRoot) == AGR_YES);
|
||||||
|
|
||||||
AnimatedGeometryRoot* result = nullptr;
|
AnimatedGeometryRoot* result = nullptr;
|
||||||
if (!mFrameToAnimatedGeometryRootMap.Get(aAnimatedGeometryRoot, &result)) {
|
if (!mFrameToAnimatedGeometryRootMap.Get(aAnimatedGeometryRoot, &result)) {
|
||||||
|
@ -1079,66 +1079,91 @@ IsStickyFrameActive(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, nsIFrame*
|
||||||
return sf->IsScrollingActive(aBuilder) && sf->GetScrolledFrame() == cursor;
|
return sf->IsScrollingActive(aBuilder) && sf->GetScrolledFrame() == cursor;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
nsDisplayListBuilder::AGRState
|
||||||
nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent)
|
nsDisplayListBuilder::IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent)
|
||||||
{
|
{
|
||||||
if (aFrame == mReferenceFrame) {
|
if (aFrame == mReferenceFrame) {
|
||||||
return true;
|
return AGR_YES;
|
||||||
}
|
}
|
||||||
if (!IsPaintingToWindow()) {
|
if (!IsPaintingToWindow()) {
|
||||||
if (aParent) {
|
if (aParent) {
|
||||||
*aParent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
|
*aParent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
|
||||||
}
|
}
|
||||||
return false;
|
return AGR_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nsLayoutUtils::IsPopup(aFrame))
|
if (nsLayoutUtils::IsPopup(aFrame))
|
||||||
return true;
|
return AGR_YES;
|
||||||
if (ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(aFrame))
|
if (ActiveLayerTracker::IsOffsetOrMarginStyleAnimated(aFrame))
|
||||||
return true;
|
// XXX: If we wanted to implement an AGRBudget, that's here.
|
||||||
|
// See bug 1247554, but it might not be needed since we have bug 1231818.
|
||||||
|
|
||||||
|
return AGR_YES;
|
||||||
if (!aFrame->GetParent() &&
|
if (!aFrame->GetParent() &&
|
||||||
nsLayoutUtils::ViewportHasDisplayPort(aFrame->PresContext())) {
|
nsLayoutUtils::ViewportHasDisplayPort(aFrame->PresContext())) {
|
||||||
// Viewport frames in a display port need to be animated geometry roots
|
// Viewport frames in a display port need to be animated geometry roots
|
||||||
// for background-attachment:fixed elements.
|
// for background-attachment:fixed elements.
|
||||||
return true;
|
return AGR_YES;
|
||||||
}
|
}
|
||||||
if (aFrame->IsTransformed()) {
|
if (aFrame->IsTransformed()) {
|
||||||
return true;
|
return AGR_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
|
nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(aFrame);
|
||||||
if (!parent)
|
if (!parent)
|
||||||
return true;
|
return AGR_YES;
|
||||||
|
|
||||||
|
bool maybe = false; // Possible to transition from not being an AGR
|
||||||
|
// to being an AGR without a style change.
|
||||||
|
|
||||||
nsIAtom* parentType = parent->GetType();
|
nsIAtom* parentType = parent->GetType();
|
||||||
// Treat the slider thumb as being as an active scrolled root when it wants
|
// Treat the slider thumb as being as an active scrolled root when it wants
|
||||||
// its own layer so that it can move without repainting.
|
// its own layer so that it can move without repainting.
|
||||||
if (parentType == nsGkAtoms::sliderFrame && nsLayoutUtils::IsScrollbarThumbLayerized(aFrame)) {
|
if (parentType == nsGkAtoms::sliderFrame) {
|
||||||
return true;
|
if (nsLayoutUtils::IsScrollbarThumbLayerized(aFrame)) {
|
||||||
|
return AGR_YES;
|
||||||
|
}
|
||||||
|
maybe = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY &&
|
if (aFrame->StyleDisplay()->mPosition == NS_STYLE_POSITION_STICKY) {
|
||||||
IsStickyFrameActive(this, aFrame, parent))
|
if (IsStickyFrameActive(this, aFrame, parent)) {
|
||||||
{
|
return AGR_YES;
|
||||||
return true;
|
}
|
||||||
|
maybe = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parentType == nsGkAtoms::scrollFrame || parentType == nsGkAtoms::listControlFrame) {
|
if (parentType == nsGkAtoms::scrollFrame || parentType == nsGkAtoms::listControlFrame) {
|
||||||
nsIScrollableFrame* sf = do_QueryFrame(parent);
|
nsIScrollableFrame* sf = do_QueryFrame(parent);
|
||||||
if (sf->IsScrollingActive(this) && sf->GetScrolledFrame() == aFrame) {
|
if (sf->GetScrolledFrame() == aFrame) {
|
||||||
return true;
|
if (sf->IsScrollingActive(this)) {
|
||||||
|
return AGR_YES;
|
||||||
|
}
|
||||||
|
maybe = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fixed-pos frames are parented by the viewport frame, which has no parent.
|
// Fixed-pos frames are parented by the viewport frame, which has no parent.
|
||||||
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame)) {
|
if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame)) {
|
||||||
return true;
|
return AGR_YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((aFrame->GetStateBits() & NS_FRAME_MAY_BE_TRANSFORMED) &&
|
||||||
|
aFrame->IsFrameOfType(nsIFrame::eSVG)) {
|
||||||
|
// For SVG containers, they always have
|
||||||
|
// NS_FRAME_MAY_BE_TRANSFORMED bit. However, they would be
|
||||||
|
// affected by the fragement identifiers in the svgView form at
|
||||||
|
// runtime without a new style context.
|
||||||
|
// For example, layout/reftests/svg/fragmentIdentifier-01.xhtml
|
||||||
|
//
|
||||||
|
// see https://www.w3.org/TR/SVG/linking.html#SVGFragmentIdentifiers
|
||||||
|
maybe = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (aParent) {
|
if (aParent) {
|
||||||
*aParent = parent;
|
*aParent = parent;
|
||||||
}
|
}
|
||||||
return false;
|
return !maybe ? AGR_NO : AGR_MAYBE;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsIFrame*
|
nsIFrame*
|
||||||
|
@ -1148,7 +1173,7 @@ nsDisplayListBuilder::FindAnimatedGeometryRootFrameFor(nsIFrame* aFrame)
|
||||||
nsIFrame* cursor = aFrame;
|
nsIFrame* cursor = aFrame;
|
||||||
while (cursor != RootReferenceFrame()) {
|
while (cursor != RootReferenceFrame()) {
|
||||||
nsIFrame* next;
|
nsIFrame* next;
|
||||||
if (IsAnimatedGeometryRoot(cursor, &next))
|
if (IsAnimatedGeometryRoot(cursor, &next) == AGR_YES)
|
||||||
return cursor;
|
return cursor;
|
||||||
cursor = next;
|
cursor = next;
|
||||||
}
|
}
|
||||||
|
@ -1159,7 +1184,7 @@ void
|
||||||
nsDisplayListBuilder::RecomputeCurrentAnimatedGeometryRoot()
|
nsDisplayListBuilder::RecomputeCurrentAnimatedGeometryRoot()
|
||||||
{
|
{
|
||||||
if (*mCurrentAGR != mCurrentFrame &&
|
if (*mCurrentAGR != mCurrentFrame &&
|
||||||
IsAnimatedGeometryRoot(const_cast<nsIFrame*>(mCurrentFrame))) {
|
IsAnimatedGeometryRoot(const_cast<nsIFrame*>(mCurrentFrame)) == AGR_YES) {
|
||||||
AnimatedGeometryRoot* oldAGR = mCurrentAGR;
|
AnimatedGeometryRoot* oldAGR = mCurrentAGR;
|
||||||
mCurrentAGR = WrapAGRForFrame(const_cast<nsIFrame*>(mCurrentFrame), mCurrentAGR);
|
mCurrentAGR = WrapAGRForFrame(const_cast<nsIFrame*>(mCurrentFrame), mCurrentAGR);
|
||||||
|
|
||||||
|
|
|
@ -160,6 +160,15 @@ class nsDisplayListBuilder {
|
||||||
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
|
typedef mozilla::LayoutDeviceIntRect LayoutDeviceIntRect;
|
||||||
typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
|
typedef mozilla::LayoutDeviceIntRegion LayoutDeviceIntRegion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A frame can be in one of three states of AGR.
|
||||||
|
* AGR_NO means the frame is not an AGR for now.
|
||||||
|
* AGR_YES means the frame is an AGR for now.
|
||||||
|
* AGR_MAYBE means the frame is not an AGR for now, but a transition
|
||||||
|
* to AGR_YES without restyling is possible.
|
||||||
|
*/
|
||||||
|
enum AGRState { AGR_NO, AGR_YES, AGR_MAYBE };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
|
typedef mozilla::FramePropertyDescriptor FramePropertyDescriptor;
|
||||||
typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
|
typedef mozilla::FrameLayerBuilder FrameLayerBuilder;
|
||||||
|
@ -636,8 +645,9 @@ public:
|
||||||
aBuilder->FindReferenceFrameFor(aForChild,
|
aBuilder->FindReferenceFrameFor(aForChild,
|
||||||
&aBuilder->mCurrentOffsetToReferenceFrame);
|
&aBuilder->mCurrentOffsetToReferenceFrame);
|
||||||
}
|
}
|
||||||
|
mCurrentAGRState = aBuilder->IsAnimatedGeometryRoot(aForChild);
|
||||||
if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
|
if (aBuilder->mCurrentFrame == aForChild->GetParent()) {
|
||||||
if (aBuilder->IsAnimatedGeometryRoot(aForChild)) {
|
if (mCurrentAGRState == AGR_YES) {
|
||||||
aBuilder->mCurrentAGR = aBuilder->WrapAGRForFrame(aForChild, aBuilder->mCurrentAGR);
|
aBuilder->mCurrentAGR = aBuilder->WrapAGRForFrame(aForChild, aBuilder->mCurrentAGR);
|
||||||
}
|
}
|
||||||
} else if (aForChild != aBuilder->mCurrentFrame) {
|
} else if (aForChild != aBuilder->mCurrentFrame) {
|
||||||
|
@ -661,8 +671,10 @@ public:
|
||||||
return mPrevAnimatedGeometryRoot;
|
return mPrevAnimatedGeometryRoot;
|
||||||
}
|
}
|
||||||
bool IsAnimatedGeometryRoot() const {
|
bool IsAnimatedGeometryRoot() const {
|
||||||
return *mBuilder->mCurrentAGR == mBuilder->mCurrentFrame;
|
return mCurrentAGRState == AGR_YES;
|
||||||
|
}
|
||||||
|
bool MaybeAnimatedGeometryRoot() const {
|
||||||
|
return mCurrentAGRState == AGR_MAYBE;
|
||||||
}
|
}
|
||||||
~AutoBuildingDisplayList() {
|
~AutoBuildingDisplayList() {
|
||||||
mBuilder->mCurrentFrame = mPrevFrame;
|
mBuilder->mCurrentFrame = mPrevFrame;
|
||||||
|
@ -676,6 +688,7 @@ public:
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
nsDisplayListBuilder* mBuilder;
|
nsDisplayListBuilder* mBuilder;
|
||||||
|
AGRState mCurrentAGRState;
|
||||||
const nsIFrame* mPrevFrame;
|
const nsIFrame* mPrevFrame;
|
||||||
const nsIFrame* mPrevReferenceFrame;
|
const nsIFrame* mPrevReferenceFrame;
|
||||||
nsIFrame* mPrevAnimatedGeometryRoot;
|
nsIFrame* mPrevAnimatedGeometryRoot;
|
||||||
|
@ -938,7 +951,7 @@ private:
|
||||||
* Returns whether a frame acts as an animated geometry root, optionally
|
* Returns whether a frame acts as an animated geometry root, optionally
|
||||||
* returning the next ancestor to check.
|
* returning the next ancestor to check.
|
||||||
*/
|
*/
|
||||||
bool IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent = nullptr);
|
AGRState IsAnimatedGeometryRoot(nsIFrame* aFrame, nsIFrame** aParent = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the nearest ancestor frame to aFrame that is considered to have
|
* Returns the nearest ancestor frame to aFrame that is considered to have
|
||||||
|
|
|
@ -870,6 +870,12 @@ nsFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
|
||||||
if (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
|
if (StyleVisibility()->mDirection == NS_STYLE_DIRECTION_RTL) {
|
||||||
PresContext()->SetBidiEnabled();
|
PresContext()->SetBidiEnabled();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* bug 1342009 has the following:
|
||||||
|
RemoveStateBits(NS_FRAME_SIMPLE_EVENT_REGIONS |
|
||||||
|
NS_FRAME_SIMPLE_DISPLAYLIST);
|
||||||
|
*/
|
||||||
|
RemoveStateBits(NS_FRAME_SIMPLE_DISPLAYLIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
// MSVC fails with link error "one or more multiply defined symbols found",
|
// MSVC fails with link error "one or more multiply defined symbols found",
|
||||||
|
@ -1705,8 +1711,10 @@ ApplyClipPropClipping(nsDisplayListBuilder* aBuilder,
|
||||||
* handled by constructing a dedicated nsHTML/XULScrollFrame, set up clipping
|
* handled by constructing a dedicated nsHTML/XULScrollFrame, set up clipping
|
||||||
* for that overflow in aBuilder->ClipState() to clip all containing-block
|
* for that overflow in aBuilder->ClipState() to clip all containing-block
|
||||||
* descendants.
|
* descendants.
|
||||||
|
*
|
||||||
|
* Return true if clipping was applied.
|
||||||
*/
|
*/
|
||||||
static void
|
static bool
|
||||||
ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
|
ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
|
||||||
const nsIFrame* aFrame,
|
const nsIFrame* aFrame,
|
||||||
const nsStyleDisplay* aDisp,
|
const nsStyleDisplay* aDisp,
|
||||||
|
@ -1718,7 +1726,7 @@ ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
|
||||||
// is required by comboboxes which make their display text (an inline frame)
|
// is required by comboboxes which make their display text (an inline frame)
|
||||||
// have clipping.
|
// have clipping.
|
||||||
if (!nsFrame::ShouldApplyOverflowClipping(aFrame, aDisp)) {
|
if (!nsFrame::ShouldApplyOverflowClipping(aFrame, aDisp)) {
|
||||||
return;
|
return false;
|
||||||
}
|
}
|
||||||
nsRect clipRect;
|
nsRect clipRect;
|
||||||
bool haveRadii = false;
|
bool haveRadii = false;
|
||||||
|
@ -1734,6 +1742,7 @@ ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
|
||||||
// XXX border-radius
|
// XXX border-radius
|
||||||
}
|
}
|
||||||
aClipState.ClipContainingBlockDescendantsExtra(clipRect, haveRadii ? radii : nullptr);
|
aClipState.ClipContainingBlockDescendantsExtra(clipRect, haveRadii ? radii : nullptr);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -2334,6 +2343,45 @@ WrapInWrapList(nsDisplayListBuilder* aBuilder,
|
||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a frame should be visited for building display list.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
DescendIntoChild(nsDisplayListBuilder* aBuilder, nsIFrame *aChild,
|
||||||
|
const nsRect& aDirty)
|
||||||
|
{
|
||||||
|
nsIFrame* child = aChild;
|
||||||
|
const nsRect& dirty = aDirty;
|
||||||
|
|
||||||
|
if (!(child->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
|
||||||
|
// No need to descend into child to catch placeholders for visible
|
||||||
|
// positioned stuff. So see if we can short-circuit frame traversal here.
|
||||||
|
|
||||||
|
// We can stop if child's frame subtree's intersection with the
|
||||||
|
// dirty area is empty.
|
||||||
|
// If the child is a scrollframe that we want to ignore, then we need
|
||||||
|
// to descend into it because its scrolled child may intersect the dirty
|
||||||
|
// area even if the scrollframe itself doesn't.
|
||||||
|
// There are cases where the "ignore scroll frame" on the builder is not set
|
||||||
|
// correctly, and so we additionally want to catch cases where the child is
|
||||||
|
// a root scrollframe and we are ignoring scrolling on the viewport.
|
||||||
|
nsIPresShell* shell = child->PresContext()->PresShell();
|
||||||
|
bool keepDescending = child == aBuilder->GetIgnoreScrollFrame() ||
|
||||||
|
(shell->IgnoringViewportScrolling() && child == shell->GetRootScrollFrame());
|
||||||
|
if (!keepDescending) {
|
||||||
|
nsRect childDirty;
|
||||||
|
if (!childDirty.IntersectRect(dirty, child->GetVisualOverflowRect()))
|
||||||
|
return false;
|
||||||
|
// Usually we could set dirty to childDirty now but there's no
|
||||||
|
// benefit, and it can be confusing. It can especially confuse
|
||||||
|
// situations where we're going to ignore a scrollframe's clipping;
|
||||||
|
// we wouldn't want to clip the dirty area to the scrollframe's
|
||||||
|
// bounds in that case.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
nsIFrame* aChild,
|
nsIFrame* aChild,
|
||||||
|
@ -2349,11 +2397,59 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
if (child->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
|
if (child->GetStateBits() & NS_FRAME_TOO_DEEP_IN_FRAME_TREE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
const bool doingShortcut =
|
||||||
|
(child->GetStateBits() & NS_FRAME_SIMPLE_DISPLAYLIST) &&
|
||||||
|
aBuilder->IsPaintingToWindow() &&
|
||||||
|
// This would be changed by the change of preference.
|
||||||
|
aBuilder->IsBuildingLayerEventRegions() &&
|
||||||
|
// Animations may change the value of |HasOpacity()|.
|
||||||
|
!(child->GetContent() &&
|
||||||
|
child->GetContent()->MayHaveAnimations());
|
||||||
|
if (doingShortcut) {
|
||||||
|
// This is the shortcut for frames been handled along the common
|
||||||
|
// path, the most common one of THE COMMON CASE mentioned later.
|
||||||
|
MOZ_ASSERT(child->Type() != LayoutFrameType::Placeholder);
|
||||||
|
MOZ_ASSERT(!aBuilder->GetSelectedFramesOnly() &&
|
||||||
|
!aBuilder->GetIncludeAllOutOfFlows(),
|
||||||
|
"It should be held for painting to window");
|
||||||
|
|
||||||
|
// dirty rect in child-relative coordinates
|
||||||
|
nsRect dirty = aDirtyRect - child->GetOffsetTo(this);
|
||||||
|
if (!DescendIntoChild(aBuilder, child, dirty)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
nsDisplayListBuilder::AutoBuildingDisplayList
|
||||||
|
buildingForChild(aBuilder, child, dirty, false);
|
||||||
|
|
||||||
|
CheckForApzAwareEventHandlers(aBuilder, child);
|
||||||
|
|
||||||
|
nsDisplayLayerEventRegions* eventRegions = aBuilder->GetLayerEventRegions();
|
||||||
|
if (eventRegions) {
|
||||||
|
eventRegions->AddFrame(aBuilder, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty);
|
||||||
|
aBuilder->AdjustWindowDraggingRegion(child);
|
||||||
|
child->BuildDisplayList(aBuilder, dirty, aLists);
|
||||||
|
aBuilder->DisplayCaret(child, dirty, aLists.Content());
|
||||||
|
#ifdef DEBUG
|
||||||
|
// DisplayDebugBorders(aBuilder, child, aLists);
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool isSVG = (child->GetStateBits() & NS_FRAME_SVG_LAYOUT);
|
bool isSVG = (child->GetStateBits() & NS_FRAME_SVG_LAYOUT);
|
||||||
|
|
||||||
|
// It is raised if the control flow strays off the common path.
|
||||||
|
// The common path is the most common one of THE COMMON CASE
|
||||||
|
// mentioned later.
|
||||||
|
bool awayFromCommonPath = false;
|
||||||
|
|
||||||
// true if this is a real or pseudo stacking context
|
// true if this is a real or pseudo stacking context
|
||||||
bool pseudoStackingContext =
|
bool pseudoStackingContext =
|
||||||
(aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0;
|
(aFlags & DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT) != 0;
|
||||||
|
awayFromCommonPath |= pseudoStackingContext;
|
||||||
if (!isSVG &&
|
if (!isSVG &&
|
||||||
(aFlags & DISPLAY_CHILD_INLINE) &&
|
(aFlags & DISPLAY_CHILD_INLINE) &&
|
||||||
!child->IsFrameOfType(eLineParticipant)) {
|
!child->IsFrameOfType(eLineParticipant)) {
|
||||||
|
@ -2361,6 +2457,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
// it acts like inline-block or inline-table. Therefore it is a
|
// it acts like inline-block or inline-table. Therefore it is a
|
||||||
// pseudo-stacking-context.
|
// pseudo-stacking-context.
|
||||||
pseudoStackingContext = true;
|
pseudoStackingContext = true;
|
||||||
|
awayFromCommonPath = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dirty rect in child-relative coordinates
|
// dirty rect in child-relative coordinates
|
||||||
|
@ -2408,6 +2505,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
dirty.SetEmpty();
|
dirty.SetEmpty();
|
||||||
}
|
}
|
||||||
pseudoStackingContext = true;
|
pseudoStackingContext = true;
|
||||||
|
awayFromCommonPath = true;
|
||||||
}
|
}
|
||||||
if (child->Preserves3D()) {
|
if (child->Preserves3D()) {
|
||||||
nsRect* savedDirty = static_cast<nsRect*>
|
nsRect* savedDirty = static_cast<nsRect*>
|
||||||
|
@ -2430,31 +2528,9 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
if (aBuilder->GetIncludeAllOutOfFlows() &&
|
if (aBuilder->GetIncludeAllOutOfFlows() &&
|
||||||
(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
(child->GetStateBits() & NS_FRAME_OUT_OF_FLOW)) {
|
||||||
dirty = child->GetVisualOverflowRect();
|
dirty = child->GetVisualOverflowRect();
|
||||||
} else if (!(child->GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO)) {
|
awayFromCommonPath = true;
|
||||||
// No need to descend into child to catch placeholders for visible
|
} else if (!DescendIntoChild(aBuilder, child, dirty)) {
|
||||||
// positioned stuff. So see if we can short-circuit frame traversal here.
|
return;
|
||||||
|
|
||||||
// We can stop if child's frame subtree's intersection with the
|
|
||||||
// dirty area is empty.
|
|
||||||
// If the child is a scrollframe that we want to ignore, then we need
|
|
||||||
// to descend into it because its scrolled child may intersect the dirty
|
|
||||||
// area even if the scrollframe itself doesn't.
|
|
||||||
// There are cases where the "ignore scroll frame" on the builder is not set
|
|
||||||
// correctly, and so we additionally want to catch cases where the child is
|
|
||||||
// a root scrollframe and we are ignoring scrolling on the viewport.
|
|
||||||
nsIPresShell* shell = PresContext()->PresShell();
|
|
||||||
bool keepDescending = child == aBuilder->GetIgnoreScrollFrame() ||
|
|
||||||
(shell->IgnoringViewportScrolling() && child == shell->GetRootScrollFrame());
|
|
||||||
if (!keepDescending) {
|
|
||||||
nsRect childDirty;
|
|
||||||
if (!childDirty.IntersectRect(dirty, child->GetVisualOverflowRect()))
|
|
||||||
return;
|
|
||||||
// Usually we could set dirty to childDirty now but there's no
|
|
||||||
// benefit, and it can be confusing. It can especially confuse
|
|
||||||
// situations where we're going to ignore a scrollframe's clipping;
|
|
||||||
// we wouldn't want to clip the dirty area to the scrollframe's
|
|
||||||
// bounds in that case.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX need to have inline-block and inline-table set pseudoStackingContext
|
// XXX need to have inline-block and inline-table set pseudoStackingContext
|
||||||
|
@ -2466,6 +2542,16 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
!PresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
|
!PresContext()->GetTheme()->WidgetIsContainer(ourDisp->mAppearance))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
#if(0)
|
||||||
|
// XXX: The backbug from bug 1342009 for tracking visibility at this
|
||||||
|
// point is only required if we implement bug 1261554 (then we also need
|
||||||
|
// bug 1284350).
|
||||||
|
if (aBuilder->IsPaintingToWindow() && child->TrackingVisibility()) {
|
||||||
|
child->PresContext()->PresShell()->EnsureFrameInApproximatelyVisibleList(child);
|
||||||
|
awayFromCommonPath = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Child is composited if it's transformed, partially transparent, or has
|
// Child is composited if it's transformed, partially transparent, or has
|
||||||
// SVG effects or a blend mode..
|
// SVG effects or a blend mode..
|
||||||
const nsStylePosition* pos = child->StylePosition();
|
const nsStylePosition* pos = child->StylePosition();
|
||||||
|
@ -2494,6 +2580,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
(aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
|
(aFlags & DISPLAY_CHILD_FORCE_STACKING_CONTEXT)) {
|
||||||
// If you change this, also change IsPseudoStackingContextFromStyle()
|
// If you change this, also change IsPseudoStackingContextFromStyle()
|
||||||
pseudoStackingContext = true;
|
pseudoStackingContext = true;
|
||||||
|
awayFromCommonPath = true;
|
||||||
}
|
}
|
||||||
NS_ASSERTION(!isStackingContext || pseudoStackingContext,
|
NS_ASSERTION(!isStackingContext || pseudoStackingContext,
|
||||||
"Stacking contexts must also be pseudo-stacking-contexts");
|
"Stacking contexts must also be pseudo-stacking-contexts");
|
||||||
|
@ -2506,8 +2593,31 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
if (savedOutOfFlowData) {
|
if (savedOutOfFlowData) {
|
||||||
clipState.SetClipForContainingBlockDescendants(
|
clipState.SetClipForContainingBlockDescendants(
|
||||||
&savedOutOfFlowData->mContainingBlockClip);
|
&savedOutOfFlowData->mContainingBlockClip);
|
||||||
|
MOZ_ASSERT(awayFromCommonPath, "It is impossible when savedOutOfFlowData is true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if(0)
|
||||||
|
// XXX: there are some backbugs from bug 1342009 that should go here.
|
||||||
|
// These appear to be based on bug 1231538 and bug 1265237, so we
|
||||||
|
// probably don't need them since we don't have that particular regression.
|
||||||
|
|
||||||
|
else if (GetStateBits() & NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO &&
|
||||||
|
isPlaceholder) {
|
||||||
|
NS_ASSERTION(dirty.IsEmpty(), "should have empty dirty rect");
|
||||||
|
// Every item we build from now until we descent into an out of flow that
|
||||||
|
// does have saved out of flow data should be invisible. This state gets
|
||||||
|
// restored when AutoBuildingDisplayList gets out of scope.
|
||||||
|
aBuilder->SetBuildingInvisibleItems(true);
|
||||||
|
|
||||||
|
// If we have nested out-of-flow frames and the outer one isn't visible
|
||||||
|
// then we won't have stored clip data for it. We can just clear the clip
|
||||||
|
// instead since we know we won't render anything, and the inner out-of-flow
|
||||||
|
// frame will setup the correct clip for itself.
|
||||||
|
clipState.SetClipChainForContainingBlockDescendants(nullptr);
|
||||||
|
awayFromCommonPath = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Setup clipping for the parent's overflow:-moz-hidden-unscrollable,
|
// Setup clipping for the parent's overflow:-moz-hidden-unscrollable,
|
||||||
// or overflow:hidden on elements that don't support scrolling (and therefore
|
// or overflow:hidden on elements that don't support scrolling (and therefore
|
||||||
// don't create nsHTML/XULScrollFrame). This clipping needs to not clip
|
// don't create nsHTML/XULScrollFrame). This clipping needs to not clip
|
||||||
|
@ -2519,7 +2629,9 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
nsIFrame* parent = child->GetParent();
|
nsIFrame* parent = child->GetParent();
|
||||||
const nsStyleDisplay* parentDisp =
|
const nsStyleDisplay* parentDisp =
|
||||||
parent == this ? ourDisp : parent->StyleDisplay();
|
parent == this ? ourDisp : parent->StyleDisplay();
|
||||||
ApplyOverflowClipping(aBuilder, parent, parentDisp, clipState);
|
if (ApplyOverflowClipping(aBuilder, parent, parentDisp, clipState)) {
|
||||||
|
awayFromCommonPath = true;
|
||||||
|
}
|
||||||
|
|
||||||
nsDisplayList list;
|
nsDisplayList list;
|
||||||
nsDisplayList extraPositionedDescendants;
|
nsDisplayList extraPositionedDescendants;
|
||||||
|
@ -2538,26 +2650,43 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
|
||||||
// clipRect is in builder-reference-frame coordinates,
|
// clipRect is in builder-reference-frame coordinates,
|
||||||
// dirty/clippedDirtyRect are in child coordinates
|
// dirty/clippedDirtyRect are in child coordinates
|
||||||
dirty.IntersectRect(dirty, clipRect);
|
dirty.IntersectRect(dirty, clipRect);
|
||||||
|
awayFromCommonPath = true; // XXX bug 1342009
|
||||||
}
|
}
|
||||||
|
|
||||||
child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty);
|
child->MarkAbsoluteFramesForDisplayList(aBuilder, dirty);
|
||||||
|
|
||||||
// moved here from below
|
// moved here from below (bug 1220466)
|
||||||
if (aBuilder->IsBuildingLayerEventRegions()) {
|
if (aBuilder->IsBuildingLayerEventRegions()) {
|
||||||
// If this frame has a different animated geometry root than its parent,
|
// If this frame has a different animated geometry root than its parent,
|
||||||
// make sure we accumulate event regions for its layer.
|
// make sure we accumulate event regions for its layer.
|
||||||
if (buildingForChild.IsAnimatedGeometryRoot()) {
|
if (buildingForChild.IsAnimatedGeometryRoot() || isPositioned) {
|
||||||
nsDisplayLayerEventRegions* eventRegions =
|
nsDisplayLayerEventRegions* eventRegions =
|
||||||
new (aBuilder) nsDisplayLayerEventRegions(aBuilder, child);
|
new (aBuilder) nsDisplayLayerEventRegions(aBuilder, child);
|
||||||
eventRegions->AddFrame(aBuilder, child);
|
eventRegions->AddFrame(aBuilder, child);
|
||||||
aBuilder->SetLayerEventRegions(eventRegions);
|
aBuilder->SetLayerEventRegions(eventRegions);
|
||||||
aLists.BorderBackground()->AppendNewToTop(eventRegions);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nsDisplayLayerEventRegions* eventRegions = aBuilder->GetLayerEventRegions();
|
// various backbugs from 1342009 follow, including 1303408 and
|
||||||
if (eventRegions) {
|
// 1287142:
|
||||||
eventRegions->AddFrame(aBuilder, child);
|
|
||||||
|
if (isPositioned) {
|
||||||
|
// We need this nsDisplayLayerEventRegions to be sorted with the positioned
|
||||||
|
// elements as positioned elements will be sorted on top of normal elements
|
||||||
|
list.AppendNewToTop(eventRegions);
|
||||||
|
} else {
|
||||||
|
aLists.BorderBackground()->AppendNewToTop(eventRegions);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
nsDisplayLayerEventRegions* eventRegions = aBuilder->GetLayerEventRegions();
|
||||||
|
if (eventRegions) {
|
||||||
|
eventRegions->AddFrame(aBuilder, child);
|
||||||
|
}
|
||||||
|
if (!awayFromCommonPath &&
|
||||||
|
aBuilder->IsPaintingToWindow() &&
|
||||||
|
!buildingForChild.MaybeAnimatedGeometryRoot()) {
|
||||||
|
// The shortcut is available for the child for next time.
|
||||||
|
child->AddStateBits(NS_FRAME_SIMPLE_DISPLAYLIST);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!pseudoStackingContext) {
|
if (!pseudoStackingContext) {
|
||||||
|
|
|
@ -254,6 +254,14 @@ FRAME_STATE_BIT(Generic, 53, NS_FRAME_IS_NONDISPLAY)
|
||||||
// Frame has a LayerActivityProperty property
|
// Frame has a LayerActivityProperty property
|
||||||
FRAME_STATE_BIT(Generic, 54, NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)
|
FRAME_STATE_BIT(Generic, 54, NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)
|
||||||
|
|
||||||
|
// The display list of the frame can be handled by the shortcut for
|
||||||
|
// COMMON CASE. This is bug 1342009, but it uses bit 57. Since we might
|
||||||
|
// implement NS_FRAME_HAS_PROPERTIES (56) in the near future, we will use bit
|
||||||
|
// 55. XXX: Dump bit 57 and make it all work out -- we'd need the backout
|
||||||
|
// bits from bug 1250244 and then just not implement the replacement API.
|
||||||
|
// However, that's only worth doing if we're really short on bits later.
|
||||||
|
FRAME_STATE_BIT(Generic, 55, NS_FRAME_SIMPLE_DISPLAYLIST)
|
||||||
|
|
||||||
// Frame has VR content, and needs VR display items created
|
// Frame has VR content, and needs VR display items created
|
||||||
FRAME_STATE_BIT(Generic, 57, NS_FRAME_HAS_VR_CONTENT)
|
FRAME_STATE_BIT(Generic, 57, NS_FRAME_HAS_VR_CONTENT)
|
||||||
|
|
||||||
|
|
|
@ -395,6 +395,49 @@ PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash)
|
||||||
// if Reason==ForAdd.)
|
// if Reason==ForAdd.)
|
||||||
PLDHashEntryHdr* firstRemoved = nullptr;
|
PLDHashEntryHdr* firstRemoved = nullptr;
|
||||||
|
|
||||||
|
#if(1)
|
||||||
|
// Speed up table searches a la bug 1352888, but we go one further by having
|
||||||
|
// separate for(;;) loops for ForAdd and everything else, which hoists the
|
||||||
|
// check up and eliminates up to several branches in the loop.
|
||||||
|
|
||||||
|
if (Reason == ForAdd) {
|
||||||
|
for (;;) {
|
||||||
|
if (!firstRemoved) {
|
||||||
|
if (MOZ_UNLIKELY(EntryIsRemoved(entry))) {
|
||||||
|
firstRemoved = entry;
|
||||||
|
} else {
|
||||||
|
entry->mKeyHash |= kCollisionFlag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hash1 -= hash2;
|
||||||
|
hash1 &= sizeMask;
|
||||||
|
|
||||||
|
entry = AddressEntry(hash1);
|
||||||
|
if (EntryIsFree(entry)) {
|
||||||
|
return (firstRemoved ? firstRemoved : entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MatchEntryKeyhash(entry, aKeyHash) &&
|
||||||
|
matchEntry(this, entry, aKey)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else for (;;) {
|
||||||
|
hash1 -= hash2;
|
||||||
|
hash1 &= sizeMask;
|
||||||
|
|
||||||
|
entry = AddressEntry(hash1);
|
||||||
|
if (EntryIsFree(entry)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MatchEntryKeyhash(entry, aKeyHash) &&
|
||||||
|
matchEntry(this, entry, aKey)) {
|
||||||
|
return entry;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (Reason == ForAdd) {
|
if (Reason == ForAdd) {
|
||||||
if (MOZ_UNLIKELY(EntryIsRemoved(entry))) {
|
if (MOZ_UNLIKELY(EntryIsRemoved(entry))) {
|
||||||
|
@ -420,6 +463,7 @@ PLDHashTable::SearchTable(const void* aKey, PLDHashNumber aKeyHash)
|
||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// NOTREACHED
|
// NOTREACHED
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user