1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/generic/nsPlaceholderFrame.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,168 @@ 1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.8 + 1.9 +/* 1.10 + * rendering object for the point that anchors out-of-flow rendering 1.11 + * objects such as floats and absolutely positioned elements 1.12 + */ 1.13 + 1.14 +/* 1.15 + * Destruction of a placeholder and its out-of-flow must observe the 1.16 + * following constraints: 1.17 + * 1.18 + * - The mapping from the out-of-flow to the placeholder must be 1.19 + * removed from the frame manager before the placeholder is destroyed. 1.20 + * - The mapping from the out-of-flow to the placeholder must be 1.21 + * removed from the frame manager before the out-of-flow is destroyed. 1.22 + * - The placeholder must be removed from the frame tree, or have the 1.23 + * mapping from it to its out-of-flow cleared, before the out-of-flow 1.24 + * is destroyed (so that the placeholder will not point to a destroyed 1.25 + * frame while it's in the frame tree). 1.26 + * 1.27 + * Furthermore, some code assumes that placeholders point to something 1.28 + * useful, so placeholders without an associated out-of-flow should not 1.29 + * remain in the tree. 1.30 + * 1.31 + * The placeholder's Destroy() implementation handles the destruction of 1.32 + * the placeholder and its out-of-flow. To avoid crashes, frame removal 1.33 + * and destruction code that works with placeholders must not assume 1.34 + * that the placeholder points to its out-of-flow. 1.35 + */ 1.36 + 1.37 +#ifndef nsPlaceholderFrame_h___ 1.38 +#define nsPlaceholderFrame_h___ 1.39 + 1.40 +#include "mozilla/Attributes.h" 1.41 +#include "nsFrame.h" 1.42 +#include "nsGkAtoms.h" 1.43 + 1.44 +nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell, 1.45 + nsStyleContext* aContext, 1.46 + nsFrameState aTypeBit); 1.47 + 1.48 +#define PLACEHOLDER_TYPE_MASK (PLACEHOLDER_FOR_FLOAT | \ 1.49 + PLACEHOLDER_FOR_ABSPOS | \ 1.50 + PLACEHOLDER_FOR_FIXEDPOS | \ 1.51 + PLACEHOLDER_FOR_POPUP) 1.52 + 1.53 +/** 1.54 + * Implementation of a frame that's used as a placeholder for a frame that 1.55 + * has been moved out of the flow. 1.56 + */ 1.57 +class nsPlaceholderFrame MOZ_FINAL : public nsFrame { 1.58 +public: 1.59 + NS_DECL_FRAMEARENA_HELPERS 1.60 +#ifdef DEBUG 1.61 + NS_DECL_QUERYFRAME_TARGET(nsPlaceholderFrame) 1.62 + NS_DECL_QUERYFRAME 1.63 +#endif 1.64 + 1.65 + /** 1.66 + * Create a new placeholder frame. aTypeBit must be one of the 1.67 + * PLACEHOLDER_FOR_* constants above. 1.68 + */ 1.69 + friend nsIFrame* NS_NewPlaceholderFrame(nsIPresShell* aPresShell, 1.70 + nsStyleContext* aContext, 1.71 + nsFrameState aTypeBit); 1.72 + nsPlaceholderFrame(nsStyleContext* aContext, nsFrameState aTypeBit) 1.73 + : nsFrame(aContext) 1.74 + { 1.75 + NS_PRECONDITION(aTypeBit == PLACEHOLDER_FOR_FLOAT || 1.76 + aTypeBit == PLACEHOLDER_FOR_ABSPOS || 1.77 + aTypeBit == PLACEHOLDER_FOR_FIXEDPOS || 1.78 + aTypeBit == PLACEHOLDER_FOR_POPUP, 1.79 + "Unexpected type bit"); 1.80 + AddStateBits(aTypeBit); 1.81 + } 1.82 + 1.83 + // Get/Set the associated out of flow frame 1.84 + nsIFrame* GetOutOfFlowFrame() const { return mOutOfFlowFrame; } 1.85 + void SetOutOfFlowFrame(nsIFrame* aFrame) { 1.86 + NS_ASSERTION(!aFrame || !aFrame->GetPrevContinuation(), 1.87 + "OOF must be first continuation"); 1.88 + mOutOfFlowFrame = aFrame; 1.89 + } 1.90 + 1.91 + // nsIFrame overrides 1.92 + // We need to override GetMinSize and GetPrefSize because XUL uses 1.93 + // placeholders not within lines. 1.94 + virtual void AddInlineMinWidth(nsRenderingContext* aRenderingContext, 1.95 + InlineMinWidthData* aData) MOZ_OVERRIDE; 1.96 + virtual void AddInlinePrefWidth(nsRenderingContext* aRenderingContext, 1.97 + InlinePrefWidthData* aData) MOZ_OVERRIDE; 1.98 + virtual nsSize GetMinSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; 1.99 + virtual nsSize GetPrefSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; 1.100 + virtual nsSize GetMaxSize(nsBoxLayoutState& aBoxLayoutState) MOZ_OVERRIDE; 1.101 + 1.102 + virtual nsresult Reflow(nsPresContext* aPresContext, 1.103 + nsHTMLReflowMetrics& aDesiredSize, 1.104 + const nsHTMLReflowState& aReflowState, 1.105 + nsReflowStatus& aStatus) MOZ_OVERRIDE; 1.106 + 1.107 + virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; 1.108 + 1.109 +#if defined(DEBUG) || (defined(MOZ_REFLOW_PERF_DSP) && defined(MOZ_REFLOW_PERF)) 1.110 + virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, 1.111 + const nsRect& aDirtyRect, 1.112 + const nsDisplayListSet& aLists) MOZ_OVERRIDE; 1.113 +#endif // DEBUG || (MOZ_REFLOW_PERF_DSP && MOZ_REFLOW_PERF) 1.114 + 1.115 +#ifdef DEBUG_FRAME_DUMP 1.116 + void List(FILE* out = stderr, const char* aPrefix = "", uint32_t aFlags = 0) const MOZ_OVERRIDE; 1.117 + virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; 1.118 +#endif // DEBUG 1.119 + 1.120 + /** 1.121 + * Get the "type" of the frame 1.122 + * 1.123 + * @see nsGkAtoms::placeholderFrame 1.124 + */ 1.125 + virtual nsIAtom* GetType() const MOZ_OVERRIDE; 1.126 + 1.127 + virtual bool IsEmpty() MOZ_OVERRIDE { return true; } 1.128 + virtual bool IsSelfEmpty() MOZ_OVERRIDE { return true; } 1.129 + 1.130 + virtual bool CanContinueTextRun() const MOZ_OVERRIDE; 1.131 + 1.132 +#ifdef ACCESSIBILITY 1.133 + virtual mozilla::a11y::AccType AccessibleType() MOZ_OVERRIDE 1.134 + { 1.135 + nsIFrame* realFrame = GetRealFrameForPlaceholder(this); 1.136 + return realFrame ? realFrame->AccessibleType() : 1.137 + nsFrame::AccessibleType(); 1.138 + } 1.139 +#endif 1.140 + 1.141 + virtual nsIFrame* GetParentStyleContextFrame() const MOZ_OVERRIDE; 1.142 + 1.143 + /** 1.144 + * @return the out-of-flow for aFrame if aFrame is a placeholder; otherwise 1.145 + * aFrame 1.146 + */ 1.147 + static nsIFrame* GetRealFrameFor(nsIFrame* aFrame) { 1.148 + NS_PRECONDITION(aFrame, "Must have a frame to work with"); 1.149 + if (aFrame->GetType() == nsGkAtoms::placeholderFrame) { 1.150 + return GetRealFrameForPlaceholder(aFrame); 1.151 + } 1.152 + return aFrame; 1.153 + } 1.154 + 1.155 + /** 1.156 + * @return the out-of-flow for aFrame, which is known to be a placeholder 1.157 + */ 1.158 + static nsIFrame* GetRealFrameForPlaceholder(nsIFrame* aFrame) { 1.159 + NS_PRECONDITION(aFrame->GetType() == nsGkAtoms::placeholderFrame, 1.160 + "Must have placeholder frame as input"); 1.161 + nsIFrame* outOfFlow = 1.162 + static_cast<nsPlaceholderFrame*>(aFrame)->GetOutOfFlowFrame(); 1.163 + NS_ASSERTION(outOfFlow, "Null out-of-flow for placeholder?"); 1.164 + return outOfFlow; 1.165 + } 1.166 + 1.167 +protected: 1.168 + nsIFrame* mOutOfFlowFrame; 1.169 +}; 1.170 + 1.171 +#endif /* nsPlaceholderFrame_h___ */