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
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.
23 * Michael Ventnor <m.ventnor@gmail.com>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either of the GNU General Public License Version 2 or later (the "GPL"),
27 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 /* base class #2 for rendering objects that have child lists */
41 #include "nsHTMLContainerFrame.h"
42 #include "nsFirstLetterFrame.h"
43 #include "nsIRenderingContext.h"
44 #include "nsPresContext.h"
45 #include "nsIPresShell.h"
46 #include "nsStyleContext.h"
47 #include "nsStyleConsts.h"
48 #include "nsIContent.h"
49 #include "nsGkAtoms.h"
50 #include "nsLayoutUtils.h"
51 #include "nsCSSAnonBoxes.h"
52 #include "nsIWidget.h"
53 #include "nsILinkHandler.h"
54 #include "nsGUIEvent.h"
55 #include "nsIDocument.h"
57 #include "nsPlaceholderFrame.h"
58 #include "nsHTMLParts.h"
60 #include "nsIViewManager.h"
61 #include "nsIDOMEvent.h"
62 #include "nsIScrollableView.h"
63 #include "nsWidgetsCID.h"
65 #include "nsIDeviceContext.h"
66 #include "nsIFontMetrics.h"
67 #include "nsIThebesFontMetrics.h"
69 #include "nsCSSFrameConstructor.h"
70 #include "nsDisplayList.h"
71 #include "nsBlockFrame.h"
72 #include "nsLineBox.h"
73 #include "nsDisplayList.h"
74 #include "nsCSSRendering.h"
76 class nsDisplayTextDecoration
: public nsDisplayItem
{
78 nsDisplayTextDecoration(nsHTMLContainerFrame
* aFrame
, PRUint8 aDecoration
,
79 nscolor aColor
, nsLineBox
* aLine
)
80 : nsDisplayItem(aFrame
), mLine(aLine
), mColor(aColor
),
81 mDecoration(aDecoration
) {
82 MOZ_COUNT_CTOR(nsDisplayTextDecoration
);
84 #ifdef NS_BUILD_REFCNT_LOGGING
85 virtual ~nsDisplayTextDecoration() {
86 MOZ_COUNT_DTOR(nsDisplayTextDecoration
);
90 virtual void Paint(nsDisplayListBuilder
* aBuilder
, nsIRenderingContext
* aCtx
,
91 const nsRect
& aDirtyRect
);
92 virtual nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
);
93 NS_DISPLAY_DECL_NAME("TextDecoration")
101 nsDisplayTextDecoration::Paint(nsDisplayListBuilder
* aBuilder
,
102 nsIRenderingContext
* aCtx
,
103 const nsRect
& aDirtyRect
)
105 nsCOMPtr
<nsIFontMetrics
> fm
;
106 nsLayoutUtils::GetFontMetricsForFrame(mFrame
, getter_AddRefs(fm
));
107 nsIThebesFontMetrics
* tfm
= static_cast<nsIThebesFontMetrics
*>(fm
.get());
108 gfxFontGroup
* fontGroup
= tfm
->GetThebesFontGroup();
109 gfxFont
* firstFont
= fontGroup
->GetFontAt(0);
112 const gfxFont::Metrics
& metrics
= firstFont
->GetMetrics();
115 // The ascent of first-letter frame's text may not be the same as the ascent
116 // of the font metrics. Because that may use the tight box of the actual
118 if (mFrame
->GetType() == nsGkAtoms::letterFrame
) {
119 // Note that nsFirstLetterFrame::GetFirstLetterBaseline() returns
120 // |border-top + padding-top + ascent|. But we only need the ascent value.
121 // Because they will be added in PaintTextDecorationLine.
122 nsFirstLetterFrame
* letterFrame
= static_cast<nsFirstLetterFrame
*>(mFrame
);
123 nscoord tmp
= letterFrame
->GetFirstLetterBaseline();
124 tmp
-= letterFrame
->GetUsedBorderAndPadding().top
;
125 ascent
= letterFrame
->PresContext()->AppUnitsToGfxUnits(tmp
);
127 ascent
= metrics
.maxAscent
;
130 nsPoint pt
= aBuilder
->ToReferenceFrame(mFrame
);
132 nsHTMLContainerFrame
* f
= static_cast<nsHTMLContainerFrame
*>(mFrame
);
133 if (mDecoration
== NS_STYLE_TEXT_DECORATION_UNDERLINE
) {
134 gfxFloat underlineOffset
= fontGroup
->GetUnderlineOffset();
135 f
->PaintTextDecorationLine(aCtx
->ThebesContext(), pt
, mLine
, mColor
,
136 underlineOffset
, ascent
,
137 metrics
.underlineSize
, mDecoration
);
138 } else if (mDecoration
== NS_STYLE_TEXT_DECORATION_OVERLINE
) {
139 f
->PaintTextDecorationLine(aCtx
->ThebesContext(), pt
, mLine
, mColor
,
140 metrics
.maxAscent
, ascent
,
141 metrics
.underlineSize
, mDecoration
);
143 f
->PaintTextDecorationLine(aCtx
->ThebesContext(), pt
, mLine
, mColor
,
144 metrics
.strikeoutOffset
, ascent
,
145 metrics
.strikeoutSize
, mDecoration
);
150 nsDisplayTextDecoration::GetBounds(nsDisplayListBuilder
* aBuilder
)
152 return mFrame
->GetOverflowRect() + aBuilder
->ToReferenceFrame(mFrame
);
155 class nsDisplayTextShadow
: public nsDisplayItem
{
157 nsDisplayTextShadow(nsHTMLContainerFrame
* aFrame
, const PRUint8 aDecoration
,
158 const nscolor
& aColor
, nsLineBox
* aLine
,
159 const nscoord
& aBlurRadius
, const gfxPoint
& aOffset
)
160 : nsDisplayItem(aFrame
), mLine(aLine
), mColor(aColor
),
161 mDecorationFlags(aDecoration
),
162 mBlurRadius(aBlurRadius
), mOffset(aOffset
) {
163 MOZ_COUNT_CTOR(nsDisplayTextShadow
);
165 virtual ~nsDisplayTextShadow() {
166 MOZ_COUNT_DTOR(nsDisplayTextShadow
);
169 virtual void Paint(nsDisplayListBuilder
* aBuilder
, nsIRenderingContext
* aCtx
,
170 const nsRect
& aDirtyRect
);
171 virtual nsRect
GetBounds(nsDisplayListBuilder
* aBuilder
);
172 NS_DISPLAY_DECL_NAME("TextShadow")
176 PRUint8 mDecorationFlags
;
177 nscoord mBlurRadius
; // App units
178 gfxPoint mOffset
; // App units
182 nsDisplayTextShadow::Paint(nsDisplayListBuilder
* aBuilder
,
183 nsIRenderingContext
* aCtx
,
184 const nsRect
& aDirtyRect
)
186 mBlurRadius
= PR_MAX(mBlurRadius
, 0);
188 nsCOMPtr
<nsIFontMetrics
> fm
;
189 nsLayoutUtils::GetFontMetricsForFrame(mFrame
, getter_AddRefs(fm
));
190 nsIThebesFontMetrics
* tfm
= static_cast<nsIThebesFontMetrics
*>(fm
.get());
191 gfxFontGroup
* fontGroup
= tfm
->GetThebesFontGroup();
192 gfxFont
* firstFont
= fontGroup
->GetFontAt(0);
195 const gfxFont::Metrics
& metrics
= firstFont
->GetMetrics();
196 nsPoint pt
= aBuilder
->ToReferenceFrame(mFrame
) + nsPoint(mOffset
.x
, mOffset
.y
);
198 nsHTMLContainerFrame
* f
= static_cast<nsHTMLContainerFrame
*>(mFrame
);
199 nsMargin bp
= f
->GetUsedBorderAndPadding();
200 nscoord innerWidthInAppUnits
= (mFrame
->GetSize().width
- bp
.LeftRight());
202 gfxRect shadowRect
= gfxRect(pt
.x
, pt
.y
, innerWidthInAppUnits
, mFrame
->GetSize().height
);
203 gfxContext
* thebesCtx
= aCtx
->ThebesContext();
205 nsContextBoxBlur contextBoxBlur
;
206 gfxContext
* shadowCtx
= contextBoxBlur
.Init(shadowRect
, mBlurRadius
,
207 mFrame
->PresContext()->AppUnitsPerDevPixel(),
213 thebesCtx
->NewPath();
214 thebesCtx
->SetColor(gfxRGBA(mColor
));
216 if (mDecorationFlags
& NS_STYLE_TEXT_DECORATION_UNDERLINE
) {
217 gfxFloat underlineOffset
= fontGroup
->GetUnderlineOffset();
218 f
->PaintTextDecorationLine(shadowCtx
, pt
, mLine
, mColor
,
219 underlineOffset
, metrics
.maxAscent
,
220 metrics
.underlineSize
, NS_STYLE_TEXT_DECORATION_UNDERLINE
);
222 if (mDecorationFlags
& NS_STYLE_TEXT_DECORATION_OVERLINE
) {
223 f
->PaintTextDecorationLine(shadowCtx
, pt
, mLine
, mColor
,
224 metrics
.maxAscent
, metrics
.maxAscent
,
225 metrics
.underlineSize
, NS_STYLE_TEXT_DECORATION_OVERLINE
);
227 if (mDecorationFlags
& NS_STYLE_TEXT_DECORATION_LINE_THROUGH
) {
228 f
->PaintTextDecorationLine(shadowCtx
, pt
, mLine
, mColor
,
229 metrics
.strikeoutOffset
, metrics
.maxAscent
,
230 metrics
.strikeoutSize
, NS_STYLE_TEXT_DECORATION_LINE_THROUGH
);
233 contextBoxBlur
.DoPaint();
234 thebesCtx
->Restore();
238 nsDisplayTextShadow::GetBounds(nsDisplayListBuilder
* aBuilder
)
240 // Shadows are always painted in the overflow rect
241 return mFrame
->GetOverflowRect() + aBuilder
->ToReferenceFrame(mFrame
);
245 nsHTMLContainerFrame::DisplayTextDecorations(nsDisplayListBuilder
* aBuilder
,
246 nsDisplayList
* aBelowTextDecorations
,
247 nsDisplayList
* aAboveTextDecorations
,
250 if (eCompatibility_NavQuirks
== PresContext()->CompatibilityMode())
252 if (!IsVisibleForPainting(aBuilder
))
255 // Do standards mode painting of 'text-decoration's: under+overline
256 // behind children, line-through in front. For Quirks mode, see
257 // nsTextFrame::PaintTextDecorations. (See bug 1777.)
258 nscolor underColor
, overColor
, strikeColor
;
259 PRUint8 decorations
= NS_STYLE_TEXT_DECORATION_NONE
;
260 GetTextDecorations(PresContext(), aLine
!= nsnull
, decorations
, underColor
,
261 overColor
, strikeColor
);
263 if (decorations
== NS_STYLE_TEXT_DECORATION_NONE
)
266 // The text-shadow spec says that any text decorations must also have a shadow applied to
267 // it. So draw the shadows as part of the display list.
268 const nsStyleText
* textStyle
= GetStyleText();
270 if (textStyle
->mTextShadow
) {
271 for (PRUint32 i
= textStyle
->mTextShadow
->Length(); i
> 0; --i
) {
272 nsCSSShadowItem
* shadow
= textStyle
->mTextShadow
->ShadowAt(i
- 1);
273 nscoord blurRadius
= shadow
->mRadius
.GetCoordValue();
276 if (shadow
->mHasColor
)
277 shadowColor
= shadow
->mColor
;
279 shadowColor
= GetStyleColor()->mColor
;
281 gfxPoint offset
= gfxPoint(shadow
->mXOffset
.GetCoordValue(),
282 shadow
->mYOffset
.GetCoordValue());
284 // Add it to the display list so it is painted underneath the text and all decorations
285 nsresult rv
= aBelowTextDecorations
->AppendNewToTop(new (aBuilder
)
286 nsDisplayTextShadow(this, decorations
, shadowColor
, aLine
, blurRadius
, offset
));
287 NS_ENSURE_SUCCESS(rv
, rv
);
291 if (decorations
& NS_STYLE_TEXT_DECORATION_UNDERLINE
) {
292 nsresult rv
= aBelowTextDecorations
->AppendNewToTop(new (aBuilder
)
293 nsDisplayTextDecoration(this, NS_STYLE_TEXT_DECORATION_UNDERLINE
, underColor
, aLine
));
294 NS_ENSURE_SUCCESS(rv
, rv
);
296 if (decorations
& NS_STYLE_TEXT_DECORATION_OVERLINE
) {
297 nsresult rv
= aBelowTextDecorations
->AppendNewToTop(new (aBuilder
)
298 nsDisplayTextDecoration(this, NS_STYLE_TEXT_DECORATION_OVERLINE
, overColor
, aLine
));
299 NS_ENSURE_SUCCESS(rv
, rv
);
301 if (decorations
& NS_STYLE_TEXT_DECORATION_LINE_THROUGH
) {
302 nsresult rv
= aAboveTextDecorations
->AppendNewToTop(new (aBuilder
)
303 nsDisplayTextDecoration(this, NS_STYLE_TEXT_DECORATION_LINE_THROUGH
, strikeColor
, aLine
));
304 NS_ENSURE_SUCCESS(rv
, rv
);
310 nsHTMLContainerFrame::DisplayTextDecorationsAndChildren(
311 nsDisplayListBuilder
* aBuilder
, const nsRect
& aDirtyRect
,
312 const nsDisplayListSet
& aLists
)
314 nsDisplayList aboveChildrenDecorations
;
315 nsresult rv
= DisplayTextDecorations(aBuilder
, aLists
.Content(),
316 &aboveChildrenDecorations
, nsnull
);
317 NS_ENSURE_SUCCESS(rv
, rv
);
319 rv
= BuildDisplayListForNonBlockChildren(aBuilder
, aDirtyRect
, aLists
,
320 DISPLAY_CHILD_INLINE
);
321 NS_ENSURE_SUCCESS(rv
, rv
);
323 aLists
.Content()->AppendToTop(&aboveChildrenDecorations
);
328 nsHTMLContainerFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
329 const nsRect
& aDirtyRect
,
330 const nsDisplayListSet
& aLists
) {
331 nsresult rv
= DisplayBorderBackgroundOutline(aBuilder
, aLists
);
332 NS_ENSURE_SUCCESS(rv
, rv
);
334 return DisplayTextDecorationsAndChildren(aBuilder
, aDirtyRect
, aLists
);
338 HasTextFrameDescendantOrInFlow(nsIFrame
* aFrame
);
341 nsHTMLContainerFrame::PaintTextDecorationLine(
349 const PRUint8 aDecoration
)
351 NS_ASSERTION(!aLine
, "Should not have passed a linebox to a non-block frame");
352 nsMargin bp
= GetUsedBorderAndPadding();
353 PRIntn skip
= GetSkipSides();
354 NS_FOR_CSS_SIDES(side
) {
355 if (skip
& (1 << side
)) {
359 nscoord innerWidth
= mRect
.width
- bp
.left
- bp
.right
;
360 gfxPoint
pt(PresContext()->AppUnitsToGfxUnits(bp
.left
+ aPt
.x
),
361 PresContext()->AppUnitsToGfxUnits(bp
.top
+ aPt
.y
));
362 gfxSize
size(PresContext()->AppUnitsToGfxUnits(innerWidth
), aSize
);
363 nsCSSRendering::PaintDecorationLine(aCtx
, aColor
, pt
, size
, aAscent
, aOffset
,
364 aDecoration
, NS_STYLE_BORDER_STYLE_SOLID
);
368 nsHTMLContainerFrame::GetTextDecorations(nsPresContext
* aPresContext
,
370 PRUint8
& aDecorations
,
371 nscolor
& aUnderColor
,
373 nscolor
& aStrikeColor
)
375 aDecorations
= NS_STYLE_TEXT_DECORATION_NONE
;
376 if (!mStyleContext
->HasTextDecorations()) {
377 // This is a necessary, but not sufficient, condition for text
382 // A mask of all possible decorations.
383 PRUint8 decorMask
= NS_STYLE_TEXT_DECORATION_UNDERLINE
|
384 NS_STYLE_TEXT_DECORATION_OVERLINE
|
385 NS_STYLE_TEXT_DECORATION_LINE_THROUGH
;
388 aDecorations
= GetStyleTextReset()->mTextDecoration
& decorMask
;
390 const nsStyleColor
* styleColor
= GetStyleColor();
391 aUnderColor
= styleColor
->mColor
;
392 aOverColor
= styleColor
->mColor
;
393 aStrikeColor
= styleColor
->mColor
;
398 for (nsIFrame
*frame
= this; frame
&& decorMask
; frame
= frame
->GetParent()) {
399 // find text-decorations. "Inherit" from parent *block* frames
401 nsStyleContext
* styleContext
= frame
->GetStyleContext();
402 const nsStyleDisplay
* styleDisplay
= styleContext
->GetStyleDisplay();
403 if (!styleDisplay
->IsBlockInside() &&
404 styleDisplay
->mDisplay
!= NS_STYLE_DISPLAY_TABLE_CELL
&&
405 styleDisplay
->mDisplay
!= NS_STYLE_DISPLAY_TABLE_CAPTION
) {
406 // If an inline frame is discovered while walking up the tree,
407 // we should stop according to CSS3 draft. CSS2 is rather vague
412 const nsStyleTextReset
* styleText
= styleContext
->GetStyleTextReset();
413 PRUint8 decors
= decorMask
& styleText
->mTextDecoration
;
415 // A *new* text-decoration is found.
416 nscolor color
= styleContext
->GetStyleColor()->mColor
;
418 if (NS_STYLE_TEXT_DECORATION_UNDERLINE
& decors
) {
420 decorMask
&= ~NS_STYLE_TEXT_DECORATION_UNDERLINE
;
421 aDecorations
|= NS_STYLE_TEXT_DECORATION_UNDERLINE
;
423 if (NS_STYLE_TEXT_DECORATION_OVERLINE
& decors
) {
425 decorMask
&= ~NS_STYLE_TEXT_DECORATION_OVERLINE
;
426 aDecorations
|= NS_STYLE_TEXT_DECORATION_OVERLINE
;
428 if (NS_STYLE_TEXT_DECORATION_LINE_THROUGH
& decors
) {
429 aStrikeColor
= color
;
430 decorMask
&= ~NS_STYLE_TEXT_DECORATION_LINE_THROUGH
;
431 aDecorations
|= NS_STYLE_TEXT_DECORATION_LINE_THROUGH
;
438 // If this frame contains no text, we're required to ignore this property
439 if (!HasTextFrameDescendantOrInFlow(this)) {
440 aDecorations
= NS_STYLE_TEXT_DECORATION_NONE
;
446 HasTextFrameDescendant(nsIFrame
* aParent
)
448 for (nsIFrame
* kid
= aParent
->GetFirstChild(nsnull
); kid
;
449 kid
= kid
->GetNextSibling())
451 if (kid
->GetType() == nsGkAtoms::textFrame
) {
452 // This is only a candidate. We need to determine if this text
453 // frame is empty, as in containing only (non-pre) whitespace.
455 if (!kid
->IsEmpty()) {
459 if (HasTextFrameDescendant(kid
)) {
467 HasTextFrameDescendantOrInFlow(nsIFrame
* aFrame
)
469 for (nsIFrame
*f
= aFrame
->GetFirstInFlow(); f
; f
= f
->GetNextInFlow()) {
470 if (HasTextFrameDescendant(f
))
477 * Create a next-in-flow for aFrame. Will return the newly created
478 * frame in aNextInFlowResult <b>if and only if</b> a new frame is
479 * created; otherwise nsnull is returned in aNextInFlowResult.
482 nsHTMLContainerFrame::CreateNextInFlow(nsPresContext
* aPresContext
,
483 nsIFrame
* aOuterFrame
,
485 nsIFrame
*& aNextInFlowResult
)
487 aNextInFlowResult
= nsnull
;
489 nsIFrame
* nextInFlow
= aFrame
->GetNextInFlow();
490 if (nsnull
== nextInFlow
) {
491 // Create a continuation frame for the child frame and insert it
492 // into our lines child list.
493 nsIFrame
* nextFrame
= aFrame
->GetNextSibling();
495 nsresult rv
= aPresContext
->PresShell()->FrameConstructor()->
496 CreateContinuingFrame(aPresContext
, aFrame
, aOuterFrame
, &nextInFlow
);
500 aFrame
->SetNextSibling(nextInFlow
);
501 nextInFlow
->SetNextSibling(nextFrame
);
503 NS_FRAME_LOG(NS_FRAME_TRACE_NEW_FRAMES
,
504 ("nsHTMLContainerFrame::CreateNextInFlow: frame=%p nextInFlow=%p",
505 aFrame
, nextInFlow
));
507 aNextInFlowResult
= nextInFlow
;
513 ReparentFrameViewTo(nsIFrame
* aFrame
,
514 nsIViewManager
* aViewManager
,
515 nsIView
* aNewParentView
,
516 nsIView
* aOldParentView
)
519 // XXX What to do about placeholder views for "position: fixed" elements?
520 // They should be reparented too.
522 // Does aFrame have a view?
523 if (aFrame
->HasView()) {
524 nsIView
* view
= aFrame
->GetView();
525 // Verify that the current parent view is what we think it is
526 //nsIView* parentView;
527 //NS_ASSERTION(parentView == aOldParentView, "unexpected parent view");
529 aViewManager
->RemoveChild(view
);
531 // The view will remember the Z-order and other attributes that have been set on it.
532 nsIView
* insertBefore
= nsLayoutUtils::FindSiblingViewFor(aNewParentView
, aFrame
);
533 aViewManager
->InsertChild(aNewParentView
, view
, insertBefore
, insertBefore
!= nsnull
);
535 PRInt32 listIndex
= 0;
536 nsIAtom
* listName
= nsnull
;
537 // This loop iterates through every child list name, and also
538 // executes once with listName == nsnull.
540 // Iterate the child frames, and check each child frame to see if it has
542 nsIFrame
* childFrame
= aFrame
->GetFirstChild(listName
);
543 for (; childFrame
; childFrame
= childFrame
->GetNextSibling()) {
544 ReparentFrameViewTo(childFrame
, aViewManager
,
545 aNewParentView
, aOldParentView
);
547 listName
= aFrame
->GetAdditionalChildListName(listIndex
++);
555 nsHTMLContainerFrame::ReparentFrameView(nsPresContext
* aPresContext
,
556 nsIFrame
* aChildFrame
,
557 nsIFrame
* aOldParentFrame
,
558 nsIFrame
* aNewParentFrame
)
560 NS_PRECONDITION(aChildFrame
, "null child frame pointer");
561 NS_PRECONDITION(aOldParentFrame
, "null old parent frame pointer");
562 NS_PRECONDITION(aNewParentFrame
, "null new parent frame pointer");
563 NS_PRECONDITION(aOldParentFrame
!= aNewParentFrame
, "same old and new parent frame");
565 // See if either the old parent frame or the new parent frame have a view
566 while (!aOldParentFrame
->HasView() && !aNewParentFrame
->HasView()) {
567 // Walk up both the old parent frame and the new parent frame nodes
568 // stopping when we either find a common parent or views for one
569 // or both of the frames.
571 // This works well in the common case where we push/pull and the old parent
572 // frame and the new parent frame are part of the same flow. They will
573 // typically be the same distance (height wise) from the
574 aOldParentFrame
= aOldParentFrame
->GetParent();
575 aNewParentFrame
= aNewParentFrame
->GetParent();
577 // We should never walk all the way to the root frame without finding
579 NS_ASSERTION(aOldParentFrame
&& aNewParentFrame
, "didn't find view");
581 // See if we reached a common ancestor
582 if (aOldParentFrame
== aNewParentFrame
) {
587 // See if we found a common parent frame
588 if (aOldParentFrame
== aNewParentFrame
) {
589 // We found a common parent and there are no views between the old parent
590 // and the common parent or the new parent frame and the common parent.
591 // Because neither the old parent frame nor the new parent frame have views,
592 // then any child views don't need reparenting
596 // We found views for one or both of the ancestor frames before we
597 // found a common ancestor.
598 nsIView
* oldParentView
= aOldParentFrame
->GetClosestView();
599 nsIView
* newParentView
= aNewParentFrame
->GetClosestView();
601 // See if the old parent frame and the new parent frame are in the
602 // same view sub-hierarchy. If they are then we don't have to do
604 if (oldParentView
!= newParentView
) {
605 // They're not so we need to reparent any child views
606 return ReparentFrameViewTo(aChildFrame
, oldParentView
->GetViewManager(), newParentView
,
614 nsHTMLContainerFrame::ReparentFrameViewList(nsPresContext
* aPresContext
,
615 nsIFrame
* aChildFrameList
,
616 nsIFrame
* aOldParentFrame
,
617 nsIFrame
* aNewParentFrame
)
619 NS_PRECONDITION(aChildFrameList
, "null child frame list");
620 NS_PRECONDITION(aOldParentFrame
, "null old parent frame pointer");
621 NS_PRECONDITION(aNewParentFrame
, "null new parent frame pointer");
622 NS_PRECONDITION(aOldParentFrame
!= aNewParentFrame
, "same old and new parent frame");
624 // See if either the old parent frame or the new parent frame have a view
625 while (!aOldParentFrame
->HasView() && !aNewParentFrame
->HasView()) {
626 // Walk up both the old parent frame and the new parent frame nodes
627 // stopping when we either find a common parent or views for one
628 // or both of the frames.
630 // This works well in the common case where we push/pull and the old parent
631 // frame and the new parent frame are part of the same flow. They will
632 // typically be the same distance (height wise) from the
633 aOldParentFrame
= aOldParentFrame
->GetParent();
634 aNewParentFrame
= aNewParentFrame
->GetParent();
636 // We should never walk all the way to the root frame without finding
638 NS_ASSERTION(aOldParentFrame
&& aNewParentFrame
, "didn't find view");
640 // See if we reached a common ancestor
641 if (aOldParentFrame
== aNewParentFrame
) {
647 // See if we found a common parent frame
648 if (aOldParentFrame
== aNewParentFrame
) {
649 // We found a common parent and there are no views between the old parent
650 // and the common parent or the new parent frame and the common parent.
651 // Because neither the old parent frame nor the new parent frame have views,
652 // then any child views don't need reparenting
656 // We found views for one or both of the ancestor frames before we
657 // found a common ancestor.
658 nsIView
* oldParentView
= aOldParentFrame
->GetClosestView();
659 nsIView
* newParentView
= aNewParentFrame
->GetClosestView();
661 // See if the old parent frame and the new parent frame are in the
662 // same view sub-hierarchy. If they are then we don't have to do
664 if (oldParentView
!= newParentView
) {
665 nsIViewManager
* viewManager
= oldParentView
->GetViewManager();
667 // They're not so we need to reparent any child views
668 for (nsIFrame
* f
= aChildFrameList
; f
; f
= f
->GetNextSibling()) {
669 ReparentFrameViewTo(f
, viewManager
, newParentView
,
678 nsHTMLContainerFrame::CreateViewForFrame(nsIFrame
* aFrame
,
679 nsIFrame
* aContentParentFrame
,
682 if (aFrame
->HasView()) {
686 // If we don't yet have a view, see if we need a view
687 if (!(aForce
|| FrameNeedsView(aFrame
))) {
692 nsIView
* parentView
= aFrame
->GetParent()->GetParentViewForChildFrame(aFrame
);
693 NS_ASSERTION(parentView
, "no parent with view");
695 nsIViewManager
* viewManager
= parentView
->GetViewManager();
696 NS_ASSERTION(viewManager
, "null view manager");
699 nsIView
* view
= viewManager
->CreateView(aFrame
->GetRect(), parentView
);
701 return NS_ERROR_OUT_OF_MEMORY
;
703 SyncFrameViewProperties(aFrame
->PresContext(), aFrame
, nsnull
, view
);
705 // Insert the view into the view hierarchy. If the parent view is a
706 // scrolling view we need to do this differently
707 nsIScrollableView
* scrollingView
= parentView
->ToScrollableView();
709 scrollingView
->SetScrolledView(view
);
711 nsIView
* insertBefore
= nsLayoutUtils::FindSiblingViewFor(parentView
, aFrame
);
712 // we insert this view 'above' the insertBefore view, unless insertBefore is null,
713 // in which case we want to call with aAbove == PR_FALSE to insert at the beginning
715 viewManager
->InsertChild(parentView
, view
, insertBefore
, insertBefore
!= nsnull
);
718 // REVIEW: Don't create a widget for fixed-pos elements anymore.
719 // ComputeRepaintRegionForCopy will calculate the right area to repaint
721 // Reparent views on any child frames (or their descendants) to this
722 // view. We can just call ReparentFrameViewTo on this frame because
723 // we know this frame has no view, so it will crawl the children. Also,
724 // we know that any descendants with views must have 'parentView' as their
726 ReparentFrameViewTo(aFrame
, viewManager
, view
, parentView
);
729 aFrame
->SetView(view
);
731 NS_FRAME_LOG(NS_FRAME_TRACE_CALLS
,
732 ("nsHTMLContainerFrame::CreateViewForFrame: frame=%p view=%p",