2017-10-27 20:33:53 +03:00
|
|
|
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
2012-05-21 15:12:37 +04:00
|
|
|
/* 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/. */
|
2006-03-29 22:29:03 +04:00
|
|
|
|
|
|
|
/* base class #1 for rendering objects that have child lists */
|
|
|
|
|
1998-10-01 01:35:29 +04:00
|
|
|
#include "nsContainerFrame.h"
|
2011-12-28 00:18:48 +04:00
|
|
|
|
2018-03-22 21:20:41 +03:00
|
|
|
#include "mozilla/ComputedStyle.h"
|
2016-09-01 18:36:22 +03:00
|
|
|
#include "mozilla/dom/HTMLSummaryElement.h"
|
2012-08-08 17:05:17 +04:00
|
|
|
#include "nsAbsoluteContainingBlock.h"
|
2016-12-01 01:51:12 +03:00
|
|
|
#include "nsAttrValue.h"
|
|
|
|
#include "nsAttrValueInlines.h"
|
Bug 1105111 part 3: Add support for 'flex-basis:content' in layout. r=mats
BACKGROUND:
Early in flex layout, we have to resolve the 'flex-basis' value to produce the
"flex base size" (basically, the flex-basis resolved to an absolute length).
This resolution happens in two "phases" (which both happen within
nsFlexContainer::GenerateFlexItemForChild()):
First phase: we try to resolve the flex-basis by creating a ReflowInput for the
flex item (which gets us some other things as well). Under the hood, we use
the flex-basis when resolving this ReflowInput's main-axis size. The code for
this lives in nsFrame::ComputeSize (and in
nsFrame::ComputeSizeWithIntrinsicDimensions, via some frame classes' overrides of
ComputeSize).
Second phase: If the first phase didn't get us a definite size, then that means
we have to do reflow to measure the content size & produce a resolved flex base
size, which we do via ResolveAutoFlexBasisAndMinSize().
NOTES ON THIS PATCH:
To add 'flex-basis:content' support to layout, this patch only needs to modify
the first phase discussed above. If it turns out we also have some second-phase
work to do (i.e. if we need to do reflow to resolve 'flex-basis:content'), this
patch causes that reflow to happen by simply making us use eStyleUnit_Auto in
the main axis's nsStyleCoord in the first phase. (And then, if that 'auto'
nsStyleCoord really does require reflow, then that first phase will end up
producing an unconstrained main-size in the flex item's ReflowInput, which will
automatically trigger the second phase.)
MozReview-Commit-ID: 2nH4Fh78C81
2018-03-31 02:50:49 +03:00
|
|
|
#include "nsFlexContainerFrame.h"
|
2003-04-06 06:49:40 +04:00
|
|
|
#include "nsIDocument.h"
|
2004-08-01 03:15:21 +04:00
|
|
|
#include "nsPresContext.h"
|
1998-10-01 01:35:29 +04:00
|
|
|
#include "nsRect.h"
|
|
|
|
#include "nsPoint.h"
|
|
|
|
#include "nsStyleConsts.h"
|
2013-01-03 17:23:11 +04:00
|
|
|
#include "nsView.h"
|
1999-10-21 09:11:43 +04:00
|
|
|
#include "nsIPresShell.h"
|
|
|
|
#include "nsCOMPtr.h"
|
2007-01-30 03:06:41 +03:00
|
|
|
#include "nsGkAtoms.h"
|
2013-01-05 07:12:24 +04:00
|
|
|
#include "nsViewManager.h"
|
2001-07-16 06:40:48 +04:00
|
|
|
#include "nsIWidget.h"
|
2002-01-14 18:00:30 +03:00
|
|
|
#include "nsCSSRendering.h"
|
2012-07-27 18:03:27 +04:00
|
|
|
#include "nsError.h"
|
2006-01-26 05:29:17 +03:00
|
|
|
#include "nsDisplayList.h"
|
2008-01-10 01:50:29 +03:00
|
|
|
#include "nsIBaseWindow.h"
|
2012-07-31 04:43:29 +04:00
|
|
|
#include "nsBoxLayoutState.h"
|
2008-08-13 04:44:14 +04:00
|
|
|
#include "nsCSSFrameConstructor.h"
|
2013-08-22 22:32:52 +04:00
|
|
|
#include "nsBlockFrame.h"
|
2016-12-01 01:51:12 +03:00
|
|
|
#include "nsBulletFrame.h"
|
2016-01-28 02:11:00 +03:00
|
|
|
#include "nsPlaceholderFrame.h"
|
2013-08-14 10:55:46 +04:00
|
|
|
#include "mozilla/AutoRestore.h"
|
2013-10-02 01:00:38 +04:00
|
|
|
#include "nsIFrameInlines.h"
|
2014-01-27 02:07:02 +04:00
|
|
|
#include "nsPrintfCString.h"
|
2013-01-15 16:22:03 +04:00
|
|
|
#include <algorithm>
|
2001-12-01 17:31:45 +03:00
|
|
|
|
2010-03-29 05:46:55 +04:00
|
|
|
using namespace mozilla;
|
2010-04-30 17:12:05 +04:00
|
|
|
using namespace mozilla::dom;
|
2013-04-01 19:26:02 +04:00
|
|
|
using namespace mozilla::layout;
|
2010-03-29 05:46:55 +04:00
|
|
|
|
1999-01-16 01:53:39 +03:00
|
|
|
nsContainerFrame::~nsContainerFrame()
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-09-18 15:09:35 +04:00
|
|
|
NS_QUERYFRAME_HEAD(nsContainerFrame)
|
|
|
|
NS_QUERYFRAME_ENTRY(nsContainerFrame)
|
|
|
|
NS_QUERYFRAME_TAIL_INHERITING(nsSplittableFrame)
|
|
|
|
|
2013-03-20 05:47:48 +04:00
|
|
|
void
|
2014-05-25 02:20:40 +04:00
|
|
|
nsContainerFrame::Init(nsIContent* aContent,
|
|
|
|
nsContainerFrame* aParent,
|
|
|
|
nsIFrame* aPrevInFlow)
|
2001-04-17 10:43:01 +04:00
|
|
|
{
|
2013-03-20 05:47:48 +04:00
|
|
|
nsSplittableFrame::Init(aContent, aParent, aPrevInFlow);
|
2001-04-17 10:43:01 +04:00
|
|
|
if (aPrevInFlow) {
|
|
|
|
// Make sure we copy bits from our prev-in-flow that will affect
|
|
|
|
// us. A continuation for a container frame needs to know if it
|
|
|
|
// has a child with a view so that we'll properly reposition it.
|
2003-06-26 15:30:17 +04:00
|
|
|
if (aPrevInFlow->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)
|
|
|
|
AddStateBits(NS_FRAME_HAS_CHILD_WITH_VIEW);
|
2001-04-17 10:43:01 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-28 23:36:58 +04:00
|
|
|
void
|
2011-08-25 00:54:30 +04:00
|
|
|
nsContainerFrame::SetInitialChildList(ChildListID aListID,
|
2009-07-28 16:53:20 +04:00
|
|
|
nsFrameList& aChildList)
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2012-06-25 23:59:42 +04:00
|
|
|
#ifdef DEBUG
|
2014-05-28 23:36:58 +04:00
|
|
|
nsFrame::VerifyDirtyBitSet(aChildList);
|
1999-07-25 01:41:15 +04:00
|
|
|
#endif
|
2016-01-28 02:11:00 +03:00
|
|
|
if (aListID == kPrincipalList) {
|
|
|
|
MOZ_ASSERT(mFrames.IsEmpty(),
|
|
|
|
"unexpected second call to SetInitialChildList");
|
|
|
|
mFrames.SetFrames(aChildList);
|
2016-01-28 02:11:00 +03:00
|
|
|
} else if (aListID == kBackdropList) {
|
|
|
|
MOZ_ASSERT(StyleDisplay()->mTopLayer != NS_STYLE_TOP_LAYER_NONE,
|
|
|
|
"Only top layer frames should have backdrop");
|
|
|
|
MOZ_ASSERT(GetStateBits() & NS_FRAME_OUT_OF_FLOW,
|
|
|
|
"Top layer frames should be out-of-flow");
|
2017-05-27 14:36:00 +03:00
|
|
|
MOZ_ASSERT(!GetProperty(BackdropProperty()),
|
2016-01-28 02:11:00 +03:00
|
|
|
"We shouldn't have setup backdrop frame list before");
|
2016-01-28 02:11:00 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
{
|
|
|
|
nsIFrame* placeholder = aChildList.FirstChild();
|
|
|
|
MOZ_ASSERT(aChildList.OnlyChild(), "Should have only one backdrop");
|
2017-04-30 18:30:08 +03:00
|
|
|
MOZ_ASSERT(placeholder->IsPlaceholderFrame(),
|
2016-01-28 02:11:00 +03:00
|
|
|
"The frame to be stored should be a placeholder");
|
|
|
|
MOZ_ASSERT(static_cast<nsPlaceholderFrame*>(placeholder)->
|
2017-04-30 18:30:08 +03:00
|
|
|
GetOutOfFlowFrame()->IsBackdropFrame(),
|
2016-01-28 02:11:00 +03:00
|
|
|
"The placeholder should points to a backdrop frame");
|
|
|
|
}
|
|
|
|
#endif
|
2017-11-09 05:00:48 +03:00
|
|
|
nsFrameList* list = new (PresShell()) nsFrameList(aChildList);
|
2017-05-27 14:36:00 +03:00
|
|
|
SetProperty(BackdropProperty(), list);
|
2016-01-28 02:11:00 +03:00
|
|
|
} else {
|
|
|
|
MOZ_ASSERT_UNREACHABLE("Unexpected child list");
|
|
|
|
}
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
|
2014-05-28 23:36:58 +04:00
|
|
|
void
|
2011-08-25 00:54:30 +04:00
|
|
|
nsContainerFrame::AppendFrames(ChildListID aListID,
|
2009-07-30 21:23:32 +04:00
|
|
|
nsFrameList& aFrameList)
|
2006-12-25 21:53:52 +03:00
|
|
|
{
|
2014-05-28 23:36:58 +04:00
|
|
|
MOZ_ASSERT(aListID == kPrincipalList || aListID == kNoReflowPrincipalList,
|
|
|
|
"unexpected child list");
|
2015-04-11 03:21:06 +03:00
|
|
|
|
|
|
|
if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DrainSelfOverflowList(); // ensure the last frame is in mFrames
|
|
|
|
mFrames.AppendFrames(this, aFrameList);
|
|
|
|
|
|
|
|
if (aListID != kNoReflowPrincipalList) {
|
2017-11-09 05:00:48 +03:00
|
|
|
PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
2006-12-25 21:53:52 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-28 23:36:58 +04:00
|
|
|
void
|
2011-08-25 00:54:30 +04:00
|
|
|
nsContainerFrame::InsertFrames(ChildListID aListID,
|
2006-12-25 21:53:52 +03:00
|
|
|
nsIFrame* aPrevFrame,
|
2009-07-30 21:23:32 +04:00
|
|
|
nsFrameList& aFrameList)
|
2006-12-25 21:53:52 +03:00
|
|
|
{
|
2014-05-28 23:36:58 +04:00
|
|
|
MOZ_ASSERT(aListID == kPrincipalList || aListID == kNoReflowPrincipalList,
|
|
|
|
"unexpected child list");
|
2006-12-25 21:53:52 +03:00
|
|
|
NS_ASSERTION(!aPrevFrame || aPrevFrame->GetParent() == this,
|
|
|
|
"inserting after sibling frame with different parent");
|
|
|
|
|
2015-04-11 03:21:06 +03:00
|
|
|
if (MOZ_UNLIKELY(aFrameList.IsEmpty())) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
DrainSelfOverflowList(); // ensure aPrevFrame is in mFrames
|
|
|
|
mFrames.InsertFrames(this, aPrevFrame, aFrameList);
|
2006-12-25 21:53:52 +03:00
|
|
|
|
2015-04-11 03:21:06 +03:00
|
|
|
if (aListID != kNoReflowPrincipalList) {
|
2017-11-09 05:00:48 +03:00
|
|
|
PresShell()->FrameNeedsReflow(this, nsIPresShell::eTreeChange,
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
2006-12-25 21:53:52 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-28 23:36:58 +04:00
|
|
|
void
|
2011-08-25 00:54:30 +04:00
|
|
|
nsContainerFrame::RemoveFrame(ChildListID aListID,
|
2006-12-25 21:53:52 +03:00
|
|
|
nsIFrame* aOldFrame)
|
|
|
|
{
|
2014-05-28 23:36:58 +04:00
|
|
|
MOZ_ASSERT(aListID == kPrincipalList || aListID == kNoReflowPrincipalList,
|
|
|
|
"unexpected child list");
|
2006-12-25 21:53:52 +03:00
|
|
|
|
2018-01-15 23:39:03 +03:00
|
|
|
AutoTArray<nsIFrame*, 10> continuations;
|
|
|
|
{
|
|
|
|
nsIFrame* continuation = aOldFrame;
|
|
|
|
while (continuation) {
|
|
|
|
continuations.AppendElement(continuation);
|
|
|
|
continuation = continuation->GetNextContinuation();
|
|
|
|
}
|
2011-11-17 02:54:08 +04:00
|
|
|
}
|
2018-01-15 23:39:03 +03:00
|
|
|
|
2017-11-09 05:00:48 +03:00
|
|
|
nsIPresShell* shell = PresShell();
|
2012-07-30 18:20:58 +04:00
|
|
|
nsContainerFrame* lastParent = nullptr;
|
2018-01-15 23:39:03 +03:00
|
|
|
|
|
|
|
// Loop and destroy aOldFrame and all of its continuations.
|
|
|
|
//
|
|
|
|
// Request a reflow on the parent frames involved unless we were explicitly
|
|
|
|
// told not to (kNoReflowPrincipalList).
|
|
|
|
const bool generateReflowCommand = (kNoReflowPrincipalList != aListID);
|
|
|
|
for (nsIFrame* continuation : Reversed(continuations)) {
|
|
|
|
nsContainerFrame* parent = continuation->GetParent();
|
|
|
|
|
|
|
|
// Please note that 'parent' may not actually be where 'continuation' lives.
|
2015-04-16 12:04:19 +03:00
|
|
|
// We really MUST use StealFrame() and nothing else here.
|
|
|
|
// @see nsInlineFrame::StealFrame for details.
|
2018-01-15 23:39:03 +03:00
|
|
|
parent->StealFrame(continuation);
|
|
|
|
continuation->Destroy();
|
|
|
|
if (generateReflowCommand && parent != lastParent) {
|
2014-02-07 02:07:47 +04:00
|
|
|
shell->FrameNeedsReflow(parent, nsIPresShell::eTreeChange,
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
2011-11-17 02:54:08 +04:00
|
|
|
lastParent = parent;
|
2006-12-25 21:53:52 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-11-02 04:52:59 +04:00
|
|
|
void
|
2017-11-07 03:20:33 +03:00
|
|
|
nsContainerFrame::DestroyAbsoluteFrames(nsIFrame* aDestructRoot,
|
|
|
|
PostDestroyData& aPostDestroyData)
|
2012-11-02 04:52:59 +04:00
|
|
|
{
|
|
|
|
if (IsAbsoluteContainer()) {
|
2017-11-07 03:20:33 +03:00
|
|
|
GetAbsoluteContainingBlock()->DestroyFrames(this, aDestructRoot, aPostDestroyData);
|
2012-11-02 04:52:59 +04:00
|
|
|
MarkAsNotAbsoluteContainingBlock();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-11 06:28:50 +04:00
|
|
|
void
|
2017-11-07 03:20:33 +03:00
|
|
|
nsContainerFrame::SafelyDestroyFrameListProp(nsIFrame* aDestructRoot,
|
|
|
|
PostDestroyData& aPostDestroyData,
|
|
|
|
nsIPresShell* aPresShell,
|
2016-01-28 06:23:59 +03:00
|
|
|
FrameListPropertyDescriptor aProp)
|
2013-02-11 06:28:50 +04:00
|
|
|
{
|
|
|
|
// Note that the last frame can be removed through another route and thus
|
|
|
|
// delete the property -- that's why we fetch the property again before
|
|
|
|
// removing each frame rather than fetching it once and iterating the list.
|
2017-05-27 14:36:00 +03:00
|
|
|
while (nsFrameList* frameList = GetProperty(aProp)) {
|
2013-02-11 06:28:50 +04:00
|
|
|
nsIFrame* frame = frameList->RemoveFirstChild();
|
|
|
|
if (MOZ_LIKELY(frame)) {
|
2017-11-07 03:20:33 +03:00
|
|
|
frame->DestroyFrom(aDestructRoot, aPostDestroyData);
|
2013-02-11 06:28:50 +04:00
|
|
|
} else {
|
2017-05-27 14:36:00 +03:00
|
|
|
RemoveProperty(aProp);
|
2013-04-01 19:26:02 +04:00
|
|
|
frameList->Delete(aPresShell);
|
2013-02-11 06:28:50 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-04-10 04:16:29 +04:00
|
|
|
void
|
2017-11-07 03:20:33 +03:00
|
|
|
nsContainerFrame::DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData& aPostDestroyData)
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2013-04-01 19:26:02 +04:00
|
|
|
// Prevent event dispatch during destruction.
|
2003-06-20 03:44:01 +04:00
|
|
|
if (HasView()) {
|
2012-07-30 18:20:58 +04:00
|
|
|
GetView()->SetFrame(nullptr);
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
|
2017-11-07 03:20:33 +03:00
|
|
|
DestroyAbsoluteFrames(aDestructRoot, aPostDestroyData);
|
2012-11-02 04:52:59 +04:00
|
|
|
|
2013-04-01 19:26:02 +04:00
|
|
|
// Destroy frames on the principal child list.
|
2017-11-07 03:20:33 +03:00
|
|
|
mFrames.DestroyFramesFrom(aDestructRoot, aPostDestroyData);
|
2007-07-26 08:03:29 +04:00
|
|
|
|
2017-05-31 22:29:49 +03:00
|
|
|
// If we have any IB split siblings, clear their references to us.
|
|
|
|
if (HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) {
|
|
|
|
// Delete previous sibling's reference to me.
|
|
|
|
nsIFrame* prevSib = GetProperty(nsIFrame::IBSplitPrevSibling());
|
|
|
|
if (prevSib) {
|
|
|
|
NS_WARNING_ASSERTION(
|
|
|
|
this == prevSib->GetProperty(nsIFrame::IBSplitSibling()),
|
|
|
|
"IB sibling chain is inconsistent");
|
|
|
|
prevSib->DeleteProperty(nsIFrame::IBSplitSibling());
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete next sibling's reference to me.
|
|
|
|
nsIFrame* nextSib = GetProperty(nsIFrame::IBSplitSibling());
|
|
|
|
if (nextSib) {
|
|
|
|
NS_WARNING_ASSERTION(
|
|
|
|
this == nextSib->GetProperty(nsIFrame::IBSplitPrevSibling()),
|
|
|
|
"IB sibling chain is inconsistent");
|
|
|
|
nextSib->DeleteProperty(nsIFrame::IBSplitPrevSibling());
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
// This is just so we can assert it's not set in nsFrame::DestroyFrom.
|
|
|
|
RemoveStateBits(NS_FRAME_PART_OF_IBSPLIT);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-06-03 20:25:56 +03:00
|
|
|
if (MOZ_UNLIKELY(!mProperties.IsEmpty())) {
|
|
|
|
using T = mozilla::FrameProperties::UntypedDescriptor;
|
|
|
|
bool hasO = false, hasOC = false, hasEOC = false, hasBackdrop = false;
|
|
|
|
mProperties.ForEach([&] (const T& aProp, void*) {
|
|
|
|
if (aProp == OverflowProperty()) {
|
|
|
|
hasO = true;
|
|
|
|
} else if (aProp == OverflowContainersProperty()) {
|
|
|
|
hasOC = true;
|
|
|
|
} else if (aProp == ExcessOverflowContainersProperty()) {
|
|
|
|
hasEOC = true;
|
|
|
|
} else if (aProp == BackdropProperty()) {
|
|
|
|
hasBackdrop = true;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
|
|
|
// Destroy frames on the auxiliary frame lists and delete the lists.
|
|
|
|
nsPresContext* pc = PresContext();
|
|
|
|
nsIPresShell* shell = pc->PresShell();
|
|
|
|
if (hasO) {
|
2017-11-07 03:20:33 +03:00
|
|
|
SafelyDestroyFrameListProp(aDestructRoot, aPostDestroyData, shell,
|
|
|
|
OverflowProperty());
|
2017-06-03 20:25:56 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(IsFrameOfType(eCanContainOverflowContainers) ||
|
|
|
|
!(hasOC || hasEOC),
|
|
|
|
"this type of frame shouldn't have overflow containers");
|
|
|
|
if (hasOC) {
|
2017-11-07 03:20:33 +03:00
|
|
|
SafelyDestroyFrameListProp(aDestructRoot, aPostDestroyData, shell,
|
2017-06-03 20:25:56 +03:00
|
|
|
OverflowContainersProperty());
|
|
|
|
}
|
|
|
|
if (hasEOC) {
|
2017-11-07 03:20:33 +03:00
|
|
|
SafelyDestroyFrameListProp(aDestructRoot, aPostDestroyData, shell,
|
2017-06-03 20:25:56 +03:00
|
|
|
ExcessOverflowContainersProperty());
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(!GetProperty(BackdropProperty()) ||
|
|
|
|
StyleDisplay()->mTopLayer != NS_STYLE_TOP_LAYER_NONE,
|
|
|
|
"only top layer frame may have backdrop");
|
|
|
|
if (hasBackdrop) {
|
2017-11-07 03:20:33 +03:00
|
|
|
SafelyDestroyFrameListProp(aDestructRoot, aPostDestroyData, shell,
|
|
|
|
BackdropProperty());
|
2017-06-03 20:25:56 +03:00
|
|
|
}
|
|
|
|
}
|
2016-01-28 02:11:00 +03:00
|
|
|
|
2017-11-07 03:20:33 +03:00
|
|
|
nsSplittableFrame::DestroyFrom(aDestructRoot, aPostDestroyData);
|
1998-11-14 22:25:34 +03:00
|
|
|
}
|
|
|
|
|
1998-10-01 01:35:29 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Child frame enumeration
|
|
|
|
|
2012-03-08 05:57:37 +04:00
|
|
|
const nsFrameList&
|
2011-08-25 00:54:29 +04:00
|
|
|
nsContainerFrame::GetChildList(ChildListID aListID) const
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2016-01-28 02:11:00 +03:00
|
|
|
// We only know about the principal child list, the overflow lists,
|
|
|
|
// and the backdrop list.
|
2011-08-25 00:54:29 +04:00
|
|
|
switch (aListID) {
|
|
|
|
case kPrincipalList:
|
|
|
|
return mFrames;
|
|
|
|
case kOverflowList: {
|
|
|
|
nsFrameList* list = GetOverflowFrames();
|
|
|
|
return list ? *list : nsFrameList::EmptyList();
|
|
|
|
}
|
|
|
|
case kOverflowContainersList: {
|
2014-02-07 02:07:47 +04:00
|
|
|
nsFrameList* list = GetPropTableFrames(OverflowContainersProperty());
|
2011-08-25 00:54:29 +04:00
|
|
|
return list ? *list : nsFrameList::EmptyList();
|
|
|
|
}
|
|
|
|
case kExcessOverflowContainersList: {
|
|
|
|
nsFrameList* list =
|
2014-02-07 02:07:47 +04:00
|
|
|
GetPropTableFrames(ExcessOverflowContainersProperty());
|
2011-08-25 00:54:29 +04:00
|
|
|
return list ? *list : nsFrameList::EmptyList();
|
|
|
|
}
|
2016-01-28 02:11:00 +03:00
|
|
|
case kBackdropList: {
|
|
|
|
nsFrameList* list = GetPropTableFrames(BackdropProperty());
|
|
|
|
return list ? *list : nsFrameList::EmptyList();
|
|
|
|
}
|
2011-08-25 00:54:29 +04:00
|
|
|
default:
|
|
|
|
return nsSplittableFrame::GetChildList(aListID);
|
2009-07-28 16:51:09 +04:00
|
|
|
}
|
2011-08-25 00:54:29 +04:00
|
|
|
}
|
2009-07-28 16:51:09 +04:00
|
|
|
|
2011-08-25 00:54:29 +04:00
|
|
|
void
|
|
|
|
nsContainerFrame::GetChildLists(nsTArray<ChildList>* aLists) const
|
2003-06-02 08:03:07 +04:00
|
|
|
{
|
2011-08-25 00:54:29 +04:00
|
|
|
mFrames.AppendIfNonempty(aLists, kPrincipalList);
|
2017-06-03 20:25:56 +03:00
|
|
|
|
|
|
|
using T = mozilla::FrameProperties::UntypedDescriptor;
|
|
|
|
mProperties.ForEach([this, aLists] (const T& aProp, void* aValue) {
|
|
|
|
typedef const nsFrameList* L;
|
|
|
|
if (aProp == OverflowProperty()) {
|
|
|
|
L(aValue)->AppendIfNonempty(aLists, kOverflowList);
|
|
|
|
} else if (aProp == OverflowContainersProperty()) {
|
|
|
|
MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
|
|
|
|
"found unexpected OverflowContainersProperty");
|
2017-06-16 15:08:20 +03:00
|
|
|
Unused << this; // silence clang -Wunused-lambda-capture in opt builds
|
2017-06-03 20:25:56 +03:00
|
|
|
L(aValue)->AppendIfNonempty(aLists, kOverflowContainersList);
|
|
|
|
} else if (aProp == ExcessOverflowContainersProperty()) {
|
|
|
|
MOZ_ASSERT(IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
|
|
|
|
"found unexpected ExcessOverflowContainersProperty");
|
2017-06-16 15:08:20 +03:00
|
|
|
Unused << this; // silence clang -Wunused-lambda-capture in opt builds
|
2017-06-03 20:25:56 +03:00
|
|
|
L(aValue)->AppendIfNonempty(aLists, kExcessOverflowContainersList);
|
|
|
|
} else if (aProp == BackdropProperty()) {
|
|
|
|
L(aValue)->AppendIfNonempty(aLists, kBackdropList);
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
|
|
|
|
2011-04-30 03:02:33 +04:00
|
|
|
nsSplittableFrame::GetChildLists(aLists);
|
2003-06-02 08:03:07 +04:00
|
|
|
}
|
|
|
|
|
1998-10-01 01:35:29 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
1999-01-16 01:53:39 +03:00
|
|
|
// Painting/Events
|
1998-10-01 01:35:29 +04:00
|
|
|
|
2013-02-14 15:12:27 +04:00
|
|
|
void
|
2006-01-26 05:29:17 +03:00
|
|
|
nsContainerFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists)
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2013-02-14 15:08:08 +04:00
|
|
|
DisplayBorderBackgroundOutline(aBuilder, aLists);
|
2017-08-07 05:23:35 +03:00
|
|
|
BuildDisplayListForNonBlockChildren(aBuilder, aLists);
|
1998-10-31 01:11:06 +03:00
|
|
|
}
|
1998-10-07 01:00:58 +04:00
|
|
|
|
2013-02-14 15:12:27 +04:00
|
|
|
void
|
2006-01-26 05:29:17 +03:00
|
|
|
nsContainerFrame::BuildDisplayListForNonBlockChildren(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags)
|
1998-10-31 01:11:06 +03:00
|
|
|
{
|
2006-01-26 05:29:17 +03:00
|
|
|
nsIFrame* kid = mFrames.FirstChild();
|
|
|
|
// Put each child's background directly onto the content list
|
|
|
|
nsDisplayListSet set(aLists, aLists.Content());
|
|
|
|
// The children should be in content order
|
2003-06-26 15:30:17 +04:00
|
|
|
while (kid) {
|
2017-08-07 05:23:35 +03:00
|
|
|
BuildDisplayListForChild(aBuilder, kid, set, aFlags);
|
2003-06-26 15:30:17 +04:00
|
|
|
kid = kid->GetNextSibling();
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
/* virtual */ void
|
|
|
|
nsContainerFrame::ChildIsDirty(nsIFrame* aChild)
|
2000-01-12 11:28:24 +03:00
|
|
|
{
|
2013-05-11 04:35:08 +04:00
|
|
|
NS_ASSERTION(NS_SUBTREE_DIRTY(aChild), "child isn't actually dirty");
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
2000-01-12 11:28:24 +03:00
|
|
|
}
|
|
|
|
|
2014-03-13 18:14:37 +04:00
|
|
|
nsIFrame::FrameSearchResult
|
2012-08-22 19:56:38 +04:00
|
|
|
nsContainerFrame::PeekOffsetNoAmount(bool aForward, int32_t* aOffset)
|
2006-12-15 12:32:24 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
|
|
|
|
// Don't allow the caret to stay in an empty (leaf) container frame.
|
2014-03-13 18:14:37 +04:00
|
|
|
return CONTINUE_EMPTY;
|
2006-12-15 12:32:24 +03:00
|
|
|
}
|
|
|
|
|
2014-03-13 18:14:37 +04:00
|
|
|
nsIFrame::FrameSearchResult
|
Bug 1375825 - part2: ContentEventHandler::ExpandToClusterBoundary() should check the return value of nsTextFrame::PeekOffsetCharacter() r=jfkthame
ContentEventHandler::ExpandToClusterBoundary() doesn't check the return value of nsTextFrame::PeekOffsetCharacter(). Therefore, it may set its result to reversed offset. (e.g., when aForward is true and offset is 6, the result may be 5. When aForward is false and offset is 5, the result may be 6.)
For avoiding that, ContentEventHandler::ExpandToClusterBoundary() should check the result and only when it returns nsIFrame::FOUND, it should compute the proper offset.
On the other hand, it's too bad for ContentEventHandler that nsTextFrame::PeekOffsetCharacter() to return nsIFrame::CONTINUE_UNSELECTABLE when the user-select style is "all" because IME doesn't expect such cases.
Therefore, this patch adds additional argument to nsIFrame::PeekOffsetCharacter(), aOptions which is a struct containing bool members. The reason why it's not a bit mask enum is, such struct doesn't cause simple mistake at checking the value and the code is shorter. When mIgnoreUserStyleAll of it is true, this patch makes nsTextFrame not return nsIFrame::CONTINUE_UNSELECTABLE.
MozReview-Commit-ID: ACNNBTP92YZ
--HG--
extra : rebase_source : bd85da902e7fb59135d15514cb20a5599a4a640b
2017-06-29 04:58:16 +03:00
|
|
|
nsContainerFrame::PeekOffsetCharacter(
|
|
|
|
bool aForward, int32_t* aOffset,
|
|
|
|
PeekOffsetCharacterOptions aOptions)
|
2006-12-15 12:32:24 +03:00
|
|
|
{
|
|
|
|
NS_ASSERTION (aOffset && *aOffset <= 1, "aOffset out of range");
|
|
|
|
// Don't allow the caret to stay in an empty (leaf) container frame.
|
2014-03-13 18:14:37 +04:00
|
|
|
return CONTINUE_EMPTY;
|
2006-12-15 12:32:24 +03:00
|
|
|
}
|
|
|
|
|
1998-10-01 01:35:29 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Helper member functions
|
|
|
|
|
2001-09-21 04:53:29 +04:00
|
|
|
/**
|
|
|
|
* Position the view associated with |aKidFrame|, if there is one. A
|
|
|
|
* container frame should call this method after positioning a frame,
|
|
|
|
* but before |Reflow|.
|
|
|
|
*/
|
1999-11-19 18:33:29 +03:00
|
|
|
void
|
2004-12-27 18:05:18 +03:00
|
|
|
nsContainerFrame::PositionFrameView(nsIFrame* aKidFrame)
|
1999-11-19 18:33:29 +03:00
|
|
|
{
|
2005-04-04 01:00:41 +04:00
|
|
|
nsIFrame* parentFrame = aKidFrame->GetParent();
|
|
|
|
if (!aKidFrame->HasView() || !parentFrame)
|
|
|
|
return;
|
2001-09-21 04:53:29 +04:00
|
|
|
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* view = aKidFrame->GetView();
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager* vm = view->GetViewManager();
|
2005-04-04 01:00:41 +04:00
|
|
|
nsPoint pt;
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* ancestorView = parentFrame->GetClosestView(&pt);
|
2005-03-31 07:40:12 +04:00
|
|
|
|
2005-04-04 01:00:41 +04:00
|
|
|
if (ancestorView != view->GetParent()) {
|
|
|
|
NS_ASSERTION(ancestorView == view->GetParent()->GetParent(),
|
|
|
|
"Allowed only one anonymous view between frames");
|
|
|
|
// parentFrame is responsible for positioning aKidFrame's view
|
|
|
|
// explicitly
|
|
|
|
return;
|
2005-03-31 22:04:50 +04:00
|
|
|
}
|
2005-04-04 01:00:41 +04:00
|
|
|
|
|
|
|
pt += aKidFrame->GetPosition();
|
|
|
|
vm->MoveViewTo(view, pt.x, pt.y);
|
1999-11-19 18:33:29 +03:00
|
|
|
}
|
|
|
|
|
2011-04-19 15:55:11 +04:00
|
|
|
nsresult
|
2014-02-07 02:07:48 +04:00
|
|
|
nsContainerFrame::ReparentFrameView(nsIFrame* aChildFrame,
|
|
|
|
nsIFrame* aOldParentFrame,
|
|
|
|
nsIFrame* aNewParentFrame)
|
2011-04-19 15:55:11 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aChildFrame, "null child frame pointer");
|
|
|
|
MOZ_ASSERT(aOldParentFrame, "null old parent frame pointer");
|
|
|
|
MOZ_ASSERT(aNewParentFrame, "null new parent frame pointer");
|
|
|
|
MOZ_ASSERT(aOldParentFrame != aNewParentFrame, "same old and new parent frame");
|
2011-04-19 15:55:11 +04:00
|
|
|
|
|
|
|
// See if either the old parent frame or the new parent frame have a view
|
|
|
|
while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) {
|
|
|
|
// Walk up both the old parent frame and the new parent frame nodes
|
|
|
|
// stopping when we either find a common parent or views for one
|
|
|
|
// or both of the frames.
|
|
|
|
//
|
|
|
|
// This works well in the common case where we push/pull and the old parent
|
|
|
|
// frame and the new parent frame are part of the same flow. They will
|
|
|
|
// typically be the same distance (height wise) from the
|
|
|
|
aOldParentFrame = aOldParentFrame->GetParent();
|
|
|
|
aNewParentFrame = aNewParentFrame->GetParent();
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-04-19 15:55:11 +04:00
|
|
|
// We should never walk all the way to the root frame without finding
|
|
|
|
// a view
|
|
|
|
NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view");
|
|
|
|
|
|
|
|
// See if we reached a common ancestor
|
|
|
|
if (aOldParentFrame == aNewParentFrame) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// See if we found a common parent frame
|
|
|
|
if (aOldParentFrame == aNewParentFrame) {
|
|
|
|
// We found a common parent and there are no views between the old parent
|
|
|
|
// and the common parent or the new parent frame and the common parent.
|
|
|
|
// Because neither the old parent frame nor the new parent frame have views,
|
|
|
|
// then any child views don't need reparenting
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We found views for one or both of the ancestor frames before we
|
|
|
|
// found a common ancestor.
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* oldParentView = aOldParentFrame->GetClosestView();
|
|
|
|
nsView* newParentView = aNewParentFrame->GetClosestView();
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-04-19 15:55:11 +04:00
|
|
|
// See if the old parent frame and the new parent frame are in the
|
|
|
|
// same view sub-hierarchy. If they are then we don't have to do
|
|
|
|
// anything
|
|
|
|
if (oldParentView != newParentView) {
|
|
|
|
// They're not so we need to reparent any child views
|
2017-03-21 03:22:13 +03:00
|
|
|
aChildFrame->ReparentFrameViewTo(oldParentView->GetViewManager(),
|
|
|
|
newParentView,
|
|
|
|
oldParentView);
|
2011-04-19 15:55:11 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
2014-02-07 02:07:47 +04:00
|
|
|
nsContainerFrame::ReparentFrameViewList(const nsFrameList& aChildFrameList,
|
2011-04-19 15:55:11 +04:00
|
|
|
nsIFrame* aOldParentFrame,
|
|
|
|
nsIFrame* aNewParentFrame)
|
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aChildFrameList.NotEmpty(), "empty child frame list");
|
|
|
|
MOZ_ASSERT(aOldParentFrame, "null old parent frame pointer");
|
|
|
|
MOZ_ASSERT(aNewParentFrame, "null new parent frame pointer");
|
|
|
|
MOZ_ASSERT(aOldParentFrame != aNewParentFrame, "same old and new parent frame");
|
2011-04-19 15:55:11 +04:00
|
|
|
|
|
|
|
// See if either the old parent frame or the new parent frame have a view
|
|
|
|
while (!aOldParentFrame->HasView() && !aNewParentFrame->HasView()) {
|
|
|
|
// Walk up both the old parent frame and the new parent frame nodes
|
|
|
|
// stopping when we either find a common parent or views for one
|
|
|
|
// or both of the frames.
|
|
|
|
//
|
|
|
|
// This works well in the common case where we push/pull and the old parent
|
|
|
|
// frame and the new parent frame are part of the same flow. They will
|
|
|
|
// typically be the same distance (height wise) from the
|
|
|
|
aOldParentFrame = aOldParentFrame->GetParent();
|
|
|
|
aNewParentFrame = aNewParentFrame->GetParent();
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-04-19 15:55:11 +04:00
|
|
|
// We should never walk all the way to the root frame without finding
|
|
|
|
// a view
|
|
|
|
NS_ASSERTION(aOldParentFrame && aNewParentFrame, "didn't find view");
|
|
|
|
|
|
|
|
// See if we reached a common ancestor
|
|
|
|
if (aOldParentFrame == aNewParentFrame) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// See if we found a common parent frame
|
|
|
|
if (aOldParentFrame == aNewParentFrame) {
|
|
|
|
// We found a common parent and there are no views between the old parent
|
|
|
|
// and the common parent or the new parent frame and the common parent.
|
|
|
|
// Because neither the old parent frame nor the new parent frame have views,
|
|
|
|
// then any child views don't need reparenting
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
// We found views for one or both of the ancestor frames before we
|
|
|
|
// found a common ancestor.
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* oldParentView = aOldParentFrame->GetClosestView();
|
|
|
|
nsView* newParentView = aNewParentFrame->GetClosestView();
|
2017-07-06 15:00:35 +03:00
|
|
|
|
2011-04-19 15:55:11 +04:00
|
|
|
// See if the old parent frame and the new parent frame are in the
|
|
|
|
// same view sub-hierarchy. If they are then we don't have to do
|
|
|
|
// anything
|
|
|
|
if (oldParentView != newParentView) {
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager* viewManager = oldParentView->GetViewManager();
|
2011-04-19 15:55:11 +04:00
|
|
|
|
|
|
|
// They're not so we need to reparent any child views
|
|
|
|
for (nsFrameList::Enumerator e(aChildFrameList); !e.AtEnd(); e.Next()) {
|
2017-03-21 03:22:13 +03:00
|
|
|
e.get()->ReparentFrameViewTo(viewManager, newParentView, oldParentView);
|
2011-04-19 15:55:11 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
2009-08-13 00:48:30 +04:00
|
|
|
static nsIWidget*
|
|
|
|
GetPresContextContainerWidget(nsPresContext* aPresContext)
|
2008-01-10 01:50:29 +03:00
|
|
|
{
|
|
|
|
nsCOMPtr<nsISupports> container = aPresContext->Document()->GetContainer();
|
|
|
|
nsCOMPtr<nsIBaseWindow> baseWindow = do_QueryInterface(container);
|
|
|
|
if (!baseWindow)
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2008-01-10 01:50:29 +03:00
|
|
|
|
|
|
|
nsCOMPtr<nsIWidget> mainWidget;
|
|
|
|
baseWindow->GetMainWidget(getter_AddRefs(mainWidget));
|
2009-08-13 00:48:30 +04:00
|
|
|
return mainWidget;
|
|
|
|
}
|
2008-01-10 01:50:29 +03:00
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
static bool
|
2009-08-13 00:48:30 +04:00
|
|
|
IsTopLevelWidget(nsIWidget* aWidget)
|
|
|
|
{
|
2014-03-19 20:48:08 +04:00
|
|
|
nsWindowType windowType = aWidget->WindowType();
|
2008-01-10 01:50:29 +03:00
|
|
|
return windowType == eWindowType_toplevel ||
|
2010-04-27 20:15:01 +04:00
|
|
|
windowType == eWindowType_dialog ||
|
2015-11-25 16:49:23 +03:00
|
|
|
windowType == eWindowType_popup ||
|
2009-08-13 00:48:30 +04:00
|
|
|
windowType == eWindowType_sheet;
|
2008-01-10 01:50:29 +03:00
|
|
|
}
|
|
|
|
|
2009-08-13 00:48:30 +04:00
|
|
|
void
|
|
|
|
nsContainerFrame::SyncWindowProperties(nsPresContext* aPresContext,
|
|
|
|
nsIFrame* aFrame,
|
2015-05-04 22:29:19 +03:00
|
|
|
nsView* aView,
|
2017-06-09 22:14:53 +03:00
|
|
|
gfxContext* aRC,
|
2015-05-04 22:29:19 +03:00
|
|
|
uint32_t aFlags)
|
2002-09-30 15:56:37 +04:00
|
|
|
{
|
2008-12-29 11:17:08 +03:00
|
|
|
#ifdef MOZ_XUL
|
2009-08-13 00:48:30 +04:00
|
|
|
if (!aView || !nsCSSRendering::IsCanvasFrame(aFrame) || !aView->HasWidget())
|
2009-02-16 04:11:34 +03:00
|
|
|
return;
|
2002-09-30 15:56:37 +04:00
|
|
|
|
2015-05-04 22:29:19 +03:00
|
|
|
nsCOMPtr<nsIWidget> windowWidget = GetPresContextContainerWidget(aPresContext);
|
2009-08-13 00:48:30 +04:00
|
|
|
if (!windowWidget || !IsTopLevelWidget(windowWidget))
|
2008-12-29 11:17:08 +03:00
|
|
|
return;
|
|
|
|
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager* vm = aView->GetViewManager();
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* rootView = vm->GetRootView();
|
2008-12-29 11:17:08 +03:00
|
|
|
|
2009-02-16 04:11:34 +03:00
|
|
|
if (aView != rootView)
|
2008-12-29 11:17:08 +03:00
|
|
|
return;
|
|
|
|
|
2010-04-30 17:12:05 +04:00
|
|
|
Element* rootElement = aPresContext->Document()->GetRootElement();
|
2015-03-03 14:08:59 +03:00
|
|
|
if (!rootElement || !rootElement->IsXULElement()) {
|
2008-12-29 11:17:08 +03:00
|
|
|
// Scrollframes use native widgets which don't work well with
|
|
|
|
// translucent windows, at least in Windows XP. So if the document
|
|
|
|
// has a root scrollrame it's useless to try to make it transparent,
|
|
|
|
// we'll just get something broken.
|
|
|
|
// nsCSSFrameConstructor::ConstructRootFrame constructs root
|
|
|
|
// scrollframes whenever the root element is not a XUL element, so
|
|
|
|
// we test for that here. We can't just call
|
|
|
|
// presShell->GetRootScrollFrame() since that might not have
|
|
|
|
// been constructed yet.
|
|
|
|
// We can change this to allow translucent toplevel HTML documents
|
|
|
|
// (e.g. to do something like Dashboard widgets), once we
|
|
|
|
// have broad support for translucent scrolled documents, but be
|
|
|
|
// careful because apparently some Firefox extensions expect
|
|
|
|
// openDialog("something.html") to produce an opaque window
|
|
|
|
// even if the HTML doesn't have a background-color set.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-08-13 00:48:30 +04:00
|
|
|
nsIFrame *rootFrame = aPresContext->PresShell()->FrameConstructor()->GetRootElementStyleFrame();
|
|
|
|
if (!rootFrame)
|
|
|
|
return;
|
|
|
|
|
2015-05-04 22:29:19 +03:00
|
|
|
if (aFlags & SET_ASYNC) {
|
|
|
|
aView->SetNeedsWindowPropertiesSync();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<nsPresContext> kungFuDeathGrip(aPresContext);
|
2017-03-01 20:03:14 +03:00
|
|
|
AutoWeakFrame weak(rootFrame);
|
2015-05-04 22:29:19 +03:00
|
|
|
|
2009-08-14 02:08:13 +04:00
|
|
|
nsTransparencyMode mode = nsLayoutUtils::GetFrameTransparency(aFrame, rootFrame);
|
2015-05-04 22:29:19 +03:00
|
|
|
int32_t shadow = rootFrame->StyleUIReset()->mWindowShadow;
|
|
|
|
nsCOMPtr<nsIWidget> viewWidget = aView->GetWidget();
|
2009-08-13 00:48:30 +04:00
|
|
|
viewWidget->SetTransparencyMode(mode);
|
2015-05-04 22:29:19 +03:00
|
|
|
windowWidget->SetWindowShadowStyle(shadow);
|
2012-07-31 04:43:29 +04:00
|
|
|
|
|
|
|
if (!aRC)
|
|
|
|
return;
|
2015-05-04 22:29:19 +03:00
|
|
|
|
|
|
|
if (!weak.IsAlive()) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2012-07-31 04:43:29 +04:00
|
|
|
nsBoxLayoutState aState(aPresContext, aRC);
|
2016-04-21 07:28:31 +03:00
|
|
|
nsSize minSize = rootFrame->GetXULMinSize(aState);
|
2016-04-21 07:28:31 +03:00
|
|
|
nsSize maxSize = rootFrame->GetXULMaxSize(aState);
|
2012-07-31 04:43:29 +04:00
|
|
|
|
|
|
|
SetSizeConstraints(aPresContext, windowWidget, minSize, maxSize);
|
2008-12-29 11:17:08 +03:00
|
|
|
#endif
|
2002-09-30 15:56:37 +04:00
|
|
|
}
|
|
|
|
|
2012-07-31 04:43:29 +04:00
|
|
|
void nsContainerFrame::SetSizeConstraints(nsPresContext* aPresContext,
|
|
|
|
nsIWidget* aWidget,
|
|
|
|
const nsSize& aMinSize,
|
|
|
|
const nsSize& aMaxSize)
|
|
|
|
{
|
2015-03-30 18:35:25 +03:00
|
|
|
LayoutDeviceIntSize devMinSize(aPresContext->AppUnitsToDevPixels(aMinSize.width),
|
|
|
|
aPresContext->AppUnitsToDevPixels(aMinSize.height));
|
|
|
|
LayoutDeviceIntSize devMaxSize(aMaxSize.width == NS_INTRINSICSIZE ? NS_MAXSIZE :
|
|
|
|
aPresContext->AppUnitsToDevPixels(aMaxSize.width),
|
|
|
|
aMaxSize.height == NS_INTRINSICSIZE ? NS_MAXSIZE :
|
|
|
|
aPresContext->AppUnitsToDevPixels(aMaxSize.height));
|
2014-06-11 07:03:00 +04:00
|
|
|
|
|
|
|
// MinSize has a priority over MaxSize
|
|
|
|
if (devMinSize.width > devMaxSize.width)
|
|
|
|
devMaxSize.width = devMinSize.width;
|
|
|
|
if (devMinSize.height > devMaxSize.height)
|
|
|
|
devMaxSize.height = devMinSize.height;
|
|
|
|
|
2012-07-31 04:43:29 +04:00
|
|
|
widget::SizeConstraints constraints(devMinSize, devMaxSize);
|
|
|
|
|
|
|
|
// The sizes are in inner window sizes, so convert them into outer window sizes.
|
|
|
|
// Use a size of (200, 200) as only the difference between the inner and outer
|
|
|
|
// size is needed.
|
2015-04-01 01:09:03 +03:00
|
|
|
LayoutDeviceIntSize windowSize =
|
|
|
|
aWidget->ClientToWindowSize(LayoutDeviceIntSize(200, 200));
|
2012-07-31 04:43:29 +04:00
|
|
|
if (constraints.mMinSize.width)
|
|
|
|
constraints.mMinSize.width += windowSize.width - 200;
|
|
|
|
if (constraints.mMinSize.height)
|
|
|
|
constraints.mMinSize.height += windowSize.height - 200;
|
|
|
|
if (constraints.mMaxSize.width != NS_MAXSIZE)
|
|
|
|
constraints.mMaxSize.width += windowSize.width - 200;
|
|
|
|
if (constraints.mMaxSize.height != NS_MAXSIZE)
|
|
|
|
constraints.mMaxSize.height += windowSize.height - 200;
|
|
|
|
|
|
|
|
aWidget->SetSizeConstraints(constraints);
|
|
|
|
}
|
|
|
|
|
2002-10-08 08:09:38 +04:00
|
|
|
void
|
2004-08-01 03:15:21 +04:00
|
|
|
nsContainerFrame::SyncFrameViewAfterReflow(nsPresContext* aPresContext,
|
2002-10-08 08:09:38 +04:00
|
|
|
nsIFrame* aFrame,
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* aView,
|
2010-10-07 08:25:45 +04:00
|
|
|
const nsRect& aVisualOverflowArea,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags)
|
2002-10-08 08:09:38 +04:00
|
|
|
{
|
|
|
|
if (!aView) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure the view is sized and positioned correctly
|
|
|
|
if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
|
2004-12-27 18:05:18 +03:00
|
|
|
PositionFrameView(aFrame);
|
2002-10-08 08:09:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
if (0 == (aFlags & NS_FRAME_NO_SIZE_VIEW)) {
|
2013-01-05 07:12:24 +04:00
|
|
|
nsViewManager* vm = aView->GetViewManager();
|
2002-10-08 08:09:38 +04:00
|
|
|
|
2011-10-17 18:59:28 +04:00
|
|
|
vm->ResizeView(aView, aVisualOverflowArea, true);
|
2002-10-08 08:09:38 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
static nscoord GetCoord(const nsStyleCoord& aCoord, nscoord aIfNotCoord)
|
|
|
|
{
|
2010-08-31 20:05:12 +04:00
|
|
|
if (aCoord.ConvertsToLength()) {
|
2017-11-20 09:05:19 +03:00
|
|
|
return aCoord.ComputeCoordPercentCalc(0);
|
2010-08-31 20:05:12 +04:00
|
|
|
}
|
|
|
|
return aIfNotCoord;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2017-06-09 22:14:53 +03:00
|
|
|
nsContainerFrame::DoInlineIntrinsicISize(gfxContext *aRenderingContext,
|
2014-07-24 21:03:25 +04:00
|
|
|
InlineIntrinsicISizeData *aData,
|
2014-07-24 21:03:26 +04:00
|
|
|
nsLayoutUtils::IntrinsicISizeType aType)
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
{
|
|
|
|
if (GetPrevInFlow())
|
|
|
|
return; // Already added.
|
|
|
|
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aType == nsLayoutUtils::MIN_ISIZE ||
|
|
|
|
aType == nsLayoutUtils::PREF_ISIZE, "bad type");
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
|
2015-04-07 11:24:04 +03:00
|
|
|
WritingMode wm = GetWritingMode();
|
2016-11-18 11:28:38 +03:00
|
|
|
mozilla::Side startSide =
|
2015-04-07 11:24:04 +03:00
|
|
|
wm.PhysicalSideForInlineAxis(eLogicalEdgeStart);
|
2016-11-18 11:28:38 +03:00
|
|
|
mozilla::Side endSide =
|
2015-04-07 11:24:04 +03:00
|
|
|
wm.PhysicalSideForInlineAxis(eLogicalEdgeEnd);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
|
2013-02-17 01:51:02 +04:00
|
|
|
const nsStylePadding *stylePadding = StylePadding();
|
|
|
|
const nsStyleBorder *styleBorder = StyleBorder();
|
|
|
|
const nsStyleMargin *styleMargin = StyleMargin();
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
// This goes at the beginning no matter how things are broken and how
|
|
|
|
// messy the bidi situations are, since per CSS2.1 section 8.6
|
|
|
|
// (implemented in bug 328168), the startSide border is always on the
|
|
|
|
// first line.
|
2008-03-12 00:54:34 +03:00
|
|
|
// This frame is a first-in-flow, but it might have a previous bidi
|
2010-04-27 20:15:01 +04:00
|
|
|
// continuation, in which case that continuation should handle the startSide
|
2008-03-12 00:54:34 +03:00
|
|
|
// border.
|
2014-05-05 21:55:54 +04:00
|
|
|
// For box-decoration-break:clone we setup clonePBM = startPBM + endPBM and
|
|
|
|
// add that to each line. For box-decoration-break:slice clonePBM is zero.
|
|
|
|
nscoord clonePBM = 0; // PBM = PaddingBorderMargin
|
|
|
|
const bool sliceBreak =
|
2016-08-26 10:14:32 +03:00
|
|
|
styleBorder->mBoxDecorationBreak == StyleBoxDecorationBreak::Slice;
|
2008-03-12 00:54:34 +03:00
|
|
|
if (!GetPrevContinuation()) {
|
2014-05-05 21:55:54 +04:00
|
|
|
nscoord startPBM =
|
2010-09-09 19:21:46 +04:00
|
|
|
// clamp negative calc() to 0
|
2013-01-15 16:22:03 +04:00
|
|
|
std::max(GetCoord(stylePadding->mPadding.Get(startSide), 0), 0) +
|
2012-05-31 09:19:49 +04:00
|
|
|
styleBorder->GetComputedBorderWidth(startSide) +
|
2008-03-12 00:54:34 +03:00
|
|
|
GetCoord(styleMargin->mMargin.Get(startSide), 0);
|
2014-05-05 21:55:54 +04:00
|
|
|
if (MOZ_LIKELY(sliceBreak)) {
|
2016-04-14 02:32:12 +03:00
|
|
|
aData->mCurrentLine += startPBM;
|
2014-05-05 21:55:54 +04:00
|
|
|
} else {
|
|
|
|
clonePBM = startPBM;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
nscoord endPBM =
|
|
|
|
// clamp negative calc() to 0
|
|
|
|
std::max(GetCoord(stylePadding->mPadding.Get(endSide), 0), 0) +
|
|
|
|
styleBorder->GetComputedBorderWidth(endSide) +
|
|
|
|
GetCoord(styleMargin->mMargin.Get(endSide), 0);
|
|
|
|
if (MOZ_UNLIKELY(!sliceBreak)) {
|
|
|
|
clonePBM += endPBM;
|
2008-03-12 00:54:34 +03:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
|
2016-04-14 02:32:12 +03:00
|
|
|
const nsLineList_iterator* savedLine = aData->mLine;
|
2015-11-14 11:46:11 +03:00
|
|
|
nsIFrame* const savedLineContainer = aData->LineContainer();
|
2008-01-10 06:18:44 +03:00
|
|
|
|
2008-03-12 00:54:34 +03:00
|
|
|
nsContainerFrame *lastInFlow;
|
2008-01-10 06:23:35 +03:00
|
|
|
for (nsContainerFrame *nif = this; nif;
|
2009-02-19 23:18:52 +03:00
|
|
|
nif = static_cast<nsContainerFrame*>(nif->GetNextInFlow())) {
|
2016-04-14 02:32:12 +03:00
|
|
|
if (aData->mCurrentLine == 0) {
|
|
|
|
aData->mCurrentLine = clonePBM;
|
2014-05-05 21:55:54 +04:00
|
|
|
}
|
2015-06-29 23:02:21 +03:00
|
|
|
for (nsIFrame* kid : nif->mFrames) {
|
2014-07-24 21:03:26 +04:00
|
|
|
if (aType == nsLayoutUtils::MIN_ISIZE)
|
2014-07-24 21:03:25 +04:00
|
|
|
kid->AddInlineMinISize(aRenderingContext,
|
|
|
|
static_cast<InlineMinISizeData*>(aData));
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
else
|
2014-07-24 21:03:25 +04:00
|
|
|
kid->AddInlinePrefISize(aRenderingContext,
|
|
|
|
static_cast<InlinePrefISizeData*>(aData));
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2009-02-19 23:18:52 +03:00
|
|
|
// After we advance to our next-in-flow, the stored line and line container
|
|
|
|
// may no longer be correct. Just forget them.
|
2016-04-14 02:32:12 +03:00
|
|
|
aData->mLine = nullptr;
|
2015-11-14 11:46:11 +03:00
|
|
|
aData->SetLineContainer(nullptr);
|
2009-02-19 23:18:52 +03:00
|
|
|
|
2008-03-12 00:54:34 +03:00
|
|
|
lastInFlow = nif;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2016-04-14 02:32:12 +03:00
|
|
|
aData->mLine = savedLine;
|
2015-11-14 11:46:11 +03:00
|
|
|
aData->SetLineContainer(savedLineContainer);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
|
|
|
|
// This goes at the end no matter how things are broken and how
|
|
|
|
// messy the bidi situations are, since per CSS2.1 section 8.6
|
|
|
|
// (implemented in bug 328168), the endSide border is always on the
|
|
|
|
// last line.
|
2008-03-12 00:54:34 +03:00
|
|
|
// We reached the last-in-flow, but it might have a next bidi
|
2010-04-27 20:15:01 +04:00
|
|
|
// continuation, in which case that continuation should handle
|
2008-03-12 00:54:34 +03:00
|
|
|
// the endSide border.
|
2014-05-05 21:55:54 +04:00
|
|
|
if (MOZ_LIKELY(!lastInFlow->GetNextContinuation() && sliceBreak)) {
|
2016-04-14 02:32:12 +03:00
|
|
|
aData->mCurrentLine += endPBM;
|
2008-03-12 00:54:34 +03:00
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
|
2014-08-24 18:34:51 +04:00
|
|
|
/* virtual */
|
|
|
|
LogicalSize
|
2017-06-09 22:14:53 +03:00
|
|
|
nsContainerFrame::ComputeAutoSize(gfxContext* aRenderingContext,
|
2016-11-05 04:57:06 +03:00
|
|
|
WritingMode aWM,
|
|
|
|
const LogicalSize& aCBSize,
|
|
|
|
nscoord aAvailableISize,
|
|
|
|
const LogicalSize& aMargin,
|
|
|
|
const LogicalSize& aBorder,
|
|
|
|
const LogicalSize& aPadding,
|
|
|
|
ComputeSizeFlags aFlags)
|
2014-08-24 18:34:51 +04:00
|
|
|
{
|
|
|
|
LogicalSize result(aWM, 0xdeadbeef, NS_UNCONSTRAINEDSIZE);
|
|
|
|
nscoord availBased = aAvailableISize - aMargin.ISize(aWM) -
|
|
|
|
aBorder.ISize(aWM) - aPadding.ISize(aWM);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
// replaced elements always shrink-wrap
|
2016-11-05 04:57:06 +03:00
|
|
|
if ((aFlags & ComputeSizeFlags::eShrinkWrap) || IsFrameOfType(eReplaced)) {
|
Bug 1105111 part 3: Add support for 'flex-basis:content' in layout. r=mats
BACKGROUND:
Early in flex layout, we have to resolve the 'flex-basis' value to produce the
"flex base size" (basically, the flex-basis resolved to an absolute length).
This resolution happens in two "phases" (which both happen within
nsFlexContainer::GenerateFlexItemForChild()):
First phase: we try to resolve the flex-basis by creating a ReflowInput for the
flex item (which gets us some other things as well). Under the hood, we use
the flex-basis when resolving this ReflowInput's main-axis size. The code for
this lives in nsFrame::ComputeSize (and in
nsFrame::ComputeSizeWithIntrinsicDimensions, via some frame classes' overrides of
ComputeSize).
Second phase: If the first phase didn't get us a definite size, then that means
we have to do reflow to measure the content size & produce a resolved flex base
size, which we do via ResolveAutoFlexBasisAndMinSize().
NOTES ON THIS PATCH:
To add 'flex-basis:content' support to layout, this patch only needs to modify
the first phase discussed above. If it turns out we also have some second-phase
work to do (i.e. if we need to do reflow to resolve 'flex-basis:content'), this
patch causes that reflow to happen by simply making us use eStyleUnit_Auto in
the main axis's nsStyleCoord in the first phase. (And then, if that 'auto'
nsStyleCoord really does require reflow, then that first phase will end up
producing an unconstrained main-size in the flex item's ReflowInput, which will
automatically trigger the second phase.)
MozReview-Commit-ID: 2nH4Fh78C81
2018-03-31 02:50:49 +03:00
|
|
|
// Only bother computing our 'auto' ISize if the result will be used.
|
|
|
|
// It'll be used under two scenarios:
|
|
|
|
// - If our ISize property is itself 'auto'.
|
|
|
|
// - If we're using flex-basis in place of our ISize property (i.e. we're a
|
|
|
|
// flex item with our inline axis being the main axis), AND we have
|
|
|
|
// flex-basis:content.
|
|
|
|
const nsStylePosition* pos = StylePosition();
|
|
|
|
if (pos->ISize(aWM).GetUnit() == eStyleUnit_Auto ||
|
|
|
|
(pos->mFlexBasis.GetUnit() == eStyleUnit_Enumerated &&
|
|
|
|
pos->mFlexBasis.GetIntValue() == NS_STYLE_FLEX_BASIS_CONTENT &&
|
|
|
|
IsFlexItem() &&
|
|
|
|
nsFlexContainerFrame::IsItemInlineAxisMainAxis(this))) {
|
2016-11-05 04:57:06 +03:00
|
|
|
result.ISize(aWM) = ShrinkWidthToFit(aRenderingContext, availBased, aFlags);
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
|
|
|
} else {
|
2014-08-24 18:34:51 +04:00
|
|
|
result.ISize(aWM) = availBased;
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
}
|
2014-12-26 10:21:32 +03:00
|
|
|
|
|
|
|
if (IsTableCaption()) {
|
|
|
|
// If we're a container for font size inflation, then shrink
|
|
|
|
// wrapping inside of us should not apply font size inflation.
|
|
|
|
AutoMaybeDisableFontInflation an(this);
|
|
|
|
|
2015-07-03 13:37:33 +03:00
|
|
|
WritingMode tableWM = GetParent()->GetWritingMode();
|
2015-09-16 00:02:30 +03:00
|
|
|
uint8_t captionSide = StyleTableBorder()->mCaptionSide;
|
2015-07-03 13:37:33 +03:00
|
|
|
|
|
|
|
if (aWM.IsOrthogonalTo(tableWM)) {
|
2015-09-16 00:02:30 +03:00
|
|
|
if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
|
|
|
|
captionSide == NS_STYLE_CAPTION_SIDE_TOP_OUTSIDE ||
|
|
|
|
captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM ||
|
|
|
|
captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM_OUTSIDE) {
|
2015-07-03 13:37:33 +03:00
|
|
|
// For an orthogonal caption on a block-dir side of the table,
|
|
|
|
// shrink-wrap to min-isize.
|
|
|
|
result.ISize(aWM) = GetMinISize(aRenderingContext);
|
|
|
|
} else {
|
|
|
|
// An orthogonal caption on an inline-dir side of the table
|
|
|
|
// is constrained to the containing block.
|
|
|
|
nscoord pref = GetPrefISize(aRenderingContext);
|
|
|
|
if (pref > aCBSize.ISize(aWM)) {
|
|
|
|
pref = aCBSize.ISize(aWM);
|
|
|
|
}
|
|
|
|
if (pref < result.ISize(aWM)) {
|
|
|
|
result.ISize(aWM) = pref;
|
|
|
|
}
|
2014-12-26 10:21:32 +03:00
|
|
|
}
|
2015-07-03 13:37:33 +03:00
|
|
|
} else {
|
2015-09-16 00:02:30 +03:00
|
|
|
if (captionSide == NS_STYLE_CAPTION_SIDE_LEFT ||
|
|
|
|
captionSide == NS_STYLE_CAPTION_SIDE_RIGHT) {
|
2015-07-03 13:37:33 +03:00
|
|
|
result.ISize(aWM) = GetMinISize(aRenderingContext);
|
2015-09-16 00:02:30 +03:00
|
|
|
} else if (captionSide == NS_STYLE_CAPTION_SIDE_TOP ||
|
|
|
|
captionSide == NS_STYLE_CAPTION_SIDE_BOTTOM) {
|
2015-07-03 13:37:33 +03:00
|
|
|
// The outer frame constrains our available isize to the isize of
|
|
|
|
// the table. Grow if our min-isize is bigger than that, but not
|
|
|
|
// larger than the containing block isize. (It would really be nice
|
|
|
|
// to transmit that information another way, so we could grow up to
|
|
|
|
// the table's available isize, but that's harder.)
|
|
|
|
nscoord min = GetMinISize(aRenderingContext);
|
|
|
|
if (min > aCBSize.ISize(aWM)) {
|
|
|
|
min = aCBSize.ISize(aWM);
|
|
|
|
}
|
|
|
|
if (min > result.ISize(aWM)) {
|
|
|
|
result.ISize(aWM) = min;
|
|
|
|
}
|
2014-12-26 10:21:32 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Bug 300030: Move intrinsic width computation out of nsIFrame::Reflow and into its own methods on nsIFrame. Replace reflow reasons, types, and commands with dirty bits/notifications. Thanks to bzbarsky for almost all of the HTML form controls (mozilla/layout/forms) changes, and many others for help testing and patching. For detailed commit logs, see REFLOW_YYYYMMDD_BRANCH, where YYYYMMDD is one of 20061031, 20060830, 20060603, 20060302, 20060119, 20051011, 20050804, 20050429, 20050315, 20050111, and 20041213.
2006-12-08 08:38:33 +03:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2014-05-13 04:47:53 +04:00
|
|
|
void
|
2015-01-07 10:10:07 +03:00
|
|
|
nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
|
|
|
nsPresContext* aPresContext,
|
2017-04-18 23:35:05 +03:00
|
|
|
ReflowOutput& aDesiredSize,
|
|
|
|
const ReflowInput& aReflowInput,
|
2015-01-07 10:10:07 +03:00
|
|
|
const WritingMode& aWM,
|
|
|
|
const LogicalPoint& aPos,
|
2015-07-16 12:07:57 +03:00
|
|
|
const nsSize& aContainerSize,
|
2015-01-07 10:10:07 +03:00
|
|
|
uint32_t aFlags,
|
|
|
|
nsReflowStatus& aStatus,
|
|
|
|
nsOverflowContinuationTracker* aTracker)
|
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aReflowInput.mFrame == aKidFrame, "bad reflow state");
|
2015-01-07 10:10:07 +03:00
|
|
|
if (aWM.IsVerticalRL() || (!aWM.IsVertical() && !aWM.IsBidiLTR())) {
|
2015-07-16 12:07:57 +03:00
|
|
|
NS_ASSERTION(aContainerSize.width != NS_UNCONSTRAINEDSIZE,
|
2015-04-10 18:56:23 +03:00
|
|
|
"ReflowChild with unconstrained container width!");
|
2015-01-07 10:10:07 +03:00
|
|
|
}
|
2017-04-18 23:35:05 +03:00
|
|
|
MOZ_ASSERT(aDesiredSize.VisualOverflow() == nsRect(0,0,0,0) &&
|
|
|
|
aDesiredSize.ScrollableOverflow() == nsRect(0,0,0,0),
|
|
|
|
"please reset the overflow areas before calling ReflowChild");
|
2015-01-07 10:10:07 +03:00
|
|
|
|
2015-03-30 01:38:40 +03:00
|
|
|
// Position the child frame and its view if requested.
|
2015-01-07 10:10:07 +03:00
|
|
|
if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
|
2015-07-16 12:07:57 +03:00
|
|
|
aKidFrame->SetPosition(aWM, aPos, aContainerSize);
|
2015-01-07 10:10:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
|
|
|
|
PositionFrameView(aKidFrame);
|
2016-12-20 22:49:32 +03:00
|
|
|
PositionChildViews(aKidFrame);
|
2015-01-07 10:10:07 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reflow the child frame
|
2016-07-21 13:36:39 +03:00
|
|
|
aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
|
2015-01-07 10:10:07 +03:00
|
|
|
|
|
|
|
// If the child frame is complete, delete any next-in-flows,
|
|
|
|
// but only if the NO_DELETE_NEXT_IN_FLOW flag isn't set.
|
2017-02-14 11:05:24 +03:00
|
|
|
if (!aStatus.IsInlineBreakBefore() &&
|
2017-02-11 17:38:48 +03:00
|
|
|
aStatus.IsFullyComplete() &&
|
2015-01-07 10:10:07 +03:00
|
|
|
!(aFlags & NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD)) {
|
|
|
|
nsIFrame* kidNextInFlow = aKidFrame->GetNextInFlow();
|
|
|
|
if (kidNextInFlow) {
|
|
|
|
// Remove all of the childs next-in-flows. Make sure that we ask
|
|
|
|
// the right parent to do the removal (it's possible that the
|
|
|
|
// parent is not this because we are executing pullup code)
|
|
|
|
nsOverflowContinuationTracker::AutoFinish fini(aTracker, aKidFrame);
|
|
|
|
kidNextInFlow->GetParent()->DeleteNextInFlowChild(kidNextInFlow, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//XXX temporary: hold on to a copy of the old physical version of
|
|
|
|
// ReflowChild so that we can convert callers incrementally.
|
|
|
|
void
|
1998-10-06 04:27:22 +04:00
|
|
|
nsContainerFrame::ReflowChild(nsIFrame* aKidFrame,
|
2005-04-29 01:57:22 +04:00
|
|
|
nsPresContext* aPresContext,
|
2016-07-21 13:36:38 +03:00
|
|
|
ReflowOutput& aDesiredSize,
|
2016-07-21 13:36:39 +03:00
|
|
|
const ReflowInput& aReflowInput,
|
1999-11-19 18:33:29 +03:00
|
|
|
nscoord aX,
|
|
|
|
nscoord aY,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags,
|
2007-07-26 08:03:29 +04:00
|
|
|
nsReflowStatus& aStatus,
|
|
|
|
nsOverflowContinuationTracker* aTracker)
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aReflowInput.mFrame == aKidFrame, "bad reflow state");
|
1998-10-01 01:35:29 +04:00
|
|
|
|
2015-03-30 01:38:40 +03:00
|
|
|
// Position the child frame and its view if requested.
|
2008-09-06 12:52:56 +04:00
|
|
|
if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
|
2003-06-26 15:30:17 +04:00
|
|
|
aKidFrame->SetPosition(nsPoint(aX, aY));
|
1999-11-19 18:33:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (0 == (aFlags & NS_FRAME_NO_MOVE_VIEW)) {
|
2004-12-27 18:05:18 +03:00
|
|
|
PositionFrameView(aKidFrame);
|
2016-12-20 22:49:32 +03:00
|
|
|
PositionChildViews(aKidFrame);
|
1999-11-19 18:33:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// Reflow the child frame
|
2016-07-21 13:36:39 +03:00
|
|
|
aKidFrame->Reflow(aPresContext, aDesiredSize, aReflowInput, aStatus);
|
1998-10-06 04:27:22 +04:00
|
|
|
|
2014-05-13 04:47:52 +04:00
|
|
|
// If the child frame is complete, delete any next-in-flows,
|
|
|
|
// but only if the NO_DELETE_NEXT_IN_FLOW flag isn't set.
|
2017-02-11 17:38:48 +03:00
|
|
|
if (aStatus.IsFullyComplete() &&
|
2013-03-15 22:36:30 +04:00
|
|
|
!(aFlags & NS_FRAME_NO_DELETE_NEXT_IN_FLOW_CHILD)) {
|
2004-09-14 06:28:03 +04:00
|
|
|
nsIFrame* kidNextInFlow = aKidFrame->GetNextInFlow();
|
2013-06-10 22:31:59 +04:00
|
|
|
if (kidNextInFlow) {
|
1998-10-01 01:35:29 +04:00
|
|
|
// Remove all of the childs next-in-flows. Make sure that we ask
|
|
|
|
// the right parent to do the removal (it's possible that the
|
|
|
|
// parent is not this because we are executing pullup code)
|
2013-06-10 22:31:59 +04:00
|
|
|
nsOverflowContinuationTracker::AutoFinish fini(aTracker, aKidFrame);
|
2014-05-25 02:20:40 +04:00
|
|
|
kidNextInFlow->GetParent()->DeleteNextInFlowChild(kidNextInFlow, true);
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2001-03-12 07:19:10 +03:00
|
|
|
|
2001-09-21 04:53:29 +04:00
|
|
|
/**
|
|
|
|
* Position the views of |aFrame|'s descendants. A container frame
|
|
|
|
* should call this method if it moves a frame after |Reflow|.
|
|
|
|
*/
|
1999-11-19 18:33:29 +03:00
|
|
|
void
|
2004-12-27 18:05:18 +03:00
|
|
|
nsContainerFrame::PositionChildViews(nsIFrame* aFrame)
|
1999-11-19 18:33:29 +03:00
|
|
|
{
|
2003-06-26 15:30:17 +04:00
|
|
|
if (!(aFrame->GetStateBits() & NS_FRAME_HAS_CHILD_WITH_VIEW)) {
|
2001-03-12 07:19:10 +03:00
|
|
|
return;
|
|
|
|
}
|
1999-11-19 18:33:29 +03:00
|
|
|
|
2011-08-25 00:54:29 +04:00
|
|
|
// Recursively walk aFrame's child frames.
|
|
|
|
// Process the additional child lists, but skip the popup list as the
|
|
|
|
// view for popups is managed by the parent. Currently only nsMenuFrame
|
2013-11-04 20:22:20 +04:00
|
|
|
// and nsPopupSetFrame have a popupList and during layout will adjust the
|
|
|
|
// view manually to position the popup.
|
2011-08-25 00:54:29 +04:00
|
|
|
ChildListIterator lists(aFrame);
|
|
|
|
for (; !lists.IsDone(); lists.Next()) {
|
|
|
|
if (lists.CurrentID() == kPopupList) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
|
|
|
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
2004-01-10 08:36:32 +03:00
|
|
|
// Position the frame's view (if it has one) otherwise recursively
|
2001-09-21 04:53:29 +04:00
|
|
|
// process its children
|
2011-08-25 00:54:29 +04:00
|
|
|
nsIFrame* childFrame = childFrames.get();
|
2004-01-10 08:36:32 +03:00
|
|
|
if (childFrame->HasView()) {
|
2004-12-27 18:05:18 +03:00
|
|
|
PositionFrameView(childFrame);
|
2004-01-10 08:36:32 +03:00
|
|
|
} else {
|
2004-12-27 18:05:18 +03:00
|
|
|
PositionChildViews(childFrame);
|
2004-01-10 08:36:32 +03:00
|
|
|
}
|
1999-11-19 18:33:29 +03:00
|
|
|
}
|
2011-08-25 00:54:29 +04:00
|
|
|
}
|
1999-11-19 18:33:29 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* The second half of frame reflow. Does the following:
|
|
|
|
* - sets the frame's bounds
|
|
|
|
* - sizes and positions (if requested) the frame's view. If the frame's final
|
|
|
|
* position differs from the current position and the frame itself does not
|
|
|
|
* have a view, then any child frames with views are positioned so they stay
|
|
|
|
* in sync
|
|
|
|
* - sets the view's visibility, opacity, content transparency, and clip
|
|
|
|
* - invoked the DidReflow() function
|
|
|
|
*
|
|
|
|
* Flags:
|
|
|
|
* NS_FRAME_NO_MOVE_FRAME - don't move the frame. aX and aY are ignored in this
|
|
|
|
* case. Also implies NS_FRAME_NO_MOVE_VIEW
|
|
|
|
* NS_FRAME_NO_MOVE_VIEW - don't position the frame's view. Set this if you
|
|
|
|
* don't want to automatically sync the frame and view
|
|
|
|
* NS_FRAME_NO_SIZE_VIEW - don't size the frame's view
|
2001-09-06 00:27:19 +04:00
|
|
|
*/
|
2018-03-06 18:15:34 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* De-optimize function to work around a VC2017 15.5+ compiler bug:
|
|
|
|
* https://bugzil.la/1424281#c12
|
|
|
|
*/
|
|
|
|
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_AMD64)
|
|
|
|
#pragma optimize("g", off)
|
|
|
|
#endif
|
2014-05-13 04:47:53 +04:00
|
|
|
void
|
2015-01-07 10:10:07 +03:00
|
|
|
nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame,
|
|
|
|
nsPresContext* aPresContext,
|
2016-07-21 13:36:38 +03:00
|
|
|
const ReflowOutput& aDesiredSize,
|
2016-07-21 13:36:39 +03:00
|
|
|
const ReflowInput* aReflowInput,
|
2015-01-07 10:10:07 +03:00
|
|
|
const WritingMode& aWM,
|
|
|
|
const LogicalPoint& aPos,
|
2015-07-16 12:07:57 +03:00
|
|
|
const nsSize& aContainerSize,
|
2015-01-07 10:10:07 +03:00
|
|
|
uint32_t aFlags)
|
|
|
|
{
|
|
|
|
if (aWM.IsVerticalRL() || (!aWM.IsVertical() && !aWM.IsBidiLTR())) {
|
2015-07-16 12:07:57 +03:00
|
|
|
NS_ASSERTION(aContainerSize.width != NS_UNCONSTRAINEDSIZE,
|
2015-01-07 10:10:07 +03:00
|
|
|
"FinishReflowChild with unconstrained container width!");
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPoint curOrigin = aKidFrame->GetPosition();
|
|
|
|
WritingMode outerWM = aDesiredSize.GetWritingMode();
|
|
|
|
LogicalSize convertedSize = aDesiredSize.Size(outerWM).ConvertTo(aWM,
|
|
|
|
outerWM);
|
|
|
|
|
|
|
|
if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
|
|
|
|
aKidFrame->SetRect(aWM, LogicalRect(aWM, aPos, convertedSize),
|
2015-07-16 12:07:57 +03:00
|
|
|
aContainerSize);
|
2015-01-07 10:10:07 +03:00
|
|
|
} else {
|
|
|
|
aKidFrame->SetSize(aWM, convertedSize);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (aKidFrame->HasView()) {
|
|
|
|
nsView* view = aKidFrame->GetView();
|
|
|
|
// Make sure the frame's view is properly sized and positioned and has
|
|
|
|
// things like opacity correct
|
|
|
|
SyncFrameViewAfterReflow(aPresContext, aKidFrame, view,
|
|
|
|
aDesiredSize.VisualOverflow(), aFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
nsPoint newOrigin = aKidFrame->GetPosition();
|
|
|
|
if (!(aFlags & NS_FRAME_NO_MOVE_VIEW) && curOrigin != newOrigin) {
|
|
|
|
if (!aKidFrame->HasView()) {
|
|
|
|
// If the frame has moved, then we need to make sure any child views are
|
|
|
|
// correctly positioned
|
|
|
|
PositionChildViews(aKidFrame);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-14 18:21:49 +03:00
|
|
|
aKidFrame->DidReflow(aPresContext, aReflowInput);
|
2015-01-07 10:10:07 +03:00
|
|
|
}
|
2018-03-06 18:15:34 +03:00
|
|
|
#if defined(_MSC_VER) && !defined(__clang__) && defined(_M_AMD64)
|
|
|
|
#pragma optimize("", on)
|
|
|
|
#endif
|
2015-01-07 10:10:07 +03:00
|
|
|
|
|
|
|
//XXX temporary: hold on to a copy of the old physical version of
|
|
|
|
// FinishReflowChild so that we can convert callers incrementally.
|
|
|
|
void
|
2008-01-03 07:33:21 +03:00
|
|
|
nsContainerFrame::FinishReflowChild(nsIFrame* aKidFrame,
|
|
|
|
nsPresContext* aPresContext,
|
2016-07-21 13:36:38 +03:00
|
|
|
const ReflowOutput& aDesiredSize,
|
2016-07-21 13:36:39 +03:00
|
|
|
const ReflowInput* aReflowInput,
|
2008-01-03 07:33:21 +03:00
|
|
|
nscoord aX,
|
|
|
|
nscoord aY,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags)
|
1999-11-19 18:33:29 +03:00
|
|
|
{
|
2003-06-26 15:30:17 +04:00
|
|
|
nsPoint curOrigin = aKidFrame->GetPosition();
|
1999-11-19 18:33:29 +03:00
|
|
|
|
2013-05-23 09:37:05 +04:00
|
|
|
if (NS_FRAME_NO_MOVE_FRAME != (aFlags & NS_FRAME_NO_MOVE_FRAME)) {
|
2013-12-27 21:59:52 +04:00
|
|
|
aKidFrame->SetRect(nsRect(aX, aY, aDesiredSize.Width(), aDesiredSize.Height()));
|
2013-05-23 09:37:05 +04:00
|
|
|
} else {
|
2013-12-27 21:59:52 +04:00
|
|
|
aKidFrame->SetSize(nsSize(aDesiredSize.Width(), aDesiredSize.Height()));
|
2013-05-23 09:37:05 +04:00
|
|
|
}
|
1999-11-19 18:33:29 +03:00
|
|
|
|
2003-06-20 03:44:01 +04:00
|
|
|
if (aKidFrame->HasView()) {
|
2013-01-03 17:23:11 +04:00
|
|
|
nsView* view = aKidFrame->GetView();
|
1999-11-19 18:33:29 +03:00
|
|
|
// Make sure the frame's view is properly sized and positioned and has
|
|
|
|
// things like opacity correct
|
1999-11-24 09:03:41 +03:00
|
|
|
SyncFrameViewAfterReflow(aPresContext, aKidFrame, view,
|
2010-10-07 08:25:46 +04:00
|
|
|
aDesiredSize.VisualOverflow(), aFlags);
|
2001-09-06 00:27:19 +04:00
|
|
|
}
|
2004-02-22 06:31:30 +03:00
|
|
|
|
|
|
|
if (!(aFlags & NS_FRAME_NO_MOVE_VIEW) &&
|
|
|
|
(curOrigin.x != aX || curOrigin.y != aY)) {
|
|
|
|
if (!aKidFrame->HasView()) {
|
|
|
|
// If the frame has moved, then we need to make sure any child views are
|
|
|
|
// correctly positioned
|
2004-12-27 18:05:18 +03:00
|
|
|
PositionChildViews(aKidFrame);
|
2004-02-22 06:31:30 +03:00
|
|
|
}
|
1999-11-19 18:33:29 +03:00
|
|
|
}
|
2010-04-27 20:15:01 +04:00
|
|
|
|
2017-12-14 18:21:49 +03:00
|
|
|
aKidFrame->DidReflow(aPresContext, aReflowInput);
|
1999-11-19 18:33:29 +03:00
|
|
|
}
|
|
|
|
|
2014-05-13 04:47:53 +04:00
|
|
|
void
|
2007-07-26 08:03:29 +04:00
|
|
|
nsContainerFrame::ReflowOverflowContainerChildren(nsPresContext* aPresContext,
|
2016-07-21 13:36:39 +03:00
|
|
|
const ReflowInput& aReflowInput,
|
2010-10-07 08:25:45 +04:00
|
|
|
nsOverflowAreas& aOverflowRects,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aFlags,
|
2016-03-11 19:39:27 +03:00
|
|
|
nsReflowStatus& aStatus,
|
|
|
|
ChildFrameMerger aMergeFunc)
|
2007-07-26 08:03:29 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aPresContext, "null pointer");
|
2007-07-26 08:03:29 +04:00
|
|
|
|
2016-03-11 19:39:27 +03:00
|
|
|
nsFrameList* overflowContainers = DrainExcessOverflowContainersList(aMergeFunc);
|
2013-03-26 00:27:05 +04:00
|
|
|
if (!overflowContainers) {
|
2014-05-13 04:47:53 +04:00
|
|
|
return; // nothing to reflow
|
2013-03-26 00:27:05 +04:00
|
|
|
}
|
2007-07-26 08:03:29 +04:00
|
|
|
|
2014-02-07 02:07:47 +04:00
|
|
|
nsOverflowContinuationTracker tracker(this, false, false);
|
2016-07-21 13:36:39 +03:00
|
|
|
bool shouldReflowAllKids = aReflowInput.ShouldReflowAllKids();
|
2010-05-19 07:04:33 +04:00
|
|
|
|
2015-06-29 23:02:21 +03:00
|
|
|
for (nsIFrame* frame : *overflowContainers) {
|
2009-05-09 05:53:44 +04:00
|
|
|
if (frame->GetPrevInFlow()->GetParent() != GetPrevInFlow()) {
|
|
|
|
// frame's prevInFlow has moved, skip reflowing this frame;
|
|
|
|
// it will get reflowed once it's been placed
|
2018-01-23 02:00:03 +03:00
|
|
|
if (GetNextInFlow()) {
|
|
|
|
// We report OverflowIncomplete status in this case to avoid our parent
|
|
|
|
// deleting our next-in-flows which might destroy non-empty frames.
|
|
|
|
nsReflowStatus status;
|
|
|
|
status.SetOverflowIncomplete();
|
|
|
|
aStatus.MergeCompletionStatusFrom(status);
|
|
|
|
}
|
2009-05-09 05:53:44 +04:00
|
|
|
continue;
|
|
|
|
}
|
2010-05-19 07:04:33 +04:00
|
|
|
// If the available vertical height has changed, we need to reflow
|
|
|
|
// even if the frame isn't dirty.
|
|
|
|
if (shouldReflowAllKids || NS_SUBTREE_DIRTY(frame)) {
|
2007-07-26 08:03:29 +04:00
|
|
|
// Get prev-in-flow
|
|
|
|
nsIFrame* prevInFlow = frame->GetPrevInFlow();
|
|
|
|
NS_ASSERTION(prevInFlow,
|
|
|
|
"overflow container frame must have a prev-in-flow");
|
|
|
|
NS_ASSERTION(frame->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER,
|
|
|
|
"overflow container frame must have overflow container bit set");
|
2015-01-07 10:10:07 +03:00
|
|
|
WritingMode wm = frame->GetWritingMode();
|
2016-07-21 13:36:39 +03:00
|
|
|
nsSize containerSize = aReflowInput.AvailableSize(wm).GetPhysicalSize(wm);
|
2015-07-16 12:07:57 +03:00
|
|
|
LogicalRect prevRect = prevInFlow->GetLogicalRect(wm, containerSize);
|
2007-07-26 08:03:29 +04:00
|
|
|
|
|
|
|
// Initialize reflow params
|
2015-01-07 10:10:07 +03:00
|
|
|
LogicalSize availSpace(wm, prevRect.ISize(wm),
|
2016-07-21 13:36:39 +03:00
|
|
|
aReflowInput.AvailableSize(wm).BSize(wm));
|
|
|
|
ReflowOutput desiredSize(aReflowInput);
|
|
|
|
ReflowInput frameState(aPresContext, aReflowInput,
|
2007-07-26 08:03:29 +04:00
|
|
|
frame, availSpace);
|
2013-02-24 04:06:55 +04:00
|
|
|
nsReflowStatus frameStatus;
|
2007-07-26 08:03:29 +04:00
|
|
|
|
|
|
|
// Reflow
|
2015-01-07 10:10:07 +03:00
|
|
|
LogicalPoint pos(wm, prevRect.IStart(wm), 0);
|
2014-05-13 04:47:53 +04:00
|
|
|
ReflowChild(frame, aPresContext, desiredSize, frameState,
|
2015-07-16 12:07:57 +03:00
|
|
|
wm, pos, containerSize, aFlags, frameStatus, &tracker);
|
2007-07-26 08:03:29 +04:00
|
|
|
//XXXfr Do we need to override any shrinkwrap effects here?
|
2013-12-27 21:59:52 +04:00
|
|
|
// e.g. desiredSize.Width() = prevRect.width;
|
2014-05-13 04:47:53 +04:00
|
|
|
FinishReflowChild(frame, aPresContext, desiredSize, &frameState,
|
2015-07-16 12:07:57 +03:00
|
|
|
wm, pos, containerSize, aFlags);
|
2007-07-26 08:03:29 +04:00
|
|
|
|
|
|
|
// Handle continuations
|
2017-02-11 17:38:48 +03:00
|
|
|
if (!frameStatus.IsFullyComplete()) {
|
2007-10-02 09:57:45 +04:00
|
|
|
if (frame->GetStateBits() & NS_FRAME_OUT_OF_FLOW) {
|
|
|
|
// Abspos frames can't cause their parent to be incomplete,
|
|
|
|
// only overflow incomplete.
|
2017-02-11 18:18:04 +03:00
|
|
|
frameStatus.SetOverflowIncomplete();
|
2007-10-02 09:57:45 +04:00
|
|
|
}
|
|
|
|
else {
|
2017-02-11 17:45:07 +03:00
|
|
|
NS_ASSERTION(frameStatus.IsComplete(),
|
2007-10-02 09:57:45 +04:00
|
|
|
"overflow container frames can't be incomplete, only overflow-incomplete");
|
|
|
|
}
|
|
|
|
|
2007-07-26 08:03:29 +04:00
|
|
|
// Acquire a next-in-flow, creating it if necessary
|
|
|
|
nsIFrame* nif = frame->GetNextInFlow();
|
|
|
|
if (!nif) {
|
2017-02-13 09:56:45 +03:00
|
|
|
NS_ASSERTION(frameStatus.NextInFlowNeedsReflow(),
|
|
|
|
"Someone forgot a NextInFlowNeedsReflow flag");
|
2013-03-20 05:47:49 +04:00
|
|
|
nif = aPresContext->PresShell()->FrameConstructor()->
|
|
|
|
CreateContinuingFrame(aPresContext, frame, this);
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
else if (!(nif->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
|
|
|
|
// used to be a normal next-in-flow; steal it from the child list
|
2014-05-25 02:20:40 +04:00
|
|
|
nsresult rv = nif->GetParent()->StealFrame(nif);
|
2014-05-13 04:47:53 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return;
|
|
|
|
}
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
tracker.Insert(nif, frameStatus);
|
|
|
|
}
|
2017-02-13 12:15:01 +03:00
|
|
|
aStatus.MergeCompletionStatusFrom(frameStatus);
|
2007-07-26 08:03:29 +04:00
|
|
|
// At this point it would be nice to assert !frame->GetOverflowRect().IsEmpty(),
|
|
|
|
// but we have some unsplittable frames that, when taller than
|
|
|
|
// availableHeight will push zero-height content into a next-in-flow.
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
tracker.Skip(frame, aStatus);
|
2016-07-21 13:36:39 +03:00
|
|
|
if (aReflowInput.mFloatManager) {
|
|
|
|
nsBlockFrame::RecoverFloatsFor(frame, *aReflowInput.mFloatManager,
|
|
|
|
aReflowInput.GetWritingMode(),
|
|
|
|
aReflowInput.ComputedPhysicalSize());
|
2014-10-22 02:16:12 +04:00
|
|
|
}
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
2010-10-07 08:25:45 +04:00
|
|
|
ConsiderChildOverflow(aOverflowRects, frame);
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsContainerFrame::DisplayOverflowContainers(nsDisplayListBuilder* aBuilder,
|
|
|
|
const nsDisplayListSet& aLists)
|
|
|
|
{
|
2014-02-07 02:07:47 +04:00
|
|
|
nsFrameList* overflowconts = GetPropTableFrames(OverflowContainersProperty());
|
2007-07-26 08:03:29 +04:00
|
|
|
if (overflowconts) {
|
2015-06-29 23:02:21 +03:00
|
|
|
for (nsIFrame* frame : *overflowconts) {
|
2017-08-07 05:23:35 +03:00
|
|
|
BuildDisplayListForChild(aBuilder, frame, aLists);
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-02-28 03:05:44 +04:00
|
|
|
static bool
|
2017-05-27 14:36:00 +03:00
|
|
|
TryRemoveFrame(nsIFrame* aFrame,
|
2016-01-28 06:23:59 +03:00
|
|
|
nsContainerFrame::FrameListPropertyDescriptor aProp,
|
|
|
|
nsIFrame* aChildToRemove)
|
2013-02-28 03:05:44 +04:00
|
|
|
{
|
2017-05-27 14:36:00 +03:00
|
|
|
nsFrameList* list = aFrame->GetProperty(aProp);
|
2013-03-16 02:32:35 +04:00
|
|
|
if (list && list->StartRemoveFrame(aChildToRemove)) {
|
2013-02-28 03:05:44 +04:00
|
|
|
// aChildToRemove *may* have been removed from this list.
|
|
|
|
if (list->IsEmpty()) {
|
2017-05-27 14:36:00 +03:00
|
|
|
aFrame->RemoveProperty(aProp);
|
2017-11-09 05:00:48 +03:00
|
|
|
list->Delete(aFrame->PresShell());
|
2013-02-28 03:05:44 +04:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-06-10 03:56:23 +03:00
|
|
|
bool
|
|
|
|
nsContainerFrame::MaybeStealOverflowContainerFrame(nsIFrame* aChild)
|
|
|
|
{
|
|
|
|
bool removed = false;
|
|
|
|
if (MOZ_UNLIKELY(aChild->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
|
|
|
|
// Try removing from the overflow container list.
|
2017-05-27 14:36:00 +03:00
|
|
|
removed = ::TryRemoveFrame(this, OverflowContainersProperty(),
|
2016-06-10 03:56:23 +03:00
|
|
|
aChild);
|
|
|
|
if (!removed) {
|
|
|
|
// It might be in the excess overflow container list.
|
2017-05-27 14:36:00 +03:00
|
|
|
removed = ::TryRemoveFrame(this,
|
2016-06-10 03:56:23 +03:00
|
|
|
ExcessOverflowContainersProperty(),
|
|
|
|
aChild);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return removed;
|
|
|
|
}
|
|
|
|
|
2007-07-26 08:03:29 +04:00
|
|
|
nsresult
|
2016-06-10 03:56:23 +03:00
|
|
|
nsContainerFrame::StealFrame(nsIFrame* aChild)
|
2007-07-26 08:03:29 +04:00
|
|
|
{
|
2013-02-28 03:05:44 +04:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (!mFrames.ContainsFrame(aChild)) {
|
2013-03-16 02:32:35 +04:00
|
|
|
nsFrameList* list = GetOverflowFrames();
|
2013-02-28 03:05:44 +04:00
|
|
|
if (!list || !list->ContainsFrame(aChild)) {
|
2017-05-27 14:36:00 +03:00
|
|
|
list = GetProperty(OverflowContainersProperty());
|
2013-03-16 02:32:35 +04:00
|
|
|
if (!list || !list->ContainsFrame(aChild)) {
|
2017-05-27 14:36:00 +03:00
|
|
|
list = GetProperty(ExcessOverflowContainersProperty());
|
2013-03-16 02:32:35 +04:00
|
|
|
MOZ_ASSERT(list && list->ContainsFrame(aChild), "aChild isn't our child"
|
|
|
|
" or on a frame list not supported by StealFrame");
|
|
|
|
}
|
2013-02-28 03:05:44 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2016-06-10 03:56:23 +03:00
|
|
|
bool removed = MaybeStealOverflowContainerFrame(aChild);
|
|
|
|
if (!removed) {
|
|
|
|
// NOTE nsColumnSetFrame and nsCanvasFrame have their overflow containers
|
|
|
|
// on the normal lists so we might get here also if the frame bit
|
|
|
|
// NS_FRAME_IS_OVERFLOW_CONTAINER is set.
|
2013-02-28 03:05:44 +04:00
|
|
|
removed = mFrames.StartRemoveFrame(aChild);
|
|
|
|
if (!removed) {
|
|
|
|
// We didn't find the child in our principal child list.
|
2007-07-26 08:03:29 +04:00
|
|
|
// Maybe it's on the overflow list?
|
2009-07-28 16:51:09 +04:00
|
|
|
nsFrameList* frameList = GetOverflowFrames();
|
|
|
|
if (frameList) {
|
2013-02-28 03:05:44 +04:00
|
|
|
removed = frameList->ContinueRemoveFrame(aChild);
|
2009-07-28 16:51:09 +04:00
|
|
|
if (frameList->IsEmpty()) {
|
2014-02-07 02:07:47 +04:00
|
|
|
DestroyOverflowList();
|
2009-07-28 16:51:09 +04:00
|
|
|
}
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-09-18 15:09:36 +04:00
|
|
|
|
2017-11-05 08:48:48 +03:00
|
|
|
MOZ_ASSERT(removed, "StealFrame: can't find aChild");
|
2009-09-18 15:09:36 +04:00
|
|
|
return removed ? NS_OK : NS_ERROR_UNEXPECTED;
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
|
2009-09-18 15:09:35 +04:00
|
|
|
nsFrameList
|
|
|
|
nsContainerFrame::StealFramesAfter(nsIFrame* aChild)
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!aChild ||
|
|
|
|
!(aChild->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER),
|
|
|
|
"StealFramesAfter doesn't handle overflow containers");
|
2017-04-30 18:30:08 +03:00
|
|
|
NS_ASSERTION(!IsBlockFrame(), "unexpected call");
|
2009-09-18 15:09:35 +04:00
|
|
|
|
|
|
|
if (!aChild) {
|
|
|
|
nsFrameList copy(mFrames);
|
|
|
|
mFrames.Clear();
|
|
|
|
return copy;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (nsFrameList::FrameLinkEnumerator iter(mFrames); !iter.AtEnd();
|
|
|
|
iter.Next()) {
|
|
|
|
if (iter.PrevFrame() == aChild) {
|
|
|
|
return mFrames.ExtractTail(iter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We didn't find the child in the principal child list.
|
|
|
|
// Maybe it's on the overflow list?
|
|
|
|
nsFrameList* overflowFrames = GetOverflowFrames();
|
|
|
|
if (overflowFrames) {
|
|
|
|
for (nsFrameList::FrameLinkEnumerator iter(*overflowFrames); !iter.AtEnd();
|
|
|
|
iter.Next()) {
|
|
|
|
if (iter.PrevFrame() == aChild) {
|
|
|
|
return overflowFrames->ExtractTail(iter);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_ERROR("StealFramesAfter: can't find aChild");
|
|
|
|
return nsFrameList::EmptyList();
|
|
|
|
}
|
|
|
|
|
2011-12-28 00:18:48 +04:00
|
|
|
/*
|
|
|
|
* Create a next-in-flow for aFrame. Will return the newly created
|
2014-12-02 09:03:57 +03:00
|
|
|
* frame <b>if and only if</b> a new frame is created; otherwise
|
|
|
|
* nullptr is returned.
|
2011-12-28 00:18:48 +04:00
|
|
|
*/
|
2014-12-02 09:03:57 +03:00
|
|
|
nsIFrame*
|
|
|
|
nsContainerFrame::CreateNextInFlow(nsIFrame* aFrame)
|
2011-12-28 00:18:48 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(!IsBlockFrame(),
|
|
|
|
"you should have called nsBlockFrame::CreateContinuationFor instead");
|
|
|
|
MOZ_ASSERT(mFrames.ContainsFrame(aFrame), "expected an in-flow child frame");
|
2011-12-28 00:18:48 +04:00
|
|
|
|
2014-02-07 02:07:47 +04:00
|
|
|
nsPresContext* pc = PresContext();
|
2011-12-28 00:18:48 +04:00
|
|
|
nsIFrame* nextInFlow = aFrame->GetNextInFlow();
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr == nextInFlow) {
|
2011-12-28 00:18:48 +04:00
|
|
|
// Create a continuation frame for the child frame and insert it
|
|
|
|
// into our child list.
|
2014-02-07 02:07:47 +04:00
|
|
|
nextInFlow = pc->PresShell()->FrameConstructor()->
|
|
|
|
CreateContinuingFrame(pc, aFrame, this);
|
2012-07-30 18:20:58 +04:00
|
|
|
mFrames.InsertFrame(nullptr, aFrame, nextInFlow);
|
2011-12-28 00:18:48 +04:00
|
|
|
|
|
|
|
NS_FRAME_LOG(NS_FRAME_TRACE_NEW_FRAMES,
|
|
|
|
("nsContainerFrame::CreateNextInFlow: frame=%p nextInFlow=%p",
|
|
|
|
aFrame, nextInFlow));
|
|
|
|
|
2014-12-02 09:03:57 +03:00
|
|
|
return nextInFlow;
|
2011-12-28 00:18:48 +04:00
|
|
|
}
|
2014-12-02 09:03:57 +03:00
|
|
|
return nullptr;
|
2011-12-28 00:18:48 +04:00
|
|
|
}
|
|
|
|
|
1998-10-01 01:35:29 +04:00
|
|
|
/**
|
2002-10-09 00:35:26 +04:00
|
|
|
* Remove and delete aNextInFlow and its next-in-flows. Updates the sibling and flow
|
1998-10-01 01:35:29 +04:00
|
|
|
* pointers
|
|
|
|
*/
|
1999-01-16 01:53:39 +03:00
|
|
|
void
|
2014-02-07 02:07:48 +04:00
|
|
|
nsContainerFrame::DeleteNextInFlowChild(nsIFrame* aNextInFlow,
|
|
|
|
bool aDeletingEmptyFrames)
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2008-09-20 17:42:03 +04:00
|
|
|
#ifdef DEBUG
|
2008-09-08 18:00:32 +04:00
|
|
|
nsIFrame* prevInFlow = aNextInFlow->GetPrevInFlow();
|
2008-09-20 17:42:03 +04:00
|
|
|
#endif
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(prevInFlow, "bad prev-in-flow");
|
1998-10-01 01:35:29 +04:00
|
|
|
|
|
|
|
// If the next-in-flow has a next-in-flow then delete it, too (and
|
|
|
|
// delete it first).
|
2005-09-06 05:26:50 +04:00
|
|
|
// Do this in a loop so we don't overflow the stack for frames
|
|
|
|
// with very many next-in-flows
|
2004-09-14 06:28:03 +04:00
|
|
|
nsIFrame* nextNextInFlow = aNextInFlow->GetNextInFlow();
|
2002-10-09 00:35:26 +04:00
|
|
|
if (nextNextInFlow) {
|
2016-02-02 18:36:30 +03:00
|
|
|
AutoTArray<nsIFrame*, 8> frames;
|
2005-09-06 05:26:50 +04:00
|
|
|
for (nsIFrame* f = nextNextInFlow; f; f = f->GetNextInFlow()) {
|
|
|
|
frames.AppendElement(f);
|
|
|
|
}
|
2018-01-15 23:39:03 +03:00
|
|
|
for (nsIFrame* delFrame : Reversed(frames)) {
|
2014-05-25 02:20:40 +04:00
|
|
|
delFrame->GetParent()->
|
|
|
|
DeleteNextInFlowChild(delFrame, aDeletingEmptyFrames);
|
2005-09-06 05:26:50 +04:00
|
|
|
}
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Take the next-in-flow out of the parent's child list
|
2014-02-07 02:07:47 +04:00
|
|
|
DebugOnly<nsresult> rv = StealFrame(aNextInFlow);
|
2007-07-26 08:03:29 +04:00
|
|
|
NS_ASSERTION(NS_SUCCEEDED(rv), "StealFrame failure");
|
1998-10-01 01:35:29 +04:00
|
|
|
|
2011-01-12 04:09:22 +03:00
|
|
|
#ifdef DEBUG
|
|
|
|
if (aDeletingEmptyFrames) {
|
|
|
|
nsLayoutUtils::AssertTreeOnlyEmptyNextInFlows(aNextInFlow);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2008-12-08 03:39:11 +03:00
|
|
|
// Delete the next-in-flow frame and its descendants. This will also
|
|
|
|
// remove it from its next-in-flow/prev-in-flow chain.
|
2006-04-10 04:16:29 +04:00
|
|
|
aNextInFlow->Destroy();
|
1998-10-01 01:35:29 +04:00
|
|
|
|
2017-11-05 08:48:48 +03:00
|
|
|
MOZ_ASSERT(!prevInFlow->GetNextInFlow(), "non null next-in-flow");
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
|
2007-07-04 02:49:00 +04:00
|
|
|
/**
|
|
|
|
* Set the frames on the overflow list
|
|
|
|
*/
|
2011-05-02 10:17:32 +04:00
|
|
|
void
|
2014-02-07 02:07:47 +04:00
|
|
|
nsContainerFrame::SetOverflowFrames(const nsFrameList& aOverflowFrames)
|
1999-10-21 09:11:43 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aOverflowFrames.NotEmpty(), "Shouldn't be called");
|
2009-07-28 16:51:09 +04:00
|
|
|
|
2014-02-07 02:07:47 +04:00
|
|
|
nsPresContext* pc = PresContext();
|
|
|
|
nsFrameList* newList = new (pc->PresShell()) nsFrameList(aOverflowFrames);
|
|
|
|
|
2017-05-27 14:36:00 +03:00
|
|
|
SetProperty(OverflowProperty(), newList);
|
1999-10-21 09:11:43 +04:00
|
|
|
}
|
|
|
|
|
2007-07-26 08:03:29 +04:00
|
|
|
nsFrameList*
|
2016-01-28 06:23:59 +03:00
|
|
|
nsContainerFrame::GetPropTableFrames(
|
|
|
|
FrameListPropertyDescriptor aProperty) const
|
2007-07-26 08:03:29 +04:00
|
|
|
{
|
2017-05-27 14:36:00 +03:00
|
|
|
return GetProperty(aProperty);
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsFrameList*
|
2016-01-28 06:23:59 +03:00
|
|
|
nsContainerFrame::RemovePropTableFrames(FrameListPropertyDescriptor aProperty)
|
2007-07-26 08:03:29 +04:00
|
|
|
{
|
2017-05-27 14:36:00 +03:00
|
|
|
return RemoveProperty(aProperty);
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
|
2013-03-24 00:10:33 +04:00
|
|
|
void
|
2016-01-28 06:23:59 +03:00
|
|
|
nsContainerFrame::SetPropTableFrames(nsFrameList* aFrameList,
|
|
|
|
FrameListPropertyDescriptor aProperty)
|
2007-07-26 08:03:29 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aProperty && aFrameList, "null ptr");
|
|
|
|
MOZ_ASSERT(
|
2010-04-12 22:36:58 +04:00
|
|
|
(aProperty != nsContainerFrame::OverflowContainersProperty() &&
|
|
|
|
aProperty != nsContainerFrame::ExcessOverflowContainersProperty()) ||
|
|
|
|
IsFrameOfType(nsIFrame::eCanContainOverflowContainers),
|
|
|
|
"this type of frame can't have overflow containers");
|
2014-02-07 02:07:47 +04:00
|
|
|
MOZ_ASSERT(!GetPropTableFrames(aProperty));
|
2017-05-27 14:36:00 +03:00
|
|
|
SetProperty(aProperty, aFrameList);
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
|
2017-09-29 01:36:36 +03:00
|
|
|
void
|
|
|
|
nsContainerFrame::PushChildrenToOverflow(nsIFrame* aFromChild,
|
|
|
|
nsIFrame* aPrevSibling)
|
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aFromChild, "null pointer");
|
|
|
|
MOZ_ASSERT(aPrevSibling, "pushing first child");
|
|
|
|
MOZ_ASSERT(aPrevSibling->GetNextSibling() == aFromChild, "bad prev sibling");
|
2017-09-29 01:36:36 +03:00
|
|
|
|
|
|
|
// Add the frames to our overflow list (let our next in flow drain
|
|
|
|
// our overflow list when it is ready)
|
|
|
|
SetOverflowFrames(mFrames.RemoveFramesAfter(aPrevSibling));
|
|
|
|
}
|
|
|
|
|
1999-01-16 01:53:39 +03:00
|
|
|
void
|
2014-02-07 02:07:48 +04:00
|
|
|
nsContainerFrame::PushChildren(nsIFrame* aFromChild,
|
|
|
|
nsIFrame* aPrevSibling)
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aFromChild, "null pointer");
|
|
|
|
MOZ_ASSERT(aPrevSibling, "pushing first child");
|
|
|
|
MOZ_ASSERT(aPrevSibling->GetNextSibling() == aFromChild, "bad prev sibling");
|
1998-10-01 01:35:29 +04:00
|
|
|
|
|
|
|
// Disconnect aFromChild from its previous sibling
|
2009-09-18 15:09:35 +04:00
|
|
|
nsFrameList tail = mFrames.RemoveFramesAfter(aPrevSibling);
|
1998-10-01 01:35:29 +04:00
|
|
|
|
2009-09-18 15:09:35 +04:00
|
|
|
nsContainerFrame* nextInFlow =
|
|
|
|
static_cast<nsContainerFrame*>(GetNextInFlow());
|
|
|
|
if (nextInFlow) {
|
1999-02-01 20:29:58 +03:00
|
|
|
// XXX This is not a very good thing to do. If it gets removed
|
|
|
|
// then remove the copy of this routine that doesn't do this from
|
|
|
|
// nsInlineFrame.
|
1999-04-13 04:15:13 +04:00
|
|
|
// When pushing and pulling frames we need to check for whether any
|
|
|
|
// views need to be reparented.
|
2003-06-26 15:30:17 +04:00
|
|
|
for (nsIFrame* f = aFromChild; f; f = f->GetNextSibling()) {
|
2014-02-07 02:07:47 +04:00
|
|
|
nsContainerFrame::ReparentFrameView(f, this, nextInFlow);
|
1999-04-13 04:15:13 +04:00
|
|
|
}
|
2012-07-30 18:20:58 +04:00
|
|
|
nextInFlow->mFrames.InsertFrames(nextInFlow, nullptr, tail);
|
1999-01-16 01:53:39 +03:00
|
|
|
}
|
|
|
|
else {
|
1998-10-01 01:35:29 +04:00
|
|
|
// Add the frames to our overflow list
|
2014-02-07 02:07:47 +04:00
|
|
|
SetOverflowFrames(tail);
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-09-29 10:19:26 +04:00
|
|
|
bool
|
2017-10-03 08:19:41 +03:00
|
|
|
nsContainerFrame::MoveOverflowToChildList()
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2011-09-29 10:19:26 +04:00
|
|
|
bool result = false;
|
1998-10-01 01:35:29 +04:00
|
|
|
|
|
|
|
// Check for an overflow list with our prev-in-flow
|
2006-02-22 00:33:47 +03:00
|
|
|
nsContainerFrame* prevInFlow = (nsContainerFrame*)GetPrevInFlow();
|
2012-07-30 18:20:58 +04:00
|
|
|
if (nullptr != prevInFlow) {
|
2014-02-07 02:07:47 +04:00
|
|
|
AutoFrameListPtr prevOverflowFrames(PresContext(),
|
2013-04-01 19:26:02 +04:00
|
|
|
prevInFlow->StealOverflowFrames());
|
1999-10-21 09:11:43 +04:00
|
|
|
if (prevOverflowFrames) {
|
2017-10-03 08:19:41 +03:00
|
|
|
// Tables are special; they can have repeated header/footer
|
|
|
|
// frames on mFrames at this point.
|
|
|
|
NS_ASSERTION(mFrames.IsEmpty() || IsTableFrame(), "bad overflow list");
|
1999-04-13 04:15:13 +04:00
|
|
|
// When pushing and pulling frames we need to check for whether any
|
|
|
|
// views need to be reparented.
|
2014-02-07 02:07:47 +04:00
|
|
|
nsContainerFrame::ReparentFrameViewList(*prevOverflowFrames,
|
2011-04-19 15:55:11 +04:00
|
|
|
prevInFlow, this);
|
2009-07-28 16:51:09 +04:00
|
|
|
mFrames.AppendFrames(this, *prevOverflowFrames);
|
2011-10-17 18:59:28 +04:00
|
|
|
result = true;
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-18 03:05:05 +04:00
|
|
|
// It's also possible that we have an overflow list for ourselves.
|
|
|
|
return DrainSelfOverflowList() || result;
|
|
|
|
}
|
|
|
|
|
2017-10-03 08:19:41 +03:00
|
|
|
bool
|
|
|
|
nsContainerFrame::MoveInlineOverflowToChildList(nsIFrame* aLineContainer)
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aLineContainer,
|
|
|
|
"Must have line container for moving inline overflows");
|
|
|
|
|
|
|
|
bool result = false;
|
|
|
|
|
|
|
|
// Check for an overflow list with our prev-in-flow
|
|
|
|
if (auto prevInFlow = static_cast<nsContainerFrame*>(GetPrevInFlow())) {
|
|
|
|
AutoFrameListPtr prevOverflowFrames(PresContext(),
|
|
|
|
prevInFlow->StealOverflowFrames());
|
|
|
|
if (prevOverflowFrames) {
|
|
|
|
// We may need to reparent floats from prev-in-flow to our line
|
|
|
|
// container if the container has prev continuation.
|
|
|
|
if (aLineContainer->GetPrevContinuation()) {
|
|
|
|
ReparentFloatsForInlineChild(aLineContainer,
|
|
|
|
prevOverflowFrames->FirstChild(), true);
|
|
|
|
}
|
|
|
|
// When pushing and pulling frames we need to check for whether
|
|
|
|
// any views need to be reparented.
|
|
|
|
nsContainerFrame::ReparentFrameViewList(*prevOverflowFrames,
|
|
|
|
prevInFlow, this);
|
|
|
|
// Prepend overflow frames to the list.
|
|
|
|
mFrames.InsertFrames(this, nullptr, *prevOverflowFrames);
|
|
|
|
result = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// It's also possible that we have overflow list for ourselves.
|
|
|
|
return DrainSelfOverflowList() || result;
|
|
|
|
}
|
|
|
|
|
2012-09-18 03:05:05 +04:00
|
|
|
bool
|
|
|
|
nsContainerFrame::DrainSelfOverflowList()
|
|
|
|
{
|
2013-04-01 19:26:02 +04:00
|
|
|
AutoFrameListPtr overflowFrames(PresContext(), StealOverflowFrames());
|
1999-10-21 09:11:43 +04:00
|
|
|
if (overflowFrames) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mFrames.AppendFrames(nullptr, *overflowFrames);
|
2012-09-18 03:05:05 +04:00
|
|
|
return true;
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
2012-09-18 03:05:05 +04:00
|
|
|
return false;
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
|
2016-03-11 19:39:27 +03:00
|
|
|
nsFrameList*
|
|
|
|
nsContainerFrame::DrainExcessOverflowContainersList(ChildFrameMerger aMergeFunc)
|
|
|
|
{
|
|
|
|
nsFrameList* overflowContainers =
|
|
|
|
GetPropTableFrames(OverflowContainersProperty());
|
|
|
|
|
|
|
|
NS_ASSERTION(!(overflowContainers && GetPrevInFlow()
|
|
|
|
&& static_cast<nsContainerFrame*>(GetPrevInFlow())
|
|
|
|
->GetPropTableFrames(ExcessOverflowContainersProperty())),
|
|
|
|
"conflicting overflow containers lists");
|
|
|
|
|
|
|
|
if (!overflowContainers) {
|
|
|
|
// Drain excess from previnflow
|
|
|
|
nsContainerFrame* prev = (nsContainerFrame*) GetPrevInFlow();
|
|
|
|
if (prev) {
|
|
|
|
nsFrameList* excessFrames =
|
|
|
|
prev->RemovePropTableFrames(ExcessOverflowContainersProperty());
|
|
|
|
if (excessFrames) {
|
|
|
|
excessFrames->ApplySetParent(this);
|
|
|
|
nsContainerFrame::ReparentFrameViewList(*excessFrames, prev, this);
|
|
|
|
overflowContainers = excessFrames;
|
|
|
|
SetPropTableFrames(overflowContainers, OverflowContainersProperty());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Our own excess overflow containers from a previous reflow can still be
|
2016-05-18 14:49:33 +03:00
|
|
|
// present if our next-in-flow hasn't been reflown yet. Move any children
|
|
|
|
// from it that don't have a continuation in this frame to the
|
|
|
|
// OverflowContainers list.
|
2016-03-11 19:39:27 +03:00
|
|
|
nsFrameList* selfExcessOCFrames =
|
|
|
|
RemovePropTableFrames(ExcessOverflowContainersProperty());
|
|
|
|
if (selfExcessOCFrames) {
|
2016-05-18 14:49:33 +03:00
|
|
|
nsFrameList toMove;
|
|
|
|
auto child = selfExcessOCFrames->FirstChild();
|
|
|
|
while (child) {
|
|
|
|
auto next = child->GetNextSibling();
|
|
|
|
MOZ_ASSERT(child->GetPrevInFlow(),
|
|
|
|
"ExcessOverflowContainers frames must be continuations");
|
|
|
|
if (child->GetPrevInFlow()->GetParent() != this) {
|
|
|
|
selfExcessOCFrames->RemoveFrame(child);
|
|
|
|
toMove.AppendFrame(nullptr, child);
|
|
|
|
}
|
|
|
|
child = next;
|
|
|
|
}
|
|
|
|
if (toMove.IsEmpty()) {
|
|
|
|
SetPropTableFrames(selfExcessOCFrames, ExcessOverflowContainersProperty());
|
|
|
|
} else if (overflowContainers) {
|
|
|
|
aMergeFunc(*overflowContainers, toMove, this);
|
|
|
|
if (selfExcessOCFrames->IsEmpty()) {
|
2017-11-09 05:00:48 +03:00
|
|
|
selfExcessOCFrames->Delete(PresShell());
|
2016-05-18 14:49:33 +03:00
|
|
|
} else {
|
|
|
|
SetPropTableFrames(selfExcessOCFrames, ExcessOverflowContainersProperty());
|
|
|
|
}
|
2016-03-11 19:39:27 +03:00
|
|
|
} else {
|
2016-05-18 14:49:33 +03:00
|
|
|
if (selfExcessOCFrames->IsEmpty()) {
|
|
|
|
*selfExcessOCFrames = toMove;
|
|
|
|
overflowContainers = selfExcessOCFrames;
|
|
|
|
} else {
|
|
|
|
SetPropTableFrames(selfExcessOCFrames, ExcessOverflowContainersProperty());
|
2017-11-09 05:00:48 +03:00
|
|
|
auto shell = PresShell();
|
2016-05-18 14:49:33 +03:00
|
|
|
overflowContainers = new (shell) nsFrameList(toMove);
|
|
|
|
}
|
2016-03-11 19:39:27 +03:00
|
|
|
SetPropTableFrames(overflowContainers, OverflowContainersProperty());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return overflowContainers;
|
|
|
|
}
|
|
|
|
|
2014-11-26 07:52:50 +03:00
|
|
|
nsIFrame*
|
|
|
|
nsContainerFrame::GetNextInFlowChild(ContinuationTraversingState& aState,
|
|
|
|
bool* aIsInOverflow)
|
|
|
|
{
|
|
|
|
nsContainerFrame*& nextInFlow = aState.mNextInFlow;
|
|
|
|
while (nextInFlow) {
|
|
|
|
// See if there is any frame in the container
|
|
|
|
nsIFrame* frame = nextInFlow->mFrames.FirstChild();
|
|
|
|
if (frame) {
|
|
|
|
if (aIsInOverflow) {
|
|
|
|
*aIsInOverflow = false;
|
|
|
|
}
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
// No frames in the principal list, try its overflow list
|
|
|
|
nsFrameList* overflowFrames = nextInFlow->GetOverflowFrames();
|
|
|
|
if (overflowFrames) {
|
|
|
|
if (aIsInOverflow) {
|
|
|
|
*aIsInOverflow = true;
|
|
|
|
}
|
|
|
|
return overflowFrames->FirstChild();
|
|
|
|
}
|
|
|
|
nextInFlow = static_cast<nsContainerFrame*>(nextInFlow->GetNextInFlow());
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsIFrame*
|
|
|
|
nsContainerFrame::PullNextInFlowChild(ContinuationTraversingState& aState)
|
|
|
|
{
|
|
|
|
bool isInOverflow;
|
|
|
|
nsIFrame* frame = GetNextInFlowChild(aState, &isInOverflow);
|
|
|
|
if (frame) {
|
|
|
|
nsContainerFrame* nextInFlow = aState.mNextInFlow;
|
|
|
|
if (isInOverflow) {
|
|
|
|
nsFrameList* overflowFrames = nextInFlow->GetOverflowFrames();
|
|
|
|
overflowFrames->RemoveFirstChild();
|
|
|
|
if (overflowFrames->IsEmpty()) {
|
|
|
|
nextInFlow->DestroyOverflowList();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
nextInFlow->mFrames.RemoveFirstChild();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Move the frame to the principal frame list of this container
|
|
|
|
mFrames.AppendFrame(this, frame);
|
|
|
|
// AppendFrame has reparented the frame, we need
|
|
|
|
// to reparent the frame view then.
|
|
|
|
nsContainerFrame::ReparentFrameView(frame, nextInFlow, this);
|
|
|
|
}
|
|
|
|
return frame;
|
|
|
|
}
|
|
|
|
|
2017-09-29 01:36:36 +03:00
|
|
|
/* static */ void
|
|
|
|
nsContainerFrame::ReparentFloatsForInlineChild(nsIFrame* aOurLineContainer,
|
|
|
|
nsIFrame* aFrame,
|
|
|
|
bool aReparentSiblings)
|
|
|
|
{
|
|
|
|
// XXXbz this would be better if it took a nsFrameList or a frame
|
|
|
|
// list slice....
|
|
|
|
NS_ASSERTION(aOurLineContainer->GetNextContinuation() ||
|
|
|
|
aOurLineContainer->GetPrevContinuation(),
|
|
|
|
"Don't call this when we have no continuation, it's a waste");
|
|
|
|
if (!aFrame) {
|
|
|
|
NS_ASSERTION(aReparentSiblings, "Why did we get called?");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsBlockFrame* frameBlock = nsLayoutUtils::GetFloatContainingBlock(aFrame);
|
|
|
|
if (!frameBlock || frameBlock == aOurLineContainer) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
nsBlockFrame* ourBlock = nsLayoutUtils::GetAsBlock(aOurLineContainer);
|
|
|
|
NS_ASSERTION(ourBlock, "Not a block, but broke vertically?");
|
|
|
|
|
|
|
|
while (true) {
|
|
|
|
ourBlock->ReparentFloats(aFrame, frameBlock, false);
|
|
|
|
|
|
|
|
if (!aReparentSiblings)
|
|
|
|
return;
|
|
|
|
nsIFrame* next = aFrame->GetNextSibling();
|
|
|
|
if (!next)
|
|
|
|
return;
|
|
|
|
if (next->GetParent() == aFrame->GetParent()) {
|
|
|
|
aFrame = next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// This is paranoid and will hardly ever get hit ... but we can't actually
|
|
|
|
// trust that the frames in the sibling chain all have the same parent,
|
|
|
|
// because lazy reparenting may be going on. If we find a different
|
|
|
|
// parent we need to redo our analysis.
|
|
|
|
ReparentFloatsForInlineChild(aOurLineContainer, next, aReparentSiblings);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-27 14:25:11 +04:00
|
|
|
bool
|
|
|
|
nsContainerFrame::ResolvedOrientationIsVertical()
|
|
|
|
{
|
2016-10-28 07:17:20 +03:00
|
|
|
StyleOrient orient = StyleDisplay()->mOrient;
|
2014-06-27 14:25:11 +04:00
|
|
|
switch (orient) {
|
2016-10-28 07:17:20 +03:00
|
|
|
case StyleOrient::Horizontal:
|
2014-06-27 14:25:11 +04:00
|
|
|
return false;
|
2016-10-28 07:17:20 +03:00
|
|
|
case StyleOrient::Vertical:
|
2014-06-27 14:25:11 +04:00
|
|
|
return true;
|
2016-10-28 07:17:20 +03:00
|
|
|
case StyleOrient::Inline:
|
2014-06-27 14:25:11 +04:00
|
|
|
return GetWritingMode().IsVertical();
|
2016-10-28 07:17:20 +03:00
|
|
|
case StyleOrient::Block:
|
2014-06-27 14:25:11 +04:00
|
|
|
return !GetWritingMode().IsVertical();
|
|
|
|
}
|
|
|
|
NS_NOTREACHED("unexpected -moz-orient value");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2016-09-01 18:36:22 +03:00
|
|
|
// static
|
|
|
|
bool
|
|
|
|
nsContainerFrame::FrameStartsCounterScope(nsIFrame* aFrame)
|
|
|
|
{
|
|
|
|
nsIContent* content = aFrame->GetContent();
|
|
|
|
if (!content || !content->IsHTMLElement())
|
|
|
|
return false;
|
|
|
|
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* localName = content->NodeInfo()->NameAtom();
|
2016-09-01 18:36:22 +03:00
|
|
|
return localName == nsGkAtoms::ol ||
|
|
|
|
localName == nsGkAtoms::ul ||
|
|
|
|
localName == nsGkAtoms::dir ||
|
|
|
|
localName == nsGkAtoms::menu;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
2016-09-01 18:36:23 +03:00
|
|
|
nsContainerFrame::RenumberList()
|
2016-09-01 18:36:22 +03:00
|
|
|
{
|
2016-09-01 18:36:22 +03:00
|
|
|
if (!FrameStartsCounterScope(this)) {
|
2016-09-01 18:36:22 +03:00
|
|
|
// If this frame doesn't start a counter scope then we don't need
|
|
|
|
// to renumber child list items.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
MOZ_ASSERT(mContent->IsHTMLElement(),
|
|
|
|
"FrameStartsCounterScope should only return true for HTML elements");
|
|
|
|
|
|
|
|
// Setup initial list ordinal value
|
|
|
|
// XXX Map html's start property to counter-reset style
|
|
|
|
int32_t ordinal = 1;
|
|
|
|
int32_t increment;
|
|
|
|
if (mContent->IsHTMLElement(nsGkAtoms::ol) &&
|
2017-12-07 21:13:50 +03:00
|
|
|
mContent->AsElement()->HasAttr(kNameSpaceID_None, nsGkAtoms::reversed)) {
|
2016-09-01 18:36:22 +03:00
|
|
|
increment = -1;
|
|
|
|
} else {
|
|
|
|
increment = 1;
|
|
|
|
}
|
|
|
|
|
2018-03-22 00:39:04 +03:00
|
|
|
nsGenericHTMLElement* hc = nsGenericHTMLElement::FromNode(mContent);
|
2016-09-01 18:36:22 +03:00
|
|
|
// Must be non-null, since FrameStartsCounterScope only returns true
|
|
|
|
// for HTML elements.
|
|
|
|
MOZ_ASSERT(hc, "How is mContent not HTML?");
|
|
|
|
const nsAttrValue* attr = hc->GetParsedAttr(nsGkAtoms::start);
|
2016-09-01 18:36:22 +03:00
|
|
|
nsContainerFrame* fif = static_cast<nsContainerFrame*>(FirstInFlow());
|
2016-09-01 18:36:22 +03:00
|
|
|
if (attr && attr->Type() == nsAttrValue::eInteger) {
|
|
|
|
ordinal = attr->GetIntegerValue();
|
|
|
|
} else if (increment < 0) {
|
|
|
|
// <ol reversed> case, or some other case with a negative increment: count
|
|
|
|
// up the child list
|
|
|
|
ordinal = 0;
|
2016-09-01 18:36:22 +03:00
|
|
|
fif->RenumberChildFrames(&ordinal, 0, -increment, true);
|
2016-09-01 18:36:22 +03:00
|
|
|
}
|
|
|
|
|
2016-09-01 18:36:22 +03:00
|
|
|
return fif->RenumberChildFrames(&ordinal, 0, increment, false);
|
2016-09-01 18:36:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// add in a sanity check for absurdly deep frame trees. See bug 42138
|
|
|
|
// can't just use IsFrameTreeTooDeep() because that method has side effects we don't want
|
|
|
|
#define MAX_DEPTH_FOR_LIST_RENUMBERING 200 // 200 open displayable tags is pretty unrealistic
|
|
|
|
|
|
|
|
bool
|
|
|
|
nsContainerFrame::RenumberFrameAndDescendants(int32_t* aOrdinal,
|
|
|
|
int32_t aDepth,
|
|
|
|
int32_t aIncrement,
|
|
|
|
bool aForCounting)
|
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aOrdinal, "null params are immoral!");
|
2016-09-01 18:36:22 +03:00
|
|
|
|
|
|
|
// add in a sanity check for absurdly deep frame trees. See bug 42138
|
|
|
|
if (MAX_DEPTH_FOR_LIST_RENUMBERING < aDepth) {
|
|
|
|
return false;
|
|
|
|
}
|
2016-09-01 18:36:22 +03:00
|
|
|
const nsStyleDisplay* display = StyleDisplay();
|
2016-09-01 18:36:22 +03:00
|
|
|
|
|
|
|
// drill down through any wrappers to the real frame
|
2016-09-01 18:36:22 +03:00
|
|
|
nsIFrame* kid = GetContentInsertionFrame();
|
2016-09-01 18:36:22 +03:00
|
|
|
if (!kid) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Do not renumber list for summary elements.
|
2016-11-16 09:02:58 +03:00
|
|
|
HTMLSummaryElement* summary =
|
2018-03-22 00:39:04 +03:00
|
|
|
HTMLSummaryElement::FromNode(kid->GetContent());
|
2016-11-16 09:02:58 +03:00
|
|
|
if (summary && summary->IsMainSummary()) {
|
|
|
|
return false;
|
2016-09-01 18:36:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
bool kidRenumberedABullet = false;
|
|
|
|
|
|
|
|
// If the frame is a list-item and the frame implements our
|
|
|
|
// block frame API then get its bullet and set the list item
|
|
|
|
// ordinal.
|
2016-08-28 05:31:50 +03:00
|
|
|
if (mozilla::StyleDisplay::ListItem == display->mDisplay) {
|
2016-09-01 18:36:22 +03:00
|
|
|
// Make certain that the frame is a block frame in case
|
|
|
|
// something foreign has crept in.
|
|
|
|
nsBlockFrame* listItem = nsLayoutUtils::GetAsBlock(kid);
|
|
|
|
if (listItem) {
|
|
|
|
nsBulletFrame* bullet = listItem->GetBullet();
|
|
|
|
if (bullet) {
|
|
|
|
if (!aForCounting) {
|
|
|
|
bool changed;
|
|
|
|
*aOrdinal = bullet->SetListItemOrdinal(*aOrdinal, &changed, aIncrement);
|
|
|
|
if (changed) {
|
|
|
|
kidRenumberedABullet = true;
|
|
|
|
|
|
|
|
// The ordinal changed - mark the bullet frame, and any
|
|
|
|
// intermediate frames between it and the block (are there
|
|
|
|
// ever any?), dirty.
|
|
|
|
// The calling code will make the necessary FrameNeedsReflow
|
|
|
|
// call for the list ancestor.
|
|
|
|
bullet->AddStateBits(NS_FRAME_IS_DIRTY);
|
|
|
|
nsIFrame *f = bullet;
|
|
|
|
do {
|
|
|
|
nsIFrame *parent = f->GetParent();
|
|
|
|
parent->ChildIsDirty(f);
|
|
|
|
f = parent;
|
|
|
|
} while (f != listItem);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// We're only counting the number of children,
|
|
|
|
// not restyling them. Don't take |value|
|
|
|
|
// into account when incrementing the ordinal
|
|
|
|
// or dirty the bullet.
|
|
|
|
*aOrdinal += aIncrement;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// XXX temporary? if the list-item has child list-items they
|
|
|
|
// should be numbered too; especially since the list-item is
|
|
|
|
// itself (ASSUMED!) not to be a counter-resetter.
|
|
|
|
bool meToo = listItem->RenumberChildFrames(aOrdinal, aDepth + 1,
|
|
|
|
aIncrement, aForCounting);
|
|
|
|
if (meToo) {
|
|
|
|
kidRenumberedABullet = true;
|
|
|
|
}
|
|
|
|
}
|
2016-08-28 05:31:50 +03:00
|
|
|
} else if (display->mDisplay == mozilla::StyleDisplay::Block ||
|
|
|
|
display->mDisplay == mozilla::StyleDisplay::Flex ||
|
|
|
|
display->mDisplay == mozilla::StyleDisplay::Grid) {
|
2016-09-01 18:36:22 +03:00
|
|
|
if (FrameStartsCounterScope(kid)) {
|
2016-09-01 18:36:22 +03:00
|
|
|
// Don't bother recursing into a frame that is a new counter scope.
|
|
|
|
// Any list-items in there will be handled by it.
|
2016-09-01 18:36:22 +03:00
|
|
|
} else {
|
2016-09-01 18:36:22 +03:00
|
|
|
nsContainerFrame* container = do_QueryFrame(kid);
|
|
|
|
if (container) {
|
2016-09-01 18:36:22 +03:00
|
|
|
kidRenumberedABullet =
|
2016-09-01 18:36:22 +03:00
|
|
|
container->RenumberChildFrames(aOrdinal, aDepth + 1,
|
|
|
|
aIncrement, aForCounting);
|
2016-09-01 18:36:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return kidRenumberedABullet;
|
|
|
|
}
|
|
|
|
|
2016-09-01 18:36:22 +03:00
|
|
|
bool
|
|
|
|
nsContainerFrame::RenumberChildFrames(int32_t* aOrdinal,
|
|
|
|
int32_t aDepth,
|
|
|
|
int32_t aIncrement,
|
|
|
|
bool aForCounting)
|
|
|
|
{
|
|
|
|
bool renumbered = false;
|
|
|
|
for (auto kid : mFrames) {
|
|
|
|
bool kidRenumbered =
|
|
|
|
kid->RenumberFrameAndDescendants(aOrdinal, aDepth, aIncrement, aForCounting);
|
|
|
|
if (!aForCounting && kidRenumbered) {
|
|
|
|
renumbered = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// We need to set NS_FRAME_HAS_DIRTY_CHILDREN bits up the tree between
|
|
|
|
// the bullet and the caller of RenumberLists. But the caller itself
|
|
|
|
// has to be responsible for setting the bit itself, since that caller
|
|
|
|
// might be making a FrameNeedsReflow call, which requires that the
|
|
|
|
// bit not be set yet.
|
|
|
|
if (renumbered && aDepth != 0) {
|
|
|
|
AddStateBits(NS_FRAME_HAS_DIRTY_CHILDREN);
|
|
|
|
}
|
|
|
|
|
|
|
|
return renumbered;
|
|
|
|
}
|
|
|
|
|
2016-10-31 18:58:18 +03:00
|
|
|
uint16_t
|
|
|
|
nsContainerFrame::CSSAlignmentForAbsPosChild(const ReflowInput& aChildRI,
|
|
|
|
LogicalAxis aLogicalAxis) const
|
|
|
|
{
|
|
|
|
MOZ_ASSERT(aChildRI.mFrame->IsAbsolutelyPositioned(),
|
|
|
|
"This method should only be called for abspos children");
|
|
|
|
NS_ERROR("Child classes that use css box alignment for abspos children "
|
|
|
|
"should provide their own implementation of this method!");
|
|
|
|
|
|
|
|
// In the unexpected/unlikely event that this implementation gets invoked,
|
|
|
|
// just use "start" alignment.
|
|
|
|
return NS_STYLE_ALIGN_START;
|
|
|
|
}
|
|
|
|
|
2016-09-01 18:36:22 +03:00
|
|
|
nsresult
|
|
|
|
nsContainerFrame::AttributeChanged(int32_t aNameSpaceID,
|
2017-10-03 01:05:19 +03:00
|
|
|
nsAtom* aAttribute,
|
2016-09-01 18:36:22 +03:00
|
|
|
int32_t aModType)
|
|
|
|
{
|
|
|
|
nsresult rv = nsSplittableFrame::AttributeChanged(aNameSpaceID,
|
|
|
|
aAttribute, aModType);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
if (nsGkAtoms::start == aAttribute ||
|
|
|
|
(nsGkAtoms::reversed == aAttribute &&
|
|
|
|
mContent->IsHTMLElement(nsGkAtoms::ol))) {
|
|
|
|
|
|
|
|
// XXX Not sure if this is necessary anymore
|
2016-09-01 18:36:23 +03:00
|
|
|
if (RenumberList()) {
|
2017-11-09 05:00:48 +03:00
|
|
|
PresShell()->FrameNeedsReflow(this, nsIPresShell::eStyleChange,
|
|
|
|
NS_FRAME_HAS_DIRTY_CHILDREN);
|
2016-09-01 18:36:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
2014-02-07 02:07:47 +04:00
|
|
|
nsOverflowContinuationTracker::nsOverflowContinuationTracker(nsContainerFrame* aFrame,
|
2011-09-29 10:19:26 +04:00
|
|
|
bool aWalkOOFFrames,
|
|
|
|
bool aSkipOverflowContainerChildren)
|
2012-07-30 18:20:58 +04:00
|
|
|
: mOverflowContList(nullptr),
|
|
|
|
mPrevOverflowCont(nullptr),
|
|
|
|
mSentry(nullptr),
|
2007-07-26 08:03:29 +04:00
|
|
|
mParent(aFrame),
|
2007-10-02 09:57:45 +04:00
|
|
|
mSkipOverflowContainerChildren(aSkipOverflowContainerChildren),
|
|
|
|
mWalkOOFFrames(aWalkOOFFrames)
|
2007-07-26 08:03:29 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aFrame, "null frame pointer");
|
2013-06-10 22:31:59 +04:00
|
|
|
SetupOverflowContList();
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsOverflowContinuationTracker::SetupOverflowContList()
|
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(mParent, "null frame pointer");
|
|
|
|
MOZ_ASSERT(!mOverflowContList, "already have list");
|
2013-06-10 22:31:59 +04:00
|
|
|
nsContainerFrame* nif =
|
|
|
|
static_cast<nsContainerFrame*>(mParent->GetNextInFlow());
|
|
|
|
if (nif) {
|
2014-02-07 02:07:47 +04:00
|
|
|
mOverflowContList = nif->GetPropTableFrames(
|
2010-03-29 05:46:55 +04:00
|
|
|
nsContainerFrame::OverflowContainersProperty());
|
2007-07-26 08:03:29 +04:00
|
|
|
if (mOverflowContList) {
|
2013-06-10 22:31:59 +04:00
|
|
|
mParent = nif;
|
2007-07-26 08:03:29 +04:00
|
|
|
SetUpListWalker();
|
|
|
|
}
|
|
|
|
}
|
2007-10-09 23:46:21 +04:00
|
|
|
if (!mOverflowContList) {
|
2014-02-07 02:07:47 +04:00
|
|
|
mOverflowContList = mParent->GetPropTableFrames(
|
2010-03-29 05:46:55 +04:00
|
|
|
nsContainerFrame::ExcessOverflowContainersProperty());
|
2007-07-26 08:03:29 +04:00
|
|
|
if (mOverflowContList) {
|
|
|
|
SetUpListWalker();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function to walk past overflow continuations whose prev-in-flow
|
|
|
|
* isn't a normal child and to set mSentry and mPrevOverflowCont correctly.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
nsOverflowContinuationTracker::SetUpListWalker()
|
|
|
|
{
|
|
|
|
NS_ASSERTION(!mSentry && !mPrevOverflowCont,
|
|
|
|
"forgot to reset mSentry or mPrevOverflowCont");
|
|
|
|
if (mOverflowContList) {
|
|
|
|
nsIFrame* cur = mOverflowContList->FirstChild();
|
|
|
|
if (mSkipOverflowContainerChildren) {
|
|
|
|
while (cur && (cur->GetPrevInFlow()->GetStateBits()
|
|
|
|
& NS_FRAME_IS_OVERFLOW_CONTAINER)) {
|
|
|
|
mPrevOverflowCont = cur;
|
|
|
|
cur = cur->GetNextSibling();
|
|
|
|
}
|
2007-12-02 06:13:23 +03:00
|
|
|
while (cur && (!(cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
|
|
|
|
== mWalkOOFFrames)) {
|
2007-10-02 09:57:45 +04:00
|
|
|
mPrevOverflowCont = cur;
|
|
|
|
cur = cur->GetNextSibling();
|
|
|
|
}
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
if (cur) {
|
|
|
|
mSentry = cur->GetPrevInFlow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Helper function to step forward through the overflow continuations list.
|
2007-10-02 09:57:45 +04:00
|
|
|
* Sets mSentry and mPrevOverflowCont, skipping over OOF or non-OOF frames
|
|
|
|
* as appropriate. May only be called when we have already set up an
|
|
|
|
* mOverflowContList; mOverflowContList cannot be null.
|
2007-07-26 08:03:29 +04:00
|
|
|
*/
|
|
|
|
void
|
|
|
|
nsOverflowContinuationTracker::StepForward()
|
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(mOverflowContList, "null list");
|
2007-07-26 08:03:29 +04:00
|
|
|
|
|
|
|
// Step forward
|
|
|
|
if (mPrevOverflowCont) {
|
|
|
|
mPrevOverflowCont = mPrevOverflowCont->GetNextSibling();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
mPrevOverflowCont = mOverflowContList->FirstChild();
|
|
|
|
}
|
|
|
|
|
2007-10-02 09:57:45 +04:00
|
|
|
// Skip over oof or non-oof frames as appropriate
|
|
|
|
if (mSkipOverflowContainerChildren) {
|
|
|
|
nsIFrame* cur = mPrevOverflowCont->GetNextSibling();
|
2007-12-02 06:13:23 +03:00
|
|
|
while (cur && (!(cur->GetStateBits() & NS_FRAME_OUT_OF_FLOW)
|
|
|
|
== mWalkOOFFrames)) {
|
2007-10-02 09:57:45 +04:00
|
|
|
mPrevOverflowCont = cur;
|
|
|
|
cur = cur->GetNextSibling();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-26 08:03:29 +04:00
|
|
|
// Set up the sentry
|
|
|
|
mSentry = (mPrevOverflowCont->GetNextSibling())
|
|
|
|
? mPrevOverflowCont->GetNextSibling()->GetPrevInFlow()
|
2012-07-30 18:20:58 +04:00
|
|
|
: nullptr;
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
nsresult
|
|
|
|
nsOverflowContinuationTracker::Insert(nsIFrame* aOverflowCont,
|
|
|
|
nsReflowStatus& aReflowStatus)
|
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aOverflowCont, "null frame pointer");
|
|
|
|
MOZ_ASSERT(!mSkipOverflowContainerChildren || mWalkOOFFrames ==
|
|
|
|
!!(aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW),
|
|
|
|
"shouldn't insert frame that doesn't match walker type");
|
|
|
|
MOZ_ASSERT(aOverflowCont->GetPrevInFlow(),
|
|
|
|
"overflow containers must have a prev-in-flow");
|
|
|
|
|
2007-07-26 08:03:29 +04:00
|
|
|
nsresult rv = NS_OK;
|
2013-01-25 03:12:48 +04:00
|
|
|
bool reparented = false;
|
2008-09-06 12:48:09 +04:00
|
|
|
nsPresContext* presContext = aOverflowCont->PresContext();
|
2013-03-26 00:27:05 +04:00
|
|
|
bool addToList = !mSentry || aOverflowCont != mSentry->GetNextInFlow();
|
|
|
|
|
|
|
|
// If we have a list and aOverflowCont is already in it then don't try to
|
|
|
|
// add it again.
|
|
|
|
if (addToList && aOverflowCont->GetParent() == mParent &&
|
|
|
|
(aOverflowCont->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) &&
|
|
|
|
mOverflowContList && mOverflowContList->ContainsFrame(aOverflowCont)) {
|
|
|
|
addToList = false;
|
|
|
|
mPrevOverflowCont = aOverflowCont->GetPrevSibling();
|
|
|
|
}
|
|
|
|
|
2013-01-25 03:12:48 +04:00
|
|
|
if (addToList) {
|
2007-11-15 22:23:07 +03:00
|
|
|
if (aOverflowCont->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) {
|
|
|
|
// aOverflowCont is in some other overflow container list,
|
2007-07-26 08:03:29 +04:00
|
|
|
// steal it first
|
2007-11-15 22:23:07 +03:00
|
|
|
NS_ASSERTION(!(mOverflowContList &&
|
|
|
|
mOverflowContList->ContainsFrame(aOverflowCont)),
|
|
|
|
"overflow containers out of order");
|
2014-05-25 02:20:40 +04:00
|
|
|
rv = aOverflowCont->GetParent()->StealFrame(aOverflowCont);
|
2007-07-26 08:03:29 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
aOverflowCont->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
|
|
|
|
}
|
|
|
|
if (!mOverflowContList) {
|
2013-04-01 19:26:02 +04:00
|
|
|
mOverflowContList = new (presContext->PresShell()) nsFrameList();
|
2014-02-07 02:07:47 +04:00
|
|
|
mParent->SetPropTableFrames(mOverflowContList,
|
2010-03-29 05:46:55 +04:00
|
|
|
nsContainerFrame::ExcessOverflowContainersProperty());
|
2007-07-26 08:03:29 +04:00
|
|
|
SetUpListWalker();
|
|
|
|
}
|
|
|
|
if (aOverflowCont->GetParent() != mParent) {
|
2014-02-07 02:07:47 +04:00
|
|
|
nsContainerFrame::ReparentFrameView(aOverflowCont,
|
2011-04-19 15:55:11 +04:00
|
|
|
aOverflowCont->GetParent(),
|
|
|
|
mParent);
|
2013-01-25 03:12:48 +04:00
|
|
|
reparented = true;
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
2013-03-26 00:27:05 +04:00
|
|
|
|
|
|
|
// If aOverflowCont has a prev/next-in-flow that might be in
|
|
|
|
// mOverflowContList we need to find it and insert after/before it to
|
|
|
|
// maintain the order amongst next-in-flows in this list.
|
|
|
|
nsIFrame* pif = aOverflowCont->GetPrevInFlow();
|
|
|
|
nsIFrame* nif = aOverflowCont->GetNextInFlow();
|
|
|
|
if ((pif && pif->GetParent() == mParent && pif != mPrevOverflowCont) ||
|
|
|
|
(nif && nif->GetParent() == mParent && mPrevOverflowCont)) {
|
|
|
|
for (nsFrameList::Enumerator e(*mOverflowContList); !e.AtEnd(); e.Next()) {
|
|
|
|
nsIFrame* f = e.get();
|
|
|
|
if (f == pif) {
|
|
|
|
mPrevOverflowCont = pif;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (f == nif) {
|
|
|
|
mPrevOverflowCont = f->GetPrevSibling();
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-07-26 08:03:29 +04:00
|
|
|
mOverflowContList->InsertFrame(mParent, mPrevOverflowCont, aOverflowCont);
|
2017-02-13 09:56:45 +03:00
|
|
|
aReflowStatus.SetNextInFlowNeedsReflow();
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// If we need to reflow it, mark it dirty
|
2017-02-13 09:56:45 +03:00
|
|
|
if (aReflowStatus.NextInFlowNeedsReflow())
|
2007-07-26 08:03:29 +04:00
|
|
|
aOverflowCont->AddStateBits(NS_FRAME_IS_DIRTY);
|
|
|
|
|
|
|
|
// It's in our list, just step forward
|
|
|
|
StepForward();
|
2007-12-02 06:13:23 +03:00
|
|
|
NS_ASSERTION(mPrevOverflowCont == aOverflowCont ||
|
|
|
|
(mSkipOverflowContainerChildren &&
|
|
|
|
(mPrevOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW) !=
|
|
|
|
(aOverflowCont->GetStateBits() & NS_FRAME_OUT_OF_FLOW)),
|
|
|
|
"OverflowContTracker in unexpected state");
|
2008-09-06 12:48:09 +04:00
|
|
|
|
2013-01-25 03:12:48 +04:00
|
|
|
if (addToList) {
|
2008-09-06 12:48:09 +04:00
|
|
|
// Convert all non-overflow-container continuations of aOverflowCont
|
|
|
|
// into overflow containers and move them to our overflow
|
|
|
|
// tracker. This preserves the invariant that the next-continuations
|
|
|
|
// of an overflow container are also overflow containers.
|
|
|
|
nsIFrame* f = aOverflowCont->GetNextContinuation();
|
2013-01-25 03:12:48 +04:00
|
|
|
if (f && (!(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER) ||
|
|
|
|
(!reparented && f->GetParent() == mParent) ||
|
|
|
|
(reparented && f->GetParent() != mParent))) {
|
|
|
|
if (!(f->GetStateBits() & NS_FRAME_IS_OVERFLOW_CONTAINER)) {
|
2014-05-25 02:20:40 +04:00
|
|
|
rv = f->GetParent()->StealFrame(f);
|
2013-01-25 03:12:48 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2008-09-06 12:48:09 +04:00
|
|
|
Insert(f, aReflowStatus);
|
|
|
|
}
|
|
|
|
}
|
2007-07-26 08:03:29 +04:00
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-06-10 22:31:59 +04:00
|
|
|
nsOverflowContinuationTracker::BeginFinish(nsIFrame* aChild)
|
2007-07-26 08:03:29 +04:00
|
|
|
{
|
2018-04-28 22:50:58 +03:00
|
|
|
MOZ_ASSERT(aChild, "null ptr");
|
|
|
|
MOZ_ASSERT(aChild->GetNextInFlow(),
|
|
|
|
"supposed to call Finish *before* deleting next-in-flow!");
|
|
|
|
|
2013-06-10 22:31:59 +04:00
|
|
|
for (nsIFrame* f = aChild; f; f = f->GetNextInFlow()) {
|
|
|
|
// We'll update these in EndFinish after the next-in-flows are gone.
|
|
|
|
if (f == mPrevOverflowCont) {
|
2012-07-30 18:20:58 +04:00
|
|
|
mSentry = nullptr;
|
2013-06-10 22:31:59 +04:00
|
|
|
mPrevOverflowCont = nullptr;
|
2010-05-13 04:56:08 +04:00
|
|
|
break;
|
|
|
|
}
|
2008-09-06 12:48:09 +04:00
|
|
|
if (f == mSentry) {
|
2013-06-10 22:31:59 +04:00
|
|
|
mSentry = nullptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
nsOverflowContinuationTracker::EndFinish(nsIFrame* aChild)
|
|
|
|
{
|
|
|
|
if (!mOverflowContList) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
// Forget mOverflowContList if it was deleted.
|
2017-05-27 14:36:00 +03:00
|
|
|
nsFrameList* eoc = mParent->GetProperty
|
|
|
|
(nsContainerFrame::ExcessOverflowContainersProperty());
|
2013-06-10 22:31:59 +04:00
|
|
|
if (eoc != mOverflowContList) {
|
2017-05-27 14:36:00 +03:00
|
|
|
nsFrameList* oc = static_cast<nsFrameList*>(mParent->GetProperty
|
|
|
|
(nsContainerFrame::OverflowContainersProperty()));
|
2013-06-10 22:31:59 +04:00
|
|
|
if (oc != mOverflowContList) {
|
|
|
|
// mOverflowContList was deleted
|
|
|
|
mPrevOverflowCont = nullptr;
|
|
|
|
mSentry = nullptr;
|
2014-05-25 02:20:40 +04:00
|
|
|
mParent = aChild->GetParent();
|
2013-06-10 22:31:59 +04:00
|
|
|
mOverflowContList = nullptr;
|
|
|
|
SetupOverflowContList();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// The list survived, update mSentry if needed.
|
|
|
|
if (!mSentry) {
|
|
|
|
if (!mPrevOverflowCont) {
|
|
|
|
SetUpListWalker();
|
|
|
|
} else {
|
|
|
|
mozilla::AutoRestore<nsIFrame*> saved(mPrevOverflowCont);
|
|
|
|
// step backward to make StepForward() use our current mPrevOverflowCont
|
|
|
|
mPrevOverflowCont = mPrevOverflowCont->GetPrevSibling();
|
2010-05-13 04:56:08 +04:00
|
|
|
StepForward();
|
2007-07-26 08:03:29 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1998-10-01 01:35:29 +04:00
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Debugging
|
|
|
|
|
2014-01-06 03:31:14 +04:00
|
|
|
#ifdef DEBUG_FRAME_DUMP
|
2013-04-30 22:38:52 +04:00
|
|
|
void
|
2014-01-27 02:07:02 +04:00
|
|
|
nsContainerFrame::List(FILE* out, const char* aPrefix, uint32_t aFlags) const
|
1998-10-01 01:35:29 +04:00
|
|
|
{
|
2014-01-27 02:07:02 +04:00
|
|
|
nsCString str;
|
|
|
|
ListGeneric(str, aPrefix, aFlags);
|
1999-01-16 03:19:10 +03:00
|
|
|
|
1998-10-01 01:35:29 +04:00
|
|
|
// Output the children
|
2011-09-29 10:19:26 +04:00
|
|
|
bool outputOneList = false;
|
2011-08-25 00:54:29 +04:00
|
|
|
ChildListIterator lists(this);
|
|
|
|
for (; !lists.IsDone(); lists.Next()) {
|
|
|
|
if (outputOneList) {
|
2014-01-27 02:07:02 +04:00
|
|
|
str += aPrefix;
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
2013-04-30 22:38:52 +04:00
|
|
|
if (lists.CurrentID() != kPrincipalList) {
|
|
|
|
if (!outputOneList) {
|
2014-01-27 02:07:02 +04:00
|
|
|
str += "\n";
|
|
|
|
str += aPrefix;
|
2013-04-30 22:38:52 +04:00
|
|
|
}
|
2014-01-27 02:07:02 +04:00
|
|
|
str += nsPrintfCString("%s %p ", mozilla::layout::ChildListName(lists.CurrentID()),
|
|
|
|
&GetChildList(lists.CurrentID()));
|
2013-04-30 22:38:52 +04:00
|
|
|
}
|
2014-01-27 02:07:02 +04:00
|
|
|
fprintf_stderr(out, "%s<\n", str.get());
|
|
|
|
str = "";
|
2011-08-25 00:54:29 +04:00
|
|
|
nsFrameList::Enumerator childFrames(lists.CurrentList());
|
|
|
|
for (; !childFrames.AtEnd(); childFrames.Next()) {
|
|
|
|
nsIFrame* kid = childFrames.get();
|
|
|
|
// Verify the child frame's parent frame pointer is correct
|
|
|
|
NS_ASSERTION(kid->GetParent() == this, "bad parent frame pointer");
|
|
|
|
|
|
|
|
// Have the child frame list
|
2014-01-27 02:07:02 +04:00
|
|
|
nsCString pfx(aPrefix);
|
|
|
|
pfx += " ";
|
|
|
|
kid->List(out, pfx.get(), aFlags);
|
2011-08-25 00:54:29 +04:00
|
|
|
}
|
2014-01-27 02:07:02 +04:00
|
|
|
fprintf_stderr(out, "%s>\n", aPrefix);
|
2013-04-30 22:38:52 +04:00
|
|
|
outputOneList = true;
|
2011-08-25 00:54:29 +04:00
|
|
|
}
|
1999-01-16 03:19:10 +03:00
|
|
|
|
|
|
|
if (!outputOneList) {
|
2014-01-27 02:07:02 +04:00
|
|
|
fprintf_stderr(out, "%s<>\n", str.get());
|
1998-10-01 01:35:29 +04:00
|
|
|
}
|
|
|
|
}
|
1999-09-01 05:02:16 +04:00
|
|
|
#endif
|