Bug 10209 - Part 1: Add an API for absolute container support for all frame types; r=roc
authorEhsan Akhgari <ehsan@mozilla.com>
Wed, 27 Apr 2011 19:41:43 -0400
changeset 77836 9989f9ef7b908b706316327b4acd40bc3b9aa9f7
parent 77835 fc7e928eaeaef372018f9cd045d45eeeeda93c0d
child 77837 0cafa2cbe386b511a03c8c8da3aafda70ab1f5f3
push id3
push userfelipc@gmail.com
push dateFri, 30 Sep 2011 20:09:13 +0000
reviewersroc
bugs10209
milestone10.0a1
Bug 10209 - Part 1: Add an API for absolute container support for all frame types; r=roc
layout/base/nsCSSFrameConstructor.cpp
layout/generic/nsFrame.cpp
layout/generic/nsIFrame.h
layout/generic/nsViewportFrame.h
--- a/layout/base/nsCSSFrameConstructor.cpp
+++ b/layout/base/nsCSSFrameConstructor.cpp
@@ -1018,16 +1018,18 @@ nsFrameConstructorState::PushAbsoluteCon
   mAbsoluteItems = 
     nsAbsoluteItems(AdjustAbsoluteContainingBlock(aNewAbsoluteContainingBlock));
 
   /* See if we're wiring the fixed-pos and abs-pos lists together.  This happens iff
    * we're a transformed element.
    */
   mFixedPosIsAbsPos = (aNewAbsoluteContainingBlock &&
                        aNewAbsoluteContainingBlock->GetStyleDisplay()->HasTransform());
+
+  aNewAbsoluteContainingBlock->MarkAsAbsoluteContainingBlock();
 }
 
 void
 nsFrameConstructorState::PushFloatContainingBlock(nsIFrame* aNewFloatContainingBlock,
                                                   nsFrameConstructorSaveState& aSaveState)
 {
   NS_PRECONDITION(!aNewFloatContainingBlock ||
                   aNewFloatContainingBlock->IsFloatContainingBlock(),
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -115,16 +115,17 @@
 #include "nsIObjectLoadingContent.h"
 #include "nsExpirationTracker.h"
 #include "nsSVGIntegrationUtils.h"
 #include "nsSVGEffects.h"
 #include "nsChangeHint.h"
 
 #include "gfxContext.h"
 #include "CSSCalc.h"
+#include "nsAbsoluteContainingBlock.h"
 
 #include "mozilla/Preferences.h"
 #include "mozilla/LookAndFeel.h"
 
 using namespace mozilla;
 using namespace mozilla::layers;
 
 // Struct containing cached metrics for box-wrapped frames.
@@ -246,16 +247,44 @@ nsFrame::RootFrameList(nsPresContext* aP
     nsIFrame* frame = shell->FrameManager()->GetRootFrame();
     if(frame) {
       frame->List(out, aIndent);
     }
   }
 }
 #endif
 
+static void
+DestroyAbsoluteContainingBlock(void* aPropertyValue)
+{
+  delete static_cast<nsAbsoluteContainingBlock*>(aPropertyValue);
+}
+
+NS_DECLARE_FRAME_PROPERTY(AbsoluteContainingBlockProperty, DestroyAbsoluteContainingBlock)
+
+bool
+nsIFrame::HasAbsolutelyPositionedChildren() const {
+  return IsAbsoluteContainer() && GetAbsoluteContainingBlock()->HasAbsoluteFrames();
+}
+
+nsAbsoluteContainingBlock*
+nsIFrame::GetAbsoluteContainingBlock() const {
+  NS_ASSERTION(IsAbsoluteContainer(), "The frame is not marked as an abspos container correctly");
+  nsAbsoluteContainingBlock* absCB = static_cast<nsAbsoluteContainingBlock*>
+    (Properties().Get(AbsoluteContainingBlockProperty()));
+  NS_ASSERTION(absCB, "The frame is marked as an abspos container but doesn't have the property");
+  return absCB;
+}
+
+void
+nsIFrame::MarkAsAbsoluteContainingBlock() {
+  AddStateBits(NS_FRAME_HAS_ABSPOS_CHILDREN);
+  Properties().Set(AbsoluteContainingBlockProperty(), new nsAbsoluteContainingBlock(GetAbsoluteListID()));
+}
+
 static bool ApplyOverflowClipping(nsDisplayListBuilder* aBuilder,
                                     const nsIFrame* aFrame,
                                     const nsStyleDisplay* aDisp, 
                                     nsRect* aRect);
 
 static bool ApplyAbsPosClipping(nsDisplayListBuilder* aBuilder,
                                   const nsStyleDisplay* aDisp, 
                                   const nsIFrame* aFrame,
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -99,16 +99,17 @@ class nsAccessible;
 #endif
 class nsDisplayListBuilder;
 class nsDisplayListSet;
 class nsDisplayList;
 class gfxSkipChars;
 class gfxSkipCharsIterator;
 class gfxContext;
 class nsLineList_iterator;
+class nsAbsoluteContainingBlock;
 
 struct nsPeekOffsetStruct;
 struct nsPoint;
 struct nsRect;
 struct nsSize;
 struct nsMargin;
 struct CharacterDataChangeInfo;
 
@@ -281,16 +282,19 @@ typedef PRUint64 nsFrameState;
 #define NS_FRAME_HAS_CLIP                           NS_FRAME_STATE_BIT(35)
 
 // Frame is a display root and the retained layer tree needs to be updated
 // at the next paint via display list construction.
 // Only meaningful for display roots, so we don't really need a global state
 // bit; we could free up this bit with a little extra complexity.
 #define NS_FRAME_UPDATE_LAYER_TREE                  NS_FRAME_STATE_BIT(36)
 
+// Frame can accept absolutely positioned children.
+#define NS_FRAME_HAS_ABSPOS_CHILDREN                NS_FRAME_STATE_BIT(37)
+
 // The lower 20 bits and upper 32 bits of the frame state are reserved
 // by this API.
 #define NS_FRAME_RESERVED                           ~NS_FRAME_IMPL_RESERVED
 
 // Box layout bits
 #define NS_STATE_IS_HORIZONTAL                      NS_FRAME_STATE_BIT(22)
 #define NS_STATE_IS_DIRECTION_NORMAL                NS_FRAME_STATE_BIT(31)
 
@@ -2718,17 +2722,27 @@ NS_PTR_TO_INT32(frame->Properties().Get(
     for (int i = 0, l = list->Length(); i < l; i++) {
       nsCOMPtr<nsIPresShell> shell = do_QueryReferent(list->ElementAt(i));
       
       if (shell) {
         shell->IncrementPaintCount();
       }
     }
   }  
-  
+
+  /**
+   * Accessors for the absolute containing block.
+   */
+  bool IsAbsoluteContainer() const { return !!(mState & NS_FRAME_HAS_ABSPOS_CHILDREN); }
+  bool HasAbsolutelyPositionedChildren() const;
+  nsAbsoluteContainingBlock* GetAbsoluteContainingBlock() const;
+  virtual void MarkAsAbsoluteContainingBlock();
+  // Child frame types override this function to select their own child list name
+  virtual mozilla::layout::FrameChildListID GetAbsoluteListID() const { return kAbsoluteList; }
+
 protected:
   // Members
   nsRect           mRect;
   nsIContent*      mContent;
   nsStyleContext*  mStyleContext;
   nsIFrame*        mParent;
 private:
   nsIFrame*        mNextSibling;  // doubly-linked list of frames
--- a/layout/generic/nsViewportFrame.h
+++ b/layout/generic/nsViewportFrame.h
@@ -112,16 +112,19 @@ public:
   virtual void InvalidateInternal(const nsRect& aDamageRect,
                                   nscoord aX, nscoord aY, nsIFrame* aForChild,
                                   PRUint32 aFlags);
 
 #ifdef DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
+private:
+  virtual mozilla::layout::FrameChildListID GetAbsoluteListName() const { return kFixedList; }
+
 protected:
   nsPoint AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const;
 
   // position: fixed content is really content which is absolutely positioned with
   // respect to the viewport.
   nsAbsoluteContainingBlock mFixedContainer;
 };