Bug 1421105 - Part2:Handle dynamic changes for ColumnSetWrapperFrame by reconstructing frames for any changes under it. draft
authorNeerja Pancholi <npancholi@mozilla.com>
Mon, 27 Nov 2017 17:34:44 -0800
changeset 762845 133158cf5198f21b5bf79618b84e282c8878fcab
parent 762844 08e923bbacdddebe03d9d98f39a7da5d1e28cd8c
child 762846 a94e8268a0c50f202c49bc14f88c6cdb558c4a44
push id101269
push userbmo:npancholi@mozilla.com
push dateSat, 03 Mar 2018 02:23:39 +0000
bugs1421105
milestone60.0a1
Bug 1421105 - Part2:Handle dynamic changes for ColumnSetWrapperFrame by reconstructing frames for any changes under it. MozReview-Commit-ID: JjyHXS2nxWk
layout/base/nsCSSFrameConstructor.cpp
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -641,16 +641,38 @@ GetIBContainingBlockFor(nsIFrame* aFrame
   // post-conditions
   NS_ASSERTION(parentFrame, "no normal ancestor found for ib-split frame "
                             "in GetIBContainingBlockFor");
   NS_ASSERTION(parentFrame != aFrame, "parentFrame is actually the child frame - bogus reslt");
 
   return parentFrame;
 }
 
+static nsIFrame*
+GetMulticolContainingBlockFor(nsIFrame* aFrame)
+{
+  NS_PRECONDITION(aFrame->HasMulticolAncestor(),
+                  "GetMulticolContainingBlockFor() should only be called on"
+                  "frames inside a multicol element!");
+
+  nsIFrame* currFrame = aFrame->GetParent();
+  while (currFrame){
+    // Find the first non-multicol, non-pseudo styled parent frame
+    if (!currFrame->HasMulticolAncestor() &&
+        !currFrame->StyleContext()->GetPseudo()) {
+      break;
+    }
+    currFrame = currFrame->GetParent();
+  }
+
+  MOZ_ASSERT(currFrame, "No valid ColumnSetWrapper in multicol hierarchy!");
+
+  return currFrame;
+}
+
 // This is a bit slow, but sometimes we need it.
 static bool
 ParentIsWrapperAnonBox(nsIFrame* aParent)
 {
   nsIFrame* maybeAnonBox = aParent;
   if (maybeAnonBox->StyleContext()->GetPseudo() ==
         nsCSSAnonBoxes::cellContent) {
     // The thing that would maybe be a wrapper anon box is the cell.
@@ -9174,16 +9196,19 @@ nsCSSFrameConstructor::CreateContinuingF
     newFrame = NS_NewXULLabelFrame(shell, styleContext);
     newFrame->Init(content, aParentFrame, aFrame);
 #endif
   } else if (LayoutFrameType::ColumnSet == frameType) {
     MOZ_ASSERT(!aFrame->IsTableCaption(),
                "no support for fragmenting table captions yet");
     newFrame = NS_NewColumnSetFrame(shell, styleContext, nsFrameState(0));
     newFrame->Init(content, aParentFrame, aFrame);
+  } else if (LayoutFrameType::ColumnSetWrapper == frameType) {
+    newFrame = NS_NewColumnSetWrapperFrame(shell, styleContext, nsFrameState(0));
+    newFrame->Init(content, aParentFrame, aFrame);
   } else if (LayoutFrameType::Page == frameType) {
     nsContainerFrame* canvasFrame;
     newFrame = ConstructPageFrame(shell, aParentFrame, aFrame, canvasFrame);
   } else if (LayoutFrameType::TableWrapper == frameType) {
     newFrame =
       CreateContinuingOuterTableFrame(shell, aPresContext, aFrame, aParentFrame,
                                       content, styleContext);
 
@@ -9551,16 +9576,21 @@ FindPreviousNonWhitespaceSibling(nsIFram
 bool
 nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval(nsIFrame* aFrame)
 {
   NS_PRECONDITION(aFrame, "Must have a frame");
   NS_PRECONDITION(aFrame->GetParent(), "Frame shouldn't be root");
   NS_PRECONDITION(aFrame == aFrame->FirstContinuation(),
                   "aFrame not the result of GetPrimaryFrame()?");
 
+  if (aFrame->HasMulticolAncestor()) {
+    ReframeContainingBlock(aFrame);
+    return true;
+  }
+
   if (IsFramePartOfIBSplit(aFrame)) {
     // The removal functions can't handle removal of an {ib} split directly; we
     // need to rebuild the containing block.
 #ifdef DEBUG
     if (gNoisyContentUpdates) {
       printf("nsCSSFrameConstructor::MaybeRecreateContainerForFrameRemoval: "
              "frame=");
       nsFrame::ListTag(stdout, aFrame);
@@ -13073,16 +13103,21 @@ nsCSSFrameConstructor::WipeContainingBlo
       RecreateFramesForContent(aFrame->GetContent(), InsertionKind::Async);
       return true;
     }
   }
 
   // Now we have several cases involving {ib} splits.  Put them all in a
   // do/while with breaks to take us to the "go and reconstruct" code.
   do {
+    if (aFrame->HasMulticolAncestor() ||
+        aFrame->Type() == LayoutFrameType::ColumnSetWrapper) {
+      // Need to go ahead and reconstruct.
+      break;
+    }
     if (IsInlineFrame(aFrame)) {
       if (aItems.AreAllItemsInline()) {
         // We can just put the kids in.
         return false;
       }
 
       if (!IsFramePartOfIBSplit(aFrame)) {
         // Need to go ahead and reconstruct.
@@ -13135,21 +13170,22 @@ nsCSSFrameConstructor::WipeContainingBlo
   // enforces that the root is display:none, display:table, or display:block.
   // Note that walking up "too far" is OK in terms of correctness, even if it
   // might be a little inefficient.  This is why we walk out of all
   // pseudo-frames -- telling which ones are or are not OK to walk out of is
   // too hard (and I suspect that we do in fact need to walk out of all of
   // them).
   while (IsFramePartOfIBSplit(aContainingBlock) ||
          aContainingBlock->IsInlineOutside() ||
-         aContainingBlock->StyleContext()->GetPseudo()) {
+         aContainingBlock->StyleContext()->GetPseudo() ||
+         aContainingBlock->HasMulticolAncestor()) {
     aContainingBlock = aContainingBlock->GetParent();
     NS_ASSERTION(aContainingBlock,
-                 "Must have non-inline, non-ib-split, non-pseudo frame as "
-                 "root (or child of root, for a table root)!");
+                 "Must have non-inline, non-ib-split, non-pseudo, non-multicol"
+                 " frame as root (or child of root, for a table root)!");
   }
 
   // Tell parent of the containing block to reformulate the
   // entire block. This is painful and definitely not optimal
   // but it will *always* get the right answer.
 
   nsIContent* blockContent = aContainingBlock->GetContent();
 #ifdef DEBUG
@@ -13182,17 +13218,22 @@ nsCSSFrameConstructor::ReframeContaining
   if (mPresShell->IsReflowLocked()) {
     // don't ReframeContainingBlock, this will result in a crash
     // if we remove a tree that's in reflow - see bug 121368 for testcase
     NS_ERROR("Atemptted to nsCSSFrameConstructor::ReframeContainingBlock during a Reflow!!!");
     return;
   }
 
   // Get the first "normal" ancestor of the target frame.
-  nsIFrame* containingBlock = GetIBContainingBlockFor(aFrame);
+  nsIFrame* containingBlock = nullptr;
+  if (aFrame->HasMulticolAncestor()) {
+    containingBlock = GetMulticolContainingBlockFor(aFrame);
+  } else {
+    containingBlock = GetIBContainingBlockFor(aFrame);
+  }
   if (containingBlock) {
     // From here we look for the containing block in case the target
     // frame is already a block (which can happen when an inline frame
     // wraps some of its content in an anonymous block; see
     // ConstructInline)
 
     // NOTE: We used to get the FloatContainingBlock here, but it was often wrong.
     // GetIBContainingBlock works much better and provides the correct container in all cases