Fixed textfield rendering in nsNativeThemeQt
[mozilla-central.git] / layout / generic / nsViewportFrame.cpp
blob0275a1695e4fb4030edee9ca21f1116976f0cf71
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 ***** */
39 * rendering object that is the root of the frame tree, which contains
40 * the document's scrollbars and contains fixed-positioned elements
43 #include "nsCOMPtr.h"
44 #include "nsViewportFrame.h"
45 #include "nsHTMLParts.h"
46 #include "nsGkAtoms.h"
47 #include "nsIScrollableFrame.h"
48 #include "nsDisplayList.h"
50 nsIFrame*
51 NS_NewViewportFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
53 return new (aPresShell) ViewportFrame(aContext);
56 NS_IMETHODIMP
57 ViewportFrame::Init(nsIContent* aContent,
58 nsIFrame* aParent,
59 nsIFrame* aPrevInFlow)
61 return Super::Init(aContent, aParent, aPrevInFlow);
64 void
65 ViewportFrame::Destroy()
67 mFixedContainer.DestroyFrames(this);
68 nsContainerFrame::Destroy();
71 NS_IMETHODIMP
72 ViewportFrame::SetInitialChildList(nsIAtom* aListName,
73 nsIFrame* aChildList)
75 nsresult rv = NS_OK;
77 // See which child list to add the frames to
78 #ifdef NS_DEBUG
79 nsFrame::VerifyDirtyBitSet(aChildList);
80 #endif
81 if (nsGkAtoms::fixedList == aListName) {
82 rv = mFixedContainer.SetInitialChildList(this, aListName, aChildList);
84 else {
85 rv = nsContainerFrame::SetInitialChildList(aListName, aChildList);
88 return rv;
91 NS_IMETHODIMP
92 ViewportFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
93 const nsRect& aDirtyRect,
94 const nsDisplayListSet& aLists)
96 // We don't need any special painting or event handling. We just need to
97 // mark our visible out-of-flow frames (i.e., the fixed position frames) so
98 // that display list construction is guaranteed to recurse into their
99 // ancestors.
100 aBuilder->MarkFramesForDisplayList(this, mFixedContainer.GetFirstChild(), aDirtyRect);
102 nsIFrame* kid = mFrames.FirstChild();
103 if (!kid)
104 return NS_OK;
106 // make the kid's BorderBackground our own. This ensures that the canvas
107 // frame's background becomes our own background and therefore appears
108 // below negative z-index elements.
109 return BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists);
112 NS_IMETHODIMP
113 ViewportFrame::AppendFrames(nsIAtom* aListName,
114 nsIFrame* aFrameList)
116 nsresult rv = NS_OK;
118 if (nsGkAtoms::fixedList == aListName) {
119 rv = mFixedContainer.AppendFrames(this, aListName, aFrameList);
121 else {
122 // We only expect incremental changes for our fixed frames
123 NS_ERROR("unexpected child list");
124 rv = NS_ERROR_INVALID_ARG;
127 return rv;
130 NS_IMETHODIMP
131 ViewportFrame::InsertFrames(nsIAtom* aListName,
132 nsIFrame* aPrevFrame,
133 nsIFrame* aFrameList)
135 nsresult rv = NS_OK;
137 if (nsGkAtoms::fixedList == aListName) {
138 rv = mFixedContainer.InsertFrames(this, aListName, aPrevFrame, aFrameList);
140 else {
141 // We only expect incremental changes for our fixed frames
142 NS_ERROR("unexpected child list");
143 rv = NS_ERROR_INVALID_ARG;
146 return rv;
149 NS_IMETHODIMP
150 ViewportFrame::RemoveFrame(nsIAtom* aListName,
151 nsIFrame* aOldFrame)
153 nsresult rv = NS_OK;
155 if (nsGkAtoms::fixedList == aListName) {
156 rv = mFixedContainer.RemoveFrame(this, aListName, aOldFrame);
158 else {
159 // We only expect incremental changes for our fixed frames
160 NS_ERROR("unexpected child list");
161 rv = NS_ERROR_INVALID_ARG;
164 return rv;
167 nsIAtom*
168 ViewportFrame::GetAdditionalChildListName(PRInt32 aIndex) const
170 NS_PRECONDITION(aIndex >= 0, "illegal index");
172 if (0 == aIndex) {
173 return nsGkAtoms::fixedList;
176 return nsnull;
179 nsIFrame*
180 ViewportFrame::GetFirstChild(nsIAtom* aListName) const
182 if (nsGkAtoms::fixedList == aListName) {
183 nsIFrame* result = nsnull;
184 mFixedContainer.FirstChild(this, aListName, &result);
185 return result;
188 return nsContainerFrame::GetFirstChild(aListName);
191 /* virtual */ nscoord
192 ViewportFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
194 nscoord result;
195 DISPLAY_MIN_WIDTH(this, result);
196 if (mFrames.IsEmpty())
197 result = 0;
198 else
199 result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
201 // XXXldb Deal with mFixedContainer (matters for SizeToContent)!
203 return result;
206 /* virtual */ nscoord
207 ViewportFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
209 nscoord result;
210 DISPLAY_PREF_WIDTH(this, result);
211 if (mFrames.IsEmpty())
212 result = 0;
213 else
214 result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
216 // XXXldb Deal with mFixedContainer (matters for SizeToContent)!
218 return result;
221 nsPoint
222 ViewportFrame::AdjustReflowStateForScrollbars(nsHTMLReflowState* aReflowState) const
224 // Calculate how much room is available for fixed frames. That means
225 // determining if the viewport is scrollable and whether the vertical and/or
226 // horizontal scrollbars are visible
228 // Get our prinicpal child frame and see if we're scrollable
229 nsIFrame* kidFrame = mFrames.FirstChild();
230 nsCOMPtr<nsIScrollableFrame> scrollingFrame(do_QueryInterface(kidFrame));
232 if (scrollingFrame) {
233 nsMargin scrollbars = scrollingFrame->GetActualScrollbarSizes();
234 aReflowState->SetComputedWidth(aReflowState->ComputedWidth() -
235 scrollbars.LeftRight());
236 aReflowState->availableWidth -= scrollbars.LeftRight();
237 aReflowState->SetComputedHeight(aReflowState->ComputedHeight() -
238 scrollbars.TopBottom());
239 // XXX why don't we also adjust "aReflowState->availableHeight"?
240 return nsPoint(scrollbars.left, scrollbars.top);
242 return nsPoint(0, 0);
245 NS_IMETHODIMP
246 ViewportFrame::Reflow(nsPresContext* aPresContext,
247 nsHTMLReflowMetrics& aDesiredSize,
248 const nsHTMLReflowState& aReflowState,
249 nsReflowStatus& aStatus)
251 DO_GLOBAL_REFLOW_COUNT("ViewportFrame");
252 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
253 NS_FRAME_TRACE_REFLOW_IN("ViewportFrame::Reflow");
255 // Initialize OUT parameters
256 aStatus = NS_FRAME_COMPLETE;
258 // Because |Reflow| sets mComputedHeight on the child to
259 // availableHeight.
260 AddStateBits(NS_FRAME_CONTAINS_RELATIVE_HEIGHT);
262 // Reflow the main content first so that the placeholders of the
263 // fixed-position frames will be in the right places on an initial
264 // reflow.
265 nscoord kidHeight = 0;
267 nsresult rv = NS_OK;
269 if (mFrames.NotEmpty()) {
270 // Deal with a non-incremental reflow or an incremental reflow
271 // targeted at our one-and-only principal child frame.
272 if (aReflowState.ShouldReflowAllKids() ||
273 aReflowState.mFlags.mVResize ||
274 NS_SUBTREE_DIRTY(mFrames.FirstChild())) {
275 // Reflow our one-and-only principal child frame
276 nsIFrame* kidFrame = mFrames.FirstChild();
277 nsHTMLReflowMetrics kidDesiredSize;
278 nsSize availableSpace(aReflowState.availableWidth,
279 aReflowState.availableHeight);
280 nsHTMLReflowState kidReflowState(aPresContext, aReflowState,
281 kidFrame, availableSpace);
283 // Reflow the frame
284 kidReflowState.SetComputedHeight(aReflowState.availableHeight);
285 rv = ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
286 0, 0, 0, aStatus);
287 kidHeight = kidDesiredSize.height;
289 FinishReflowChild(kidFrame, aPresContext, nsnull, kidDesiredSize, 0, 0, 0);
290 } else {
291 kidHeight = mFrames.FirstChild()->GetSize().height;
295 NS_ASSERTION(aReflowState.availableWidth != NS_UNCONSTRAINEDSIZE,
296 "shouldn't happen anymore");
298 // Return the max size as our desired size
299 aDesiredSize.width = aReflowState.availableWidth;
300 // Being flowed initially at an unconstrained height means we should
301 // return our child's intrinsic size.
302 aDesiredSize.height = aReflowState.availableHeight != NS_UNCONSTRAINEDSIZE
303 ? aReflowState.availableHeight
304 : kidHeight;
306 // Make a copy of the reflow state and change the computed width and height
307 // to reflect the available space for the fixed items
308 nsHTMLReflowState reflowState(aReflowState);
309 nsPoint offset = AdjustReflowStateForScrollbars(&reflowState);
311 #ifdef DEBUG
312 nsIFrame* f;
313 mFixedContainer.FirstChild(this, nsGkAtoms::fixedList, &f);
314 NS_ASSERTION(!f || (offset.x == 0 && offset.y == 0),
315 "We don't handle correct positioning of fixed frames with "
316 "scrollbars in odd positions");
317 #endif
319 // Just reflow all the fixed-pos frames.
320 rv = mFixedContainer.Reflow(this, aPresContext, reflowState, aStatus,
321 reflowState.ComputedWidth(),
322 reflowState.ComputedHeight(),
323 PR_FALSE, PR_TRUE, PR_TRUE); // XXX could be optimized
325 // If we were dirty then do a repaint
326 if (GetStateBits() & NS_FRAME_IS_DIRTY) {
327 nsRect damageRect(0, 0, aDesiredSize.width, aDesiredSize.height);
328 Invalidate(damageRect, PR_FALSE);
331 // XXX Should we do something to clip our children to this?
332 aDesiredSize.mOverflowArea =
333 nsRect(nsPoint(0, 0), nsSize(aDesiredSize.width, aDesiredSize.height));
335 NS_FRAME_TRACE_REFLOW_OUT("ViewportFrame::Reflow", aStatus);
336 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
337 return rv;
340 nsIAtom*
341 ViewportFrame::GetType() const
343 return nsGkAtoms::viewportFrame;
346 /* virtual */ PRBool
347 ViewportFrame::IsContainingBlock() const
349 return PR_TRUE;
352 void
353 ViewportFrame::InvalidateInternal(const nsRect& aDamageRect,
354 nscoord aX, nscoord aY, nsIFrame* aForChild,
355 PRBool aImmediate)
357 nsIFrame* parent = nsLayoutUtils::GetCrossDocParentFrame(this);
358 if (parent) {
359 nsPoint pt = GetOffsetTo(parent);
360 parent->InvalidateInternal(aDamageRect, aX + pt.x, aY + pt.y, this, aImmediate);
361 return;
363 InvalidateRoot(aDamageRect, aX, aY, aImmediate);
366 #ifdef DEBUG
367 NS_IMETHODIMP
368 ViewportFrame::GetFrameName(nsAString& aResult) const
370 return MakeFrameName(NS_LITERAL_STRING("Viewport"), aResult);
372 #endif