forked from mirrors/gecko-dev
Bug 1815552 - Make positioned table parts deal correctly with switching position without being reframed. r=TYLin,layout-reviewers
While looking at the backout, I noticed table parts relied on reframing on abspos-container-ness changes in a subtle way, see the test, which fails with the first patch of this bug applied without these changes. Make the NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN mean the same for table parts as for everything else. Instead, keep the registration status on each relevant frame class individually. Depends on D169127 Differential Revision: https://phabricator.services.mozilla.com/D170969
This commit is contained in:
parent
b953328172
commit
e18c9b7ad6
18 changed files with 198 additions and 167 deletions
|
|
@ -2080,11 +2080,10 @@ nsIFrame* nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
|
||||||
|
|
||||||
// Process children
|
// Process children
|
||||||
nsFrameConstructorSaveState absoluteSaveState;
|
nsFrameConstructorSaveState absoluteSaveState;
|
||||||
const nsStyleDisplay* display = outerComputedStyle->StyleDisplay();
|
|
||||||
|
|
||||||
// Mark the table frame as an absolute container if needed
|
// Mark the table frame as an absolute container if needed
|
||||||
newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
newFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
||||||
if (display->IsAbsPosContainingBlock(newFrame)) {
|
if (newFrame->IsAbsPosContainingBlock()) {
|
||||||
aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
|
aState.PushAbsoluteContainingBlock(newFrame, newFrame, absoluteSaveState);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2117,21 +2116,14 @@ nsIFrame* nsCSSFrameConstructor::ConstructTable(nsFrameConstructorState& aState,
|
||||||
return newFrame;
|
return newFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void MakeTablePartAbsoluteContainingBlockIfNeeded(
|
static void MakeTablePartAbsoluteContainingBlock(
|
||||||
nsFrameConstructorState& aState, const nsStyleDisplay* aDisplay,
|
nsFrameConstructorState& aState, nsFrameConstructorSaveState& aAbsSaveState,
|
||||||
nsFrameConstructorSaveState& aAbsSaveState, nsContainerFrame* aFrame) {
|
nsContainerFrame* aFrame) {
|
||||||
// If we're positioned, then we need to become an absolute containing block
|
// If we're positioned, then we need to become an absolute containing block
|
||||||
// for any absolutely positioned children and register for post-reflow fixup.
|
// for any absolutely positioned children.
|
||||||
//
|
aFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
||||||
// Note that usually if a frame type can be an absolute containing block, we
|
if (aFrame->IsAbsPosContainingBlock()) {
|
||||||
// always set NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN, whether it actually is or
|
|
||||||
// not. However, in this case flag serves the additional purpose of indicating
|
|
||||||
// that the frame was registered with its table frame. This allows us to avoid
|
|
||||||
// the overhead of unregistering the frame in most cases.
|
|
||||||
if (aDisplay->IsAbsPosContainingBlock(aFrame)) {
|
|
||||||
aFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
|
||||||
aState.PushAbsoluteContainingBlock(aFrame, aFrame, aAbsSaveState);
|
aState.PushAbsoluteContainingBlock(aFrame, aFrame, aAbsSaveState);
|
||||||
nsTableFrame::RegisterPositionedTablePart(aFrame);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2162,8 +2154,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructTableRowOrRowGroup(
|
||||||
InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
|
InitAndRestoreFrame(aState, content, aParentFrame, newFrame);
|
||||||
|
|
||||||
nsFrameConstructorSaveState absoluteSaveState;
|
nsFrameConstructorSaveState absoluteSaveState;
|
||||||
MakeTablePartAbsoluteContainingBlockIfNeeded(aState, aDisplay,
|
MakeTablePartAbsoluteContainingBlock(aState, absoluteSaveState, newFrame);
|
||||||
absoluteSaveState, newFrame);
|
|
||||||
|
|
||||||
nsFrameConstructorSaveState floatSaveState;
|
nsFrameConstructorSaveState floatSaveState;
|
||||||
aState.MaybePushFloatContainingBlock(newFrame, floatSaveState);
|
aState.MaybePushFloatContainingBlock(newFrame, floatSaveState);
|
||||||
|
|
@ -2262,8 +2253,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructTableCell(
|
||||||
InitAndRestoreFrame(aState, content, newFrame, cellInnerFrame);
|
InitAndRestoreFrame(aState, content, newFrame, cellInnerFrame);
|
||||||
|
|
||||||
nsFrameConstructorSaveState absoluteSaveState;
|
nsFrameConstructorSaveState absoluteSaveState;
|
||||||
MakeTablePartAbsoluteContainingBlockIfNeeded(aState, aDisplay,
|
MakeTablePartAbsoluteContainingBlock(aState, absoluteSaveState, newFrame);
|
||||||
absoluteSaveState, newFrame);
|
|
||||||
|
|
||||||
nsFrameConstructorSaveState floatSaveState;
|
nsFrameConstructorSaveState floatSaveState;
|
||||||
aState.MaybePushFloatContainingBlock(cellInnerFrame, floatSaveState);
|
aState.MaybePushFloatContainingBlock(cellInnerFrame, floatSaveState);
|
||||||
|
|
@ -2519,7 +2509,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
|
||||||
processChildren = true;
|
processChildren = true;
|
||||||
|
|
||||||
contentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
contentFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
||||||
if (display->IsAbsPosContainingBlock(contentFrame)) {
|
if (contentFrame->IsAbsPosContainingBlock()) {
|
||||||
state.PushAbsoluteContainingBlock(contentFrame, contentFrame,
|
state.PushAbsoluteContainingBlock(contentFrame, contentFrame,
|
||||||
absoluteSaveState);
|
absoluteSaveState);
|
||||||
}
|
}
|
||||||
|
|
@ -2556,8 +2546,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructDocElementFrame(
|
||||||
state, aDocElement,
|
state, aDocElement,
|
||||||
state.GetGeometricParent(*display, mDocElementContainingBlock),
|
state.GetGeometricParent(*display, mDocElementContainingBlock),
|
||||||
mDocElementContainingBlock, computedStyle, &contentFrame, frameList,
|
mDocElementContainingBlock, computedStyle, &contentFrame, frameList,
|
||||||
display->IsAbsPosContainingBlock(contentFrame) ? contentFrame
|
contentFrame->IsAbsPosContainingBlock() ? contentFrame : nullptr);
|
||||||
: nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MOZ_ASSERT(frameList.FirstChild());
|
MOZ_ASSERT(frameList.FirstChild());
|
||||||
|
|
@ -3306,7 +3295,7 @@ nsIFrame* nsCSSFrameConstructor::ConstructBlockRubyFrame(
|
||||||
|
|
||||||
nsFrameConstructorSaveState absoluteSaveState;
|
nsFrameConstructorSaveState absoluteSaveState;
|
||||||
blockFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
blockFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
||||||
if (aStyleDisplay->IsAbsPosContainingBlock(newFrame)) {
|
if (newFrame->IsAbsPosContainingBlock()) {
|
||||||
aState.PushAbsoluteContainingBlock(blockFrame, blockFrame,
|
aState.PushAbsoluteContainingBlock(blockFrame, blockFrame,
|
||||||
absoluteSaveState);
|
absoluteSaveState);
|
||||||
}
|
}
|
||||||
|
|
@ -3839,8 +3828,7 @@ void nsCSSFrameConstructor::ConstructFrameFromItemInternal(
|
||||||
|
|
||||||
// Now figure out whether newFrame or outerFrame should be the
|
// Now figure out whether newFrame or outerFrame should be the
|
||||||
// absolute container.
|
// absolute container.
|
||||||
auto outerDisplay = outerStyle->StyleDisplay();
|
if (outerFrame->IsAbsPosContainingBlock()) {
|
||||||
if (outerDisplay->IsAbsPosContainingBlock(outerFrame)) {
|
|
||||||
maybeAbsoluteContainingBlock = outerFrame;
|
maybeAbsoluteContainingBlock = outerFrame;
|
||||||
maybeAbsoluteContainingBlockStyleFrame = outerFrame;
|
maybeAbsoluteContainingBlockStyleFrame = outerFrame;
|
||||||
innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
innerFrame->AddStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN);
|
||||||
|
|
@ -4582,10 +4570,9 @@ nsIFrame* nsCSSFrameConstructor::ConstructScrollableBlock(
|
||||||
aState.AddChild(newFrame, aFrameList, content, aParentFrame);
|
aState.AddChild(newFrame, aFrameList, content, aParentFrame);
|
||||||
|
|
||||||
nsFrameList blockList;
|
nsFrameList blockList;
|
||||||
ConstructBlock(
|
ConstructBlock(aState, content, newFrame, newFrame, scrolledContentStyle,
|
||||||
aState, content, newFrame, newFrame, scrolledContentStyle, &scrolledFrame,
|
&scrolledFrame, blockList,
|
||||||
blockList,
|
newFrame->IsAbsPosContainingBlock() ? newFrame : nullptr);
|
||||||
aDisplay->IsAbsPosContainingBlock(newFrame) ? newFrame : nullptr);
|
|
||||||
|
|
||||||
MOZ_ASSERT(blockList.OnlyChild() == scrolledFrame,
|
MOZ_ASSERT(blockList.OnlyChild() == scrolledFrame,
|
||||||
"Scrollframe's frameList should be exactly the scrolled frame!");
|
"Scrollframe's frameList should be exactly the scrolled frame!");
|
||||||
|
|
@ -4619,11 +4606,10 @@ nsIFrame* nsCSSFrameConstructor::ConstructNonScrollableBlock(
|
||||||
|
|
||||||
nsContainerFrame* newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
|
nsContainerFrame* newFrame = NS_NewBlockFrame(mPresShell, computedStyle);
|
||||||
newFrame->AddStateBits(flags);
|
newFrame->AddStateBits(flags);
|
||||||
ConstructBlock(
|
ConstructBlock(aState, aItem.mContent,
|
||||||
aState, aItem.mContent,
|
aState.GetGeometricParent(*aDisplay, aParentFrame),
|
||||||
aState.GetGeometricParent(*aDisplay, aParentFrame), aParentFrame,
|
aParentFrame, computedStyle, &newFrame, aFrameList,
|
||||||
computedStyle, &newFrame, aFrameList,
|
newFrame->IsAbsPosContainingBlock() ? newFrame : nullptr);
|
||||||
aDisplay->IsAbsPosContainingBlock(newFrame) ? newFrame : nullptr);
|
|
||||||
return newFrame;
|
return newFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7894,9 +7880,8 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingTableFrame(
|
||||||
headerFooterFrame->Init(headerFooter, newFrame, nullptr);
|
headerFooterFrame->Init(headerFooter, newFrame, nullptr);
|
||||||
|
|
||||||
nsFrameConstructorSaveState absoluteSaveState;
|
nsFrameConstructorSaveState absoluteSaveState;
|
||||||
MakeTablePartAbsoluteContainingBlockIfNeeded(
|
MakeTablePartAbsoluteContainingBlock(state, absoluteSaveState,
|
||||||
state, headerFooterComputedStyle->StyleDisplay(), absoluteSaveState,
|
headerFooterFrame);
|
||||||
headerFooterFrame);
|
|
||||||
|
|
||||||
nsFrameConstructorSaveState floatSaveState;
|
nsFrameConstructorSaveState floatSaveState;
|
||||||
state.MaybePushFloatContainingBlock(headerFooterFrame, floatSaveState);
|
state.MaybePushFloatContainingBlock(headerFooterFrame, floatSaveState);
|
||||||
|
|
@ -7969,16 +7954,10 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
|
||||||
} else if (LayoutFrameType::TableRowGroup == frameType) {
|
} else if (LayoutFrameType::TableRowGroup == frameType) {
|
||||||
newFrame = NS_NewTableRowGroupFrame(mPresShell, computedStyle);
|
newFrame = NS_NewTableRowGroupFrame(mPresShell, computedStyle);
|
||||||
newFrame->Init(content, aParentFrame, aFrame);
|
newFrame->Init(content, aParentFrame, aFrame);
|
||||||
if (newFrame->HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
|
|
||||||
nsTableFrame::RegisterPositionedTablePart(newFrame);
|
|
||||||
}
|
|
||||||
} else if (LayoutFrameType::TableRow == frameType) {
|
} else if (LayoutFrameType::TableRow == frameType) {
|
||||||
nsTableRowFrame* rowFrame = NS_NewTableRowFrame(mPresShell, computedStyle);
|
nsTableRowFrame* rowFrame = NS_NewTableRowFrame(mPresShell, computedStyle);
|
||||||
|
|
||||||
rowFrame->Init(content, aParentFrame, aFrame);
|
rowFrame->Init(content, aParentFrame, aFrame);
|
||||||
if (rowFrame->HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
|
|
||||||
nsTableFrame::RegisterPositionedTablePart(rowFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a continuing frame for each table cell frame
|
// Create a continuing frame for each table cell frame
|
||||||
nsFrameList newChildList;
|
nsFrameList newChildList;
|
||||||
|
|
@ -8007,9 +7986,6 @@ nsIFrame* nsCSSFrameConstructor::CreateContinuingFrame(
|
||||||
NS_NewTableCellFrame(mPresShell, computedStyle, tableFrame);
|
NS_NewTableCellFrame(mPresShell, computedStyle, tableFrame);
|
||||||
|
|
||||||
cellFrame->Init(content, aParentFrame, aFrame);
|
cellFrame->Init(content, aParentFrame, aFrame);
|
||||||
if (cellFrame->HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
|
|
||||||
nsTableFrame::RegisterPositionedTablePart(cellFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a continuing area frame
|
// Create a continuing area frame
|
||||||
nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
|
nsIFrame* blockFrame = aFrame->PrincipalChildList().FirstChild();
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,6 @@
|
||||||
#include "nsStyleStruct.h"
|
#include "nsStyleStruct.h"
|
||||||
#include "Visibility.h"
|
#include "Visibility.h"
|
||||||
#include "nsChangeHint.h"
|
#include "nsChangeHint.h"
|
||||||
#include "mozilla/ComputedStyleInlines.h"
|
|
||||||
#include "mozilla/EnumSet.h"
|
#include "mozilla/EnumSet.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
#include "mozilla/gfx/CompositorHitTestInfo.h"
|
#include "mozilla/gfx/CompositorHitTestInfo.h"
|
||||||
|
|
|
||||||
|
|
@ -8,10 +8,10 @@
|
||||||
#define nsIFrameInlines_h___
|
#define nsIFrameInlines_h___
|
||||||
|
|
||||||
#include "mozilla/dom/ElementInlines.h"
|
#include "mozilla/dom/ElementInlines.h"
|
||||||
|
#include "mozilla/ComputedStyleInlines.h"
|
||||||
#include "nsContainerFrame.h"
|
#include "nsContainerFrame.h"
|
||||||
#include "nsLayoutUtils.h"
|
#include "nsLayoutUtils.h"
|
||||||
#include "nsPlaceholderFrame.h"
|
#include "nsPlaceholderFrame.h"
|
||||||
#include "nsStyleStructInlines.h"
|
|
||||||
#include "nsCSSAnonBoxes.h"
|
#include "nsCSSAnonBoxes.h"
|
||||||
#include "nsFrameManager.h"
|
#include "nsFrameManager.h"
|
||||||
|
|
||||||
|
|
@ -53,11 +53,11 @@ bool nsIFrame::IsFloating() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsIFrame::IsAbsPosContainingBlock() const {
|
bool nsIFrame::IsAbsPosContainingBlock() const {
|
||||||
return StyleDisplay()->IsAbsPosContainingBlock(this);
|
return Style()->IsAbsPosContainingBlock(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsIFrame::IsFixedPosContainingBlock() const {
|
bool nsIFrame::IsFixedPosContainingBlock() const {
|
||||||
return StyleDisplay()->IsFixedPosContainingBlock(this);
|
return Style()->IsFixedPosContainingBlock(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsIFrame::IsRelativelyOrStickyPositioned() const {
|
bool nsIFrame::IsRelativelyOrStickyPositioned() const {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "nsSubDocumentFrame.h"
|
#include "nsSubDocumentFrame.h"
|
||||||
|
|
||||||
|
#include "mozilla/ComputedStyleInlines.h"
|
||||||
#include "mozilla/Preferences.h"
|
#include "mozilla/Preferences.h"
|
||||||
#include "mozilla/PresShell.h"
|
#include "mozilla/PresShell.h"
|
||||||
#include "mozilla/StaticPrefs_layout.h"
|
#include "mozilla/StaticPrefs_layout.h"
|
||||||
|
|
|
||||||
|
|
@ -52,17 +52,18 @@ ComputedStyle::ComputedStyle(PseudoStyleType aPseudoType,
|
||||||
// whether we establish a containing block has really changed.
|
// whether we establish a containing block has really changed.
|
||||||
static bool ContainingBlockMayHaveChanged(const ComputedStyle& aOldStyle,
|
static bool ContainingBlockMayHaveChanged(const ComputedStyle& aOldStyle,
|
||||||
const ComputedStyle& aNewStyle) {
|
const ComputedStyle& aNewStyle) {
|
||||||
auto* oldDisp = aOldStyle.StyleDisplay();
|
const auto& oldDisp = *aOldStyle.StyleDisplay();
|
||||||
auto* newDisp = aNewStyle.StyleDisplay();
|
const auto& newDisp = *aNewStyle.StyleDisplay();
|
||||||
|
|
||||||
if (oldDisp->IsPositionedStyle() != newDisp->IsPositionedStyle()) {
|
if (oldDisp.IsPositionedStyle() != newDisp.IsPositionedStyle()) {
|
||||||
|
// XXX This check can probably be moved to after the fixedCB check, since
|
||||||
|
// IsPositionedStyle() is also only relevant for non-svg text frame
|
||||||
|
// subtrees.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fixedCB =
|
const bool fixedCB = aOldStyle.IsFixedPosContainingBlockForNonSVGTextFrames();
|
||||||
oldDisp->IsFixedPosContainingBlockForNonSVGTextFrames(aOldStyle);
|
if (fixedCB != aNewStyle.IsFixedPosContainingBlockForNonSVGTextFrames()) {
|
||||||
if (fixedCB !=
|
|
||||||
newDisp->IsFixedPosContainingBlockForNonSVGTextFrames(aNewStyle)) {
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
// If we were both before and after a fixed-pos containing-block that means
|
// If we were both before and after a fixed-pos containing-block that means
|
||||||
|
|
@ -71,20 +72,21 @@ static bool ContainingBlockMayHaveChanged(const ComputedStyle& aOldStyle,
|
||||||
if (fixedCB) {
|
if (fixedCB) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Note that neither of these two following sets of frames
|
// Note that neither of these two following sets of frames
|
||||||
// (transform-supporting and layout-and-paint-supporting frames) is a subset
|
// (transform-supporting and layout-and-paint-supporting frames) is a subset
|
||||||
// of the other, because table frames support contain: layout/paint but not
|
// of the other, because table frames support contain: layout/paint but not
|
||||||
// transforms (which are instead inherited to the table wrapper), and quite a
|
// transforms (which are instead inherited to the table wrapper), and quite a
|
||||||
// few frame types support transforms but not contain: layout/paint (e.g.,
|
// few frame types support transforms but not contain: layout/paint (e.g.,
|
||||||
// table rows and row groups, many SVG frames).
|
// table rows and row groups, many SVG frames).
|
||||||
if (oldDisp->IsFixedPosContainingBlockForTransformSupportingFrames() !=
|
if (oldDisp.IsFixedPosContainingBlockForTransformSupportingFrames() !=
|
||||||
newDisp->IsFixedPosContainingBlockForTransformSupportingFrames()) {
|
newDisp.IsFixedPosContainingBlockForTransformSupportingFrames()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (oldDisp
|
if (oldDisp
|
||||||
->IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() !=
|
.IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() !=
|
||||||
newDisp
|
newDisp
|
||||||
->IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames()) {
|
.IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
||||||
|
|
@ -229,6 +229,32 @@ class ComputedStyle {
|
||||||
inline mozilla::StylePointerEvents PointerEvents() const;
|
inline mozilla::StylePointerEvents PointerEvents() const;
|
||||||
inline mozilla::StyleUserSelect UserSelect() const;
|
inline mozilla::StyleUserSelect UserSelect() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the element is a containing block for its absolutely
|
||||||
|
* positioned descendants.
|
||||||
|
* aContextFrame is the frame for which this is the style (or an old style).
|
||||||
|
*/
|
||||||
|
inline bool IsAbsPosContainingBlock(const nsIFrame*) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true when the element is a containing block for its fixed-pos
|
||||||
|
* descendants.
|
||||||
|
* aContextFrame is the frame for which this is the style (or an old style).
|
||||||
|
*/
|
||||||
|
inline bool IsFixedPosContainingBlock(const nsIFrame*) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for only the sub-parts of IsFixedPosContainingBlock that apply to:
|
||||||
|
* - nearly all frames, except those that are in SVG text subtrees.
|
||||||
|
* - frames that support CSS contain:layout and contain:paint and are not
|
||||||
|
* in SVG text subtrees.
|
||||||
|
* - frames that support CSS transforms and are not in SVG text subtrees.
|
||||||
|
*
|
||||||
|
* This should be used only when the caller has the style but not the
|
||||||
|
* frame (i.e., when calculating style changes).
|
||||||
|
*/
|
||||||
|
inline bool IsFixedPosContainingBlockForNonSVGTextFrames() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the style changes needed during restyling when this style
|
* Compute the style changes needed during restyling when this style
|
||||||
* context is being replaced by aNewContext. (This is nonsymmetric since
|
* context is being replaced by aNewContext. (This is nonsymmetric since
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
#include "MainThreadUtils.h"
|
#include "MainThreadUtils.h"
|
||||||
#include "mozilla/Assertions.h"
|
#include "mozilla/Assertions.h"
|
||||||
#include "mozilla/Unused.h"
|
#include "mozilla/Unused.h"
|
||||||
#include "nsStyleStruct.h"
|
#include "nsStyleStructInlines.h"
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
|
@ -68,6 +68,55 @@ StyleUserSelect ComputedStyle::UserSelect() const {
|
||||||
: StyleUIReset()->ComputedUserSelect();
|
: StyleUIReset()->ComputedUserSelect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ComputedStyle::IsFixedPosContainingBlockForNonSVGTextFrames() const {
|
||||||
|
// NOTE: Any CSS properties that influence the output of this function
|
||||||
|
// should return FIXPOS_CB_NON_SVG for will-change.
|
||||||
|
if (IsRootElementStyle()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& disp = *StyleDisplay();
|
||||||
|
if (disp.mWillChange.bits & mozilla::StyleWillChangeBits::FIXPOS_CB_NON_SVG) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& effects = *StyleEffects();
|
||||||
|
return effects.HasFilters() || effects.HasBackdropFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputedStyle::IsFixedPosContainingBlock(
|
||||||
|
const nsIFrame* aContextFrame) const {
|
||||||
|
// NOTE: Any CSS properties that influence the output of this function
|
||||||
|
// should also handle will-change appropriately.
|
||||||
|
if (mozilla::SVGUtils::IsInSVGTextSubtree(aContextFrame)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (IsFixedPosContainingBlockForNonSVGTextFrames()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const auto& disp = *StyleDisplay();
|
||||||
|
if (disp.IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() &&
|
||||||
|
aContextFrame->IsFrameOfType(nsIFrame::eSupportsContainLayoutAndPaint)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (disp.IsFixedPosContainingBlockForTransformSupportingFrames() &&
|
||||||
|
aContextFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ComputedStyle::IsAbsPosContainingBlock(
|
||||||
|
const nsIFrame* aContextFrame) const {
|
||||||
|
if (IsFixedPosContainingBlock(aContextFrame)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// NOTE: Any CSS properties that influence the output of this function
|
||||||
|
// should also handle will-change appropriately.
|
||||||
|
return StyleDisplay()->IsPositionedStyle() &&
|
||||||
|
!mozilla::SVGUtils::IsInSVGTextSubtree(aContextFrame);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace mozilla
|
} // namespace mozilla
|
||||||
|
|
||||||
#endif // ComputedStyleInlines_h
|
#endif // ComputedStyleInlines_h
|
||||||
|
|
|
||||||
|
|
@ -1730,33 +1730,6 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleDisplay {
|
||||||
*/
|
*/
|
||||||
inline bool HasPerspective(const nsIFrame* aContextFrame) const;
|
inline bool HasPerspective(const nsIFrame* aContextFrame) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the element is a containing block for its
|
|
||||||
* absolutely positioned descendants.
|
|
||||||
* aContextFrame is the frame for which this is the nsStyleDisplay.
|
|
||||||
*/
|
|
||||||
inline bool IsAbsPosContainingBlock(const nsIFrame* aContextFrame) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true when the element is a containing block for its fixed-pos
|
|
||||||
* descendants.
|
|
||||||
* aContextFrame is the frame for which this is the nsStyleDisplay.
|
|
||||||
*/
|
|
||||||
inline bool IsFixedPosContainingBlock(const nsIFrame* aContextFrame) const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Tests for only the sub-parts of IsFixedPosContainingBlock that apply
|
|
||||||
* to:
|
|
||||||
* - nearly all frames, except those that are SVG text frames.
|
|
||||||
* - frames that support CSS contain:layout and contain:paint and are not
|
|
||||||
* SVG text frames.
|
|
||||||
* - frames that support CSS transforms and are not SVG text frames.
|
|
||||||
*
|
|
||||||
* This should be used only when the caller has the style but not the
|
|
||||||
* frame (i.e., when calculating style changes).
|
|
||||||
*/
|
|
||||||
inline bool IsFixedPosContainingBlockForNonSVGTextFrames(
|
|
||||||
const mozilla::ComputedStyle&) const;
|
|
||||||
inline bool
|
inline bool
|
||||||
IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() const;
|
IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() const;
|
||||||
inline bool IsFixedPosContainingBlockForTransformSupportingFrames() const;
|
inline bool IsFixedPosContainingBlockForTransformSupportingFrames() const;
|
||||||
|
|
|
||||||
|
|
@ -91,24 +91,6 @@ bool nsStyleDisplay::HasPerspective(const nsIFrame* aContextFrame) const {
|
||||||
aContextFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms);
|
aContextFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsStyleDisplay::IsFixedPosContainingBlockForNonSVGTextFrames(
|
|
||||||
const mozilla::ComputedStyle& aStyle) const {
|
|
||||||
// NOTE: Any CSS properties that influence the output of this function
|
|
||||||
// should return FIXPOS_CB_NON_SVG for will-change.
|
|
||||||
NS_ASSERTION(aStyle.StyleDisplay() == this, "unexpected aStyle");
|
|
||||||
|
|
||||||
if (aStyle.IsRootElementStyle()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mWillChange.bits & mozilla::StyleWillChangeBits::FIXPOS_CB_NON_SVG) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return aStyle.StyleEffects()->HasFilters() ||
|
|
||||||
aStyle.StyleEffects()->HasBackdropFilters();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nsStyleDisplay::
|
bool nsStyleDisplay::
|
||||||
IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() const {
|
IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() const {
|
||||||
return IsContainPaint() || IsContainLayout() ||
|
return IsContainPaint() || IsContainLayout() ||
|
||||||
|
|
@ -123,42 +105,6 @@ bool nsStyleDisplay::IsFixedPosContainingBlockForTransformSupportingFrames()
|
||||||
mWillChange.bits & mozilla::StyleWillChangeBits::PERSPECTIVE;
|
mWillChange.bits & mozilla::StyleWillChangeBits::PERSPECTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool nsStyleDisplay::IsFixedPosContainingBlock(
|
|
||||||
const nsIFrame* aContextFrame) const {
|
|
||||||
const auto* style = aContextFrame->Style();
|
|
||||||
NS_ASSERTION(style->StyleDisplay() == this, "unexpected aContextFrame");
|
|
||||||
// NOTE: Any CSS properties that influence the output of this function
|
|
||||||
// should also handle will-change appropriately.
|
|
||||||
if (mozilla::SVGUtils::IsInSVGTextSubtree(aContextFrame)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (IsFixedPosContainingBlockForNonSVGTextFrames(*style)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (IsFixedPosContainingBlockForContainLayoutAndPaintSupportingFrames() &&
|
|
||||||
aContextFrame->IsFrameOfType(nsIFrame::eSupportsContainLayoutAndPaint)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (IsFixedPosContainingBlockForTransformSupportingFrames() &&
|
|
||||||
aContextFrame->IsFrameOfType(nsIFrame::eSupportsCSSTransforms)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nsStyleDisplay::IsAbsPosContainingBlock(
|
|
||||||
const nsIFrame* aContextFrame) const {
|
|
||||||
NS_ASSERTION(aContextFrame->StyleDisplay() == this,
|
|
||||||
"unexpected aContextFrame");
|
|
||||||
if (IsFixedPosContainingBlock(aContextFrame)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
// NOTE: Any CSS properties that influence the output of this function
|
|
||||||
// should also handle will-change appropriately.
|
|
||||||
return IsPositionedStyle() &&
|
|
||||||
!mozilla::SVGUtils::IsInSVGTextSubtree(aContextFrame);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool nsStyleDisplay::IsRelativelyOrStickyPositioned(
|
bool nsStyleDisplay::IsRelativelyOrStickyPositioned(
|
||||||
const nsIFrame* aContextFrame) const {
|
const nsIFrame* aContextFrame) const {
|
||||||
NS_ASSERTION(aContextFrame->StyleDisplay() == this,
|
NS_ASSERTION(aContextFrame->StyleDisplay() == this,
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
#include "gfxContext.h"
|
#include "gfxContext.h"
|
||||||
#include "gfxPlatform.h"
|
#include "gfxPlatform.h"
|
||||||
#include "mozilla/gfx/2D.h"
|
#include "mozilla/gfx/2D.h"
|
||||||
|
#include "mozilla/ComputedStyleInlines.h"
|
||||||
#include "mozilla/image/WebRenderImageProvider.h"
|
#include "mozilla/image/WebRenderImageProvider.h"
|
||||||
#include "mozilla/layers/RenderRootStateManager.h"
|
#include "mozilla/layers/RenderRootStateManager.h"
|
||||||
#include "mozilla/layers/WebRenderLayerManager.h"
|
#include "mozilla/layers/WebRenderLayerManager.h"
|
||||||
|
|
|
||||||
|
|
@ -83,10 +83,7 @@ void nsTableCellFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||||
|
|
||||||
void nsTableCellFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
void nsTableCellFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
||||||
PostDestroyData& aPostDestroyData) {
|
PostDestroyData& aPostDestroyData) {
|
||||||
if (HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
|
nsTableFrame::MaybeUnregisterPositionedTablePart(this, aDestructRoot);
|
||||||
nsTableFrame::UnregisterPositionedTablePart(this, aDestructRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -183,6 +180,7 @@ nsresult nsTableCellFrame::AttributeChanged(int32_t aNameSpaceID,
|
||||||
/* virtual */
|
/* virtual */
|
||||||
void nsTableCellFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
void nsTableCellFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||||
nsContainerFrame::DidSetComputedStyle(aOldComputedStyle);
|
nsContainerFrame::DidSetComputedStyle(aOldComputedStyle);
|
||||||
|
nsTableFrame::PositionedTablePartMaybeChanged(this, aOldComputedStyle);
|
||||||
|
|
||||||
if (!aOldComputedStyle) {
|
if (!aOldComputedStyle) {
|
||||||
return; // avoid the following on init
|
return; // avoid the following on init
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
#include "gfxContext.h"
|
#include "gfxContext.h"
|
||||||
#include "nsCOMPtr.h"
|
#include "nsCOMPtr.h"
|
||||||
#include "mozilla/ComputedStyle.h"
|
#include "mozilla/ComputedStyle.h"
|
||||||
|
#include "nsIFrameInlines.h"
|
||||||
#include "nsFrameList.h"
|
#include "nsFrameList.h"
|
||||||
#include "nsStyleConsts.h"
|
#include "nsStyleConsts.h"
|
||||||
#include "nsIContent.h"
|
#include "nsIContent.h"
|
||||||
|
|
@ -250,7 +251,16 @@ bool nsTableFrame::PageBreakAfter(nsIFrame* aSourceFrame,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void nsTableFrame::RegisterPositionedTablePart(nsIFrame* aFrame) {
|
void nsTableFrame::PositionedTablePartMaybeChanged(nsIFrame* aFrame,
|
||||||
|
ComputedStyle* aOldStyle) {
|
||||||
|
const bool wasPositioned =
|
||||||
|
aOldStyle && aOldStyle->IsAbsPosContainingBlock(aFrame);
|
||||||
|
const bool isPositioned = aFrame->IsAbsPosContainingBlock();
|
||||||
|
MOZ_ASSERT(isPositioned == aFrame->Style()->IsAbsPosContainingBlock(aFrame));
|
||||||
|
if (wasPositioned == isPositioned) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(aFrame);
|
nsTableFrame* tableFrame = nsTableFrame::GetTableFrame(aFrame);
|
||||||
MOZ_ASSERT(tableFrame, "Should have a table frame here");
|
MOZ_ASSERT(tableFrame, "Should have a table frame here");
|
||||||
tableFrame = static_cast<nsTableFrame*>(tableFrame->FirstContinuation());
|
tableFrame = static_cast<nsTableFrame*>(tableFrame->FirstContinuation());
|
||||||
|
|
@ -265,13 +275,20 @@ void nsTableFrame::RegisterPositionedTablePart(nsIFrame* aFrame) {
|
||||||
tableFrame->SetProperty(PositionedTablePartArray(), positionedParts);
|
tableFrame->SetProperty(PositionedTablePartArray(), positionedParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add this frame to the list.
|
if (isPositioned) {
|
||||||
positionedParts->AppendElement(aFrame);
|
// Add this frame to the list.
|
||||||
|
positionedParts->AppendElement(aFrame);
|
||||||
|
} else {
|
||||||
|
positionedParts->RemoveElement(aFrame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */
|
/* static */
|
||||||
void nsTableFrame::UnregisterPositionedTablePart(nsIFrame* aFrame,
|
void nsTableFrame::MaybeUnregisterPositionedTablePart(nsIFrame* aFrame,
|
||||||
nsIFrame* aDestructRoot) {
|
nsIFrame* aDestructRoot) {
|
||||||
|
if (!aFrame->IsAbsPosContainingBlock()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Retrieve the table frame, and check if we hit aDestructRoot on the way.
|
// Retrieve the table frame, and check if we hit aDestructRoot on the way.
|
||||||
bool didPassThrough;
|
bool didPassThrough;
|
||||||
nsTableFrame* tableFrame =
|
nsTableFrame* tableFrame =
|
||||||
|
|
|
||||||
|
|
@ -177,14 +177,18 @@ class nsTableFrame : public nsContainerFrame {
|
||||||
|
|
||||||
static bool PageBreakAfter(nsIFrame* aSourceFrame, nsIFrame* aNextFrame);
|
static bool PageBreakAfter(nsIFrame* aSourceFrame, nsIFrame* aNextFrame);
|
||||||
|
|
||||||
// Register a positioned table part with its nsTableFrame. These objects will
|
// Register or deregister a positioned table part with its nsTableFrame.
|
||||||
// be visited by FixupPositionedTableParts after reflow is complete. (See that
|
// These objects will be visited by FixupPositionedTableParts after reflow is
|
||||||
// function for more explanation.) Should be called during frame construction.
|
// complete. (See that function for more explanation.) Should be called
|
||||||
static void RegisterPositionedTablePart(nsIFrame* aFrame);
|
// during frame construction or style recalculation.
|
||||||
|
//
|
||||||
|
// @return true if the frame is a registered positioned table part.
|
||||||
|
static void PositionedTablePartMaybeChanged(
|
||||||
|
nsIFrame*, mozilla::ComputedStyle* aOldStyle);
|
||||||
|
|
||||||
// Unregister a positioned table part with its nsTableFrame.
|
// Unregister a positioned table part with its nsTableFrame, if needed.
|
||||||
static void UnregisterPositionedTablePart(nsIFrame* aFrame,
|
static void MaybeUnregisterPositionedTablePart(nsIFrame* aFrame,
|
||||||
nsIFrame* aDestructRoot);
|
nsIFrame* aDestructRoot);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Notification that rowspan or colspan has changed for content inside a
|
* Notification that rowspan or colspan has changed for content inside a
|
||||||
|
|
|
||||||
|
|
@ -156,16 +156,14 @@ void nsTableRowFrame::Init(nsIContent* aContent, nsContainerFrame* aParent,
|
||||||
|
|
||||||
void nsTableRowFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
void nsTableRowFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
||||||
PostDestroyData& aPostDestroyData) {
|
PostDestroyData& aPostDestroyData) {
|
||||||
if (HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
|
nsTableFrame::MaybeUnregisterPositionedTablePart(this, aDestructRoot);
|
||||||
nsTableFrame::UnregisterPositionedTablePart(this, aDestructRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */
|
/* virtual */
|
||||||
void nsTableRowFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
void nsTableRowFrame::DidSetComputedStyle(ComputedStyle* aOldComputedStyle) {
|
||||||
nsContainerFrame::DidSetComputedStyle(aOldComputedStyle);
|
nsContainerFrame::DidSetComputedStyle(aOldComputedStyle);
|
||||||
|
nsTableFrame::PositionedTablePartMaybeChanged(this, aOldComputedStyle);
|
||||||
|
|
||||||
if (!aOldComputedStyle) {
|
if (!aOldComputedStyle) {
|
||||||
return; // avoid the following on init
|
return; // avoid the following on init
|
||||||
|
|
|
||||||
|
|
@ -64,10 +64,7 @@ nsTableRowGroupFrame::~nsTableRowGroupFrame() = default;
|
||||||
|
|
||||||
void nsTableRowGroupFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
void nsTableRowGroupFrame::DestroyFrom(nsIFrame* aDestructRoot,
|
||||||
PostDestroyData& aPostDestroyData) {
|
PostDestroyData& aPostDestroyData) {
|
||||||
if (HasAnyStateBits(NS_FRAME_CAN_HAVE_ABSPOS_CHILDREN)) {
|
nsTableFrame::MaybeUnregisterPositionedTablePart(this, aDestructRoot);
|
||||||
nsTableFrame::UnregisterPositionedTablePart(this, aDestructRoot);
|
|
||||||
}
|
|
||||||
|
|
||||||
nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
nsContainerFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1436,6 +1433,7 @@ bool nsTableRowGroupFrame::ComputeCustomOverflow(
|
||||||
void nsTableRowGroupFrame::DidSetComputedStyle(
|
void nsTableRowGroupFrame::DidSetComputedStyle(
|
||||||
ComputedStyle* aOldComputedStyle) {
|
ComputedStyle* aOldComputedStyle) {
|
||||||
nsContainerFrame::DidSetComputedStyle(aOldComputedStyle);
|
nsContainerFrame::DidSetComputedStyle(aOldComputedStyle);
|
||||||
|
nsTableFrame::PositionedTablePartMaybeChanged(this, aOldComputedStyle);
|
||||||
|
|
||||||
if (!aOldComputedStyle) {
|
if (!aOldComputedStyle) {
|
||||||
return; // avoid the following on init
|
return; // avoid the following on init
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "nsTreeStyleCache.h"
|
#include "nsTreeStyleCache.h"
|
||||||
|
#include "mozilla/ComputedStyleInlines.h"
|
||||||
#include "mozilla/dom/Element.h"
|
#include "mozilla/dom/Element.h"
|
||||||
#include "mozilla/ServoStyleSet.h"
|
#include "mozilla/ServoStyleSet.h"
|
||||||
#include "nsPresContextInlines.h"
|
#include "nsPresContextInlines.h"
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>CSS Test Reference</title>
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>A</td>
|
||||||
|
<td id="target" style="position: relative">B
|
||||||
|
<div style="position: absolute; top: 0; left: 0; width: 100px; height: 100px; background-color: lime;"></div>
|
||||||
|
</td>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<!doctype html>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Dynamic position change in table cell with abspos child</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-position-3/#position-property">
|
||||||
|
<link rel="help" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1815552">
|
||||||
|
<link rel="author" title="Emilio Cobos Álvarez" href="mailto:emilio@crisal.io">
|
||||||
|
<link rel="author" title="Mozilla" href="https://mozilla.org">
|
||||||
|
<link rel="match" href="abspos-container-change-dynamic-001-ref.html">
|
||||||
|
<table>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>A</td>
|
||||||
|
<td id="target">B</td>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<script>
|
||||||
|
let target = document.getElementById("target");
|
||||||
|
target.getBoundingClientRect();
|
||||||
|
target.style.position = "relative";
|
||||||
|
let abspos = document.createElement("div");
|
||||||
|
abspos.style = `
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: lime;
|
||||||
|
`;
|
||||||
|
target.appendChild(abspos);
|
||||||
|
</script>
|
||||||
Loading…
Reference in a new issue