Fixed textfield rendering in nsNativeThemeQt
[mozilla-central.git] / layout / generic / nsPageContentFrame.cpp
blobee0ef24576b19523bb5fd53af2226287e44981f7
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
37 #include "nsPageContentFrame.h"
38 #include "nsPageFrame.h"
39 #include "nsPlaceholderFrame.h"
40 #include "nsCSSFrameConstructor.h"
41 #include "nsHTMLContainerFrame.h"
42 #include "nsHTMLParts.h"
43 #include "nsIContent.h"
44 #include "nsPresContext.h"
45 #include "nsIRenderingContext.h"
46 #include "nsGkAtoms.h"
47 #include "nsIPresShell.h"
48 #include "nsIDeviceContext.h"
49 #include "nsReadableUtils.h"
50 #include "nsSimplePageSequence.h"
51 #include "nsDisplayList.h"
53 nsIFrame*
54 NS_NewPageContentFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
56 return new (aPresShell) nsPageContentFrame(aContext);
59 /* virtual */ nsSize
60 nsPageContentFrame::ComputeSize(nsIRenderingContext *aRenderingContext,
61 nsSize aCBSize, nscoord aAvailableWidth,
62 nsSize aMargin, nsSize aBorder, nsSize aPadding,
63 PRBool aShrinkWrap)
65 NS_ASSERTION(mPD, "Pages are supposed to have page data");
66 nscoord height = (!mPD || mPD->mReflowSize.height == NS_UNCONSTRAINEDSIZE)
67 ? NS_UNCONSTRAINEDSIZE
68 : (mPD->mReflowSize.height - mPD->mReflowMargin.TopBottom());
69 return nsSize(aAvailableWidth, height);
72 /**
73 * Returns true if aFrame is a placeholder for one of our fixed frames.
75 inline PRBool
76 nsPageContentFrame::IsFixedPlaceholder(nsIFrame* aFrame)
78 if (!aFrame || nsGkAtoms::placeholderFrame != aFrame->GetType())
79 return PR_FALSE;
81 return static_cast<nsPlaceholderFrame*>(aFrame)->GetOutOfFlowFrame()
82 ->GetParent() == this;
85 /**
86 * Steals replicated fixed placeholder frames from aDocRoot so they don't
87 * get in the way of reflow.
89 inline nsFrameList
90 nsPageContentFrame::StealFixedPlaceholders(nsIFrame* aDocRoot)
92 nsPresContext* presContext = PresContext();
93 nsFrameList list;
94 if (GetPrevInFlow()) {
95 for (nsIFrame* f = aDocRoot->GetFirstChild(nsnull);
96 IsFixedPlaceholder(f); f = aDocRoot->GetFirstChild(nsnull)) {
97 nsresult rv = static_cast<nsContainerFrame*>(aDocRoot)
98 ->StealFrame(presContext, f);
99 NS_ENSURE_SUCCESS(rv, list);
100 list.AppendFrame(nsnull, f);
103 return list;
107 * Restores stolen replicated fixed placeholder frames to aDocRoot.
109 static inline nsresult
110 ReplaceFixedPlaceholders(nsIFrame* aDocRoot,
111 nsFrameList& aPlaceholderList)
113 nsresult rv = NS_OK;
114 if (aPlaceholderList.NotEmpty()) {
115 rv = static_cast<nsContainerFrame*>(aDocRoot)
116 ->AddFrames(aPlaceholderList.FirstChild(), nsnull);
118 return rv;
121 NS_IMETHODIMP
122 nsPageContentFrame::Reflow(nsPresContext* aPresContext,
123 nsHTMLReflowMetrics& aDesiredSize,
124 const nsHTMLReflowState& aReflowState,
125 nsReflowStatus& aStatus)
127 DO_GLOBAL_REFLOW_COUNT("nsPageContentFrame");
128 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
129 aStatus = NS_FRAME_COMPLETE; // initialize out parameter
130 nsresult rv = NS_OK;
132 // A PageContentFrame must always have one child: the doc root element's frame.
133 // We only need to get overflow frames if we don't already have that child;
134 // Also we need to avoid repeating the call to ReplicateFixedFrames.
135 nsPageContentFrame* prevPageContentFrame = static_cast<nsPageContentFrame*>
136 (GetPrevInFlow());
137 if (mFrames.IsEmpty() && prevPageContentFrame) {
138 // Pull the doc root frame's continuation and copy fixed frames.
139 nsIFrame* overflow = prevPageContentFrame->GetOverflowFrames(aPresContext, PR_TRUE);
140 NS_ASSERTION(overflow && !overflow->GetNextSibling(),
141 "must have doc root as pageContentFrame's only child");
142 nsHTMLContainerFrame::ReparentFrameView(aPresContext, overflow, prevPageContentFrame, this);
143 // Prepend overflow to the page content frame. There may already be
144 // children placeholders which don't get reflowed but must not be
145 // lost until the page content frame is destroyed.
146 mFrames.InsertFrames(this, nsnull, overflow);
147 nsresult rv = aPresContext->PresShell()->FrameConstructor()
148 ->ReplicateFixedFrames(this);
149 NS_ENSURE_SUCCESS(rv, rv);
152 // Resize our frame allowing it only to be as big as we are
153 // XXX Pay attention to the page's border and padding...
154 if (mFrames.NotEmpty()) {
155 nsIFrame* frame = mFrames.FirstChild();
156 nsSize maxSize(aReflowState.availableWidth, aReflowState.availableHeight);
157 nsHTMLReflowState kidReflowState(aPresContext, aReflowState, frame, maxSize);
159 mPD->mPageContentSize = aReflowState.availableWidth;
161 // Get replicated fixed frames' placeholders out of the way
162 nsFrameList stolenPlaceholders = StealFixedPlaceholders(frame);
164 // Reflow the page content area
165 rv = ReflowChild(frame, aPresContext, aDesiredSize, kidReflowState, 0, 0, 0, aStatus);
166 NS_ENSURE_SUCCESS(rv, rv);
168 // Put removed fixed placeholders back
169 rv = ReplaceFixedPlaceholders(frame, stolenPlaceholders);
170 NS_ENSURE_SUCCESS(rv, rv);
172 if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
173 nsIFrame* nextFrame = frame->GetNextInFlow();
174 NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
175 "If it's incomplete and has no nif yet, it must flag a nif reflow.");
176 if (!nextFrame) {
177 nsresult rv = nsHTMLContainerFrame::CreateNextInFlow(aPresContext,
178 this, frame, nextFrame);
179 NS_ENSURE_SUCCESS(rv, rv);
180 frame->SetNextSibling(nextFrame->GetNextSibling());
181 nextFrame->SetNextSibling(nsnull);
182 SetOverflowFrames(aPresContext, nextFrame);
183 // Root overflow containers will be normal children of
184 // the pageContentFrame, but that's ok because there
185 // aren't any other frames we need to isolate them from
186 // during reflow.
188 if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
189 nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
193 // The document element's background should cover the entire canvas, so
194 // take into account the combined area and any space taken up by
195 // absolutely positioned elements
196 nsMargin padding(0,0,0,0);
198 // XXXbz this screws up percentage padding (sets padding to zero
199 // in the percentage padding case)
200 kidReflowState.mStylePadding->GetPadding(padding);
202 // First check the combined area
203 if (NS_FRAME_OUTSIDE_CHILDREN & frame->GetStateBits()) {
204 // The background covers the content area and padding area, so check
205 // for children sticking outside the child frame's padding edge
206 if (aDesiredSize.mOverflowArea.XMost() > aDesiredSize.width) {
207 mPD->mPageContentXMost =
208 aDesiredSize.mOverflowArea.XMost() +
209 kidReflowState.mStyleBorder->GetBorderWidth(NS_SIDE_RIGHT) +
210 padding.right;
214 // Place and size the child
215 FinishReflowChild(frame, aPresContext, &kidReflowState, aDesiredSize, 0, 0, 0);
217 NS_ASSERTION(aPresContext->IsDynamic() || !NS_FRAME_IS_FULLY_COMPLETE(aStatus) ||
218 !frame->GetNextInFlow(), "bad child flow list");
220 // Reflow our fixed frames
221 mFixedContainer.Reflow(this, aPresContext, aReflowState, aStatus,
222 aReflowState.availableWidth,
223 aReflowState.availableHeight,
224 PR_FALSE, PR_TRUE, PR_TRUE); // XXX could be optimized
226 // Return our desired size
227 aDesiredSize.width = aReflowState.availableWidth;
228 if (aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE) {
229 aDesiredSize.height = aReflowState.availableHeight;
232 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
233 return NS_OK;
236 nsIAtom*
237 nsPageContentFrame::GetType() const
239 return nsGkAtoms::pageContentFrame;
242 #ifdef DEBUG
243 NS_IMETHODIMP
244 nsPageContentFrame::GetFrameName(nsAString& aResult) const
246 return MakeFrameName(NS_LITERAL_STRING("PageContent"), aResult);
248 #endif
250 /* virtual */ PRBool
251 nsPageContentFrame::IsContainingBlock() const
253 return PR_TRUE;