layout/generic/nsViewportFrame.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 /*
     7  * rendering object that is the root of the frame tree, which contains
     8  * the document's scrollbars and contains fixed-positioned elements
     9  */
    11 #include "nsViewportFrame.h"
    12 #include "nsGkAtoms.h"
    13 #include "nsIScrollableFrame.h"
    14 #include "nsSubDocumentFrame.h"
    15 #include "nsAbsoluteContainingBlock.h"
    16 #include "GeckoProfiler.h"
    18 using namespace mozilla;
    20 nsIFrame*
    21 NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
    22 {
    23   return new (aPresShell) ViewportFrame(aContext);
    24 }
    26 NS_IMPL_FRAMEARENA_HELPERS(ViewportFrame)
    27 NS_QUERYFRAME_HEAD(ViewportFrame)
    28   NS_QUERYFRAME_ENTRY(ViewportFrame)
    29 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
    31 void
    32 ViewportFrame::Init(nsIContent*      aContent,
    33                     nsIFrame*        aParent,
    34                     nsIFrame*        aPrevInFlow)
    35 {
    36   Super::Init(aContent, aParent, aPrevInFlow);
    38   nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(this);
    39   if (parent) {
    40     nsFrameState state = parent->GetStateBits();
    42     mState |= state & (NS_FRAME_IN_POPUP);
    43   }
    44 }
    46 nsresult
    47 ViewportFrame::SetInitialChildList(ChildListID     aListID,
    48                                    nsFrameList&    aChildList)
    49 {
    50   // See which child list to add the frames to
    51 #ifdef DEBUG
    52   nsFrame::VerifyDirtyBitSet(aChildList);
    53 #endif
    54   return nsContainerFrame::SetInitialChildList(aListID, aChildList);
    55 }
    57 void
    58 ViewportFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
    59                                 const nsRect&           aDirtyRect,
    60                                 const nsDisplayListSet& aLists)
    61 {
    62   PROFILER_LABEL("ViewportFrame", "BuildDisplayList");
    63   nsIFrame* kid = mFrames.FirstChild();
    64   if (!kid)
    65     return;
    67   // make the kid's BorderBackground our own. This ensures that the canvas
    68   // frame's background becomes our own background and therefore appears
    69   // below negative z-index elements.
    70   BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
    71 }
    73 nsresult
    74 ViewportFrame::AppendFrames(ChildListID     aListID,
    75                             nsFrameList&    aFrameList)
    76 {
    77   NS_ASSERTION(aListID == kPrincipalList ||
    78                aListID == GetAbsoluteListID(), "unexpected child list");
    79   NS_ASSERTION(aListID != GetAbsoluteListID() ||
    80                GetChildList(aListID).IsEmpty(), "Shouldn't have any kids!");
    81   return nsContainerFrame::AppendFrames(aListID, aFrameList);
    82 }
    84 nsresult
    85 ViewportFrame::InsertFrames(ChildListID     aListID,
    86                             nsIFrame*       aPrevFrame,
    87                             nsFrameList&    aFrameList)
    88 {
    89   NS_ASSERTION(aListID == kPrincipalList ||
    90                aListID == GetAbsoluteListID(), "unexpected child list");
    91   NS_ASSERTION(aListID != GetAbsoluteListID() ||
    92                GetChildList(aListID).IsEmpty(), "Shouldn't have any kids!");
    93   return nsContainerFrame::InsertFrames(aListID, aPrevFrame, aFrameList);
    94 }
    96 nsresult
    97 ViewportFrame::RemoveFrame(ChildListID     aListID,
    98                            nsIFrame*       aOldFrame)
    99 {
   100   NS_ASSERTION(aListID == kPrincipalList ||
   101                aListID == GetAbsoluteListID(), "unexpected child list");
   102   return nsContainerFrame::RemoveFrame(aListID, aOldFrame);
   103 }
   105 /* virtual */ nscoord
   106 ViewportFrame::GetMinWidth(nsRenderingContext *aRenderingContext)
   107 {
   108   nscoord result;
   109   DISPLAY_MIN_WIDTH(this, result);
   110   if (mFrames.IsEmpty())
   111     result = 0;
   112   else
   113     result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
   115   return result;
   116 }
   118 /* virtual */ nscoord
   119 ViewportFrame::GetPrefWidth(nsRenderingContext *aRenderingContext)
   120 {
   121   nscoord result;
   122   DISPLAY_PREF_WIDTH(this, result);
   123   if (mFrames.IsEmpty())
   124     result = 0;
   125   else
   126     result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
   128   return result;
   129 }
   131 nsPoint
   132 ViewportFrame::AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const
   133 {
   134   // Get our prinicpal child frame and see if we're scrollable
   135   nsIFrame* kidFrame = mFrames.FirstChild();
   136   nsIScrollableFrame* scrollingFrame = do_QueryFrame(kidFrame);
   138   if (scrollingFrame) {
   139     nsMargin scrollbars = scrollingFrame->GetActualScrollbarSizes();
   140     aReflowState->SetComputedWidth(aReflowState->ComputedWidth() -
   141                                    scrollbars.LeftRight());
   142     aReflowState->AvailableWidth() -= scrollbars.LeftRight();
   143     aReflowState->SetComputedHeightWithoutResettingResizeFlags(
   144       aReflowState->ComputedHeight() - scrollbars.TopBottom());
   145     return nsPoint(scrollbars.left, scrollbars.top);
   146   }
   147   return nsPoint(0, 0);
   148 }
   150 nsRect
   151 ViewportFrame::AdjustReflowStateAsContainingBlock(nsHTMLReflowState* aReflowState) const
   152 {
   153 #ifdef DEBUG
   154   nsPoint offset =
   155 #endif
   156     AdjustReflowStateForScrollbars(aReflowState);
   158   NS_ASSERTION(GetAbsoluteContainingBlock()->GetChildList().IsEmpty() ||
   159                (offset.x == 0 && offset.y == 0),
   160                "We don't handle correct positioning of fixed frames with "
   161                "scrollbars in odd positions");
   163   // If a scroll position clamping scroll-port size has been set, layout
   164   // fixed position elements to this size instead of the computed size.
   165   nsRect rect(0, 0, aReflowState->ComputedWidth(), aReflowState->ComputedHeight());
   166   nsIPresShell* ps = PresContext()->PresShell();
   167   if (ps->IsScrollPositionClampingScrollPortSizeSet()) {
   168     rect.SizeTo(ps->GetScrollPositionClampingScrollPortSize());
   169   }
   171   // Make sure content document fixed-position margins are respected.
   172   rect.Deflate(ps->GetContentDocumentFixedPositionMargins());
   173   return rect;
   174 }
   176 nsresult
   177 ViewportFrame::Reflow(nsPresContext*           aPresContext,
   178                       nsHTMLReflowMetrics&     aDesiredSize,
   179                       const nsHTMLReflowState& aReflowState,
   180                       nsReflowStatus&          aStatus)
   181 {
   182   DO_GLOBAL_REFLOW_COUNT("ViewportFrame");
   183   DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
   184   NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow");
   186   // Initialize OUT parameters
   187   aStatus = NS_FRAME_COMPLETE;
   189   // Because |Reflow| sets mComputedHeight on the child to
   190   // availableHeight.
   191   AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
   193   // Set our size up front, since some parts of reflow depend on it
   194   // being already set.  Note that the computed height may be
   195   // unconstrained; that's ok.  Consumers should watch out for that.
   196   SetSize(nsSize(aReflowState.ComputedWidth(), aReflowState.ComputedHeight()));
   198   // Reflow the main content first so that the placeholders of the
   199   // fixed-position frames will be in the right places on an initial
   200   // reflow.
   201   nscoord kidHeight = 0;
   203   nsresult rv = NS_OK;
   205   if (mFrames.NotEmpty()) {
   206     // Deal with a non-incremental reflow or an incremental reflow
   207     // targeted at our one-and-only principal child frame.
   208     if (aReflowState.ShouldReflowAllKids() ||
   209         aReflowState.mFlags.mVResize ||
   210         NS_SUBTREE_DIRTY(mFrames.FirstChild())) {
   211       // Reflow our one-and-only principal child frame
   212       nsIFrame*           kidFrame = mFrames.FirstChild();
   213       nsHTMLReflowMetrics kidDesiredSize(aReflowState);
   214       nsSize              availableSpace(aReflowState.AvailableWidth(),
   215                                          aReflowState.AvailableHeight());
   216       nsHTMLReflowState   kidReflowState(aPresContext, aReflowState,
   217                                          kidFrame, availableSpace);
   219       // Reflow the frame
   220       kidReflowState.SetComputedHeight(aReflowState.ComputedHeight());
   221       rv = ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
   222                        0, 0, 0, aStatus);
   223       kidHeight = kidDesiredSize.Height();
   225       FinishReflowChild(kidFrame, aPresContext, kidDesiredSize, nullptr, 0, 0, 0);
   226     } else {
   227       kidHeight = mFrames.FirstChild()->GetSize().height;
   228     }
   229   }
   231   NS_ASSERTION(aReflowState.AvailableWidth() != NS_UNCONSTRAINEDSIZE,
   232                "shouldn't happen anymore");
   234   // Return the max size as our desired size
   235   aDesiredSize.Width() = aReflowState.AvailableWidth();
   236   // Being flowed initially at an unconstrained height means we should
   237   // return our child's intrinsic size.
   238   aDesiredSize.Height() = aReflowState.ComputedHeight() != NS_UNCONSTRAINEDSIZE
   239                           ? aReflowState.ComputedHeight()
   240                           : kidHeight;
   241   aDesiredSize.SetOverflowAreasToDesiredBounds();
   243   if (mFrames.NotEmpty()) {
   244     ConsiderChildOverflow(aDesiredSize.mOverflowAreas, mFrames.FirstChild());
   245   }
   247   if (IsAbsoluteContainer()) {
   248     // Make a copy of the reflow state and change the computed width and height
   249     // to reflect the available space for the fixed items
   250     nsHTMLReflowState reflowState(aReflowState);
   252     if (reflowState.AvailableHeight() == NS_UNCONSTRAINEDSIZE) {
   253       // We have an intrinsic-height document with abs-pos/fixed-pos children.
   254       // Set the available height and mComputedHeight to our chosen height.
   255       reflowState.AvailableHeight() = aDesiredSize.Height();
   256       // Not having border/padding simplifies things
   257       NS_ASSERTION(reflowState.ComputedPhysicalBorderPadding() == nsMargin(0,0,0,0),
   258                    "Viewports can't have border/padding");
   259       reflowState.SetComputedHeight(aDesiredSize.Height());
   260     }
   262     nsRect rect = AdjustReflowStateAsContainingBlock(&reflowState);
   264     // Just reflow all the fixed-pos frames.
   265     rv = GetAbsoluteContainingBlock()->Reflow(this, aPresContext, reflowState, aStatus,
   266                                               rect,
   267                                               false, true, true, // XXX could be optimized
   268                                               &aDesiredSize.mOverflowAreas);
   269   }
   271   // If we were dirty then do a repaint
   272   if (GetStateBits() & NS_FRAME_IS_DIRTY) {
   273     InvalidateFrame();
   274   }
   276   // Clipping is handled by the document container (e.g., nsSubDocumentFrame),
   277   // so we don't need to change our overflow areas.
   278   bool overflowChanged = FinishAndStoreOverflow(&aDesiredSize);
   279   if (overflowChanged) {
   280     // We may need to alert our container to get it to pick up the
   281     // overflow change.
   282     nsSubDocumentFrame* container = static_cast<nsSubDocumentFrame*>
   283       (nsLayoutUtils::GetCrossDocParentFrame(this));
   284     if (container && !container->ShouldClipSubdocument()) {
   285       container->PresContext()->PresShell()->
   286         FrameNeedsReflow(container, nsIPresShell::eResize, NS_FRAME_IS_DIRTY);
   287     }
   288   }
   290   NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus);
   291   NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
   292   return rv; 
   293 }
   295 nsIAtom*
   296 ViewportFrame::GetType() const
   297 {
   298   return nsGkAtoms::viewportFrame;
   299 }
   301 #ifdef DEBUG_FRAME_DUMP
   302 nsresult
   303 ViewportFrame::GetFrameName(nsAString& aResult) const
   304 {
   305   return MakeFrameName(NS_LITERAL_STRING("Viewport"), aResult);
   306 }
   307 #endif

mercurial