Fixed regex LIR to be x64 compliant (bug 514548, r=lw).
[mozilla-central.git] / layout / generic / nsHTMLFrame.cpp
blob005943449469bebae978a70afd5ee11e05895179
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 ***** */
38 /* rendering object that goes directly inside the document's scrollbars */
40 #include "nsIServiceManager.h"
41 #include "nsHTMLParts.h"
42 #include "nsHTMLContainerFrame.h"
43 #include "nsCSSRendering.h"
44 #include "nsPresContext.h"
45 #include "nsStyleContext.h"
46 #include "nsIView.h"
47 #include "nsIViewManager.h"
48 #include "nsIRenderingContext.h"
49 #include "nsGUIEvent.h"
50 #include "nsStyleConsts.h"
51 #include "nsGkAtoms.h"
52 #include "nsIEventStateManager.h"
53 #include "nsIDeviceContext.h"
54 #include "nsIPresShell.h"
55 #include "nsIScrollPositionListener.h"
56 #include "nsDisplayList.h"
57 #include "nsAbsoluteContainingBlock.h"
59 // for focus
60 #include "nsIDOMWindowInternal.h"
61 #include "nsIScrollableFrame.h"
62 #include "nsIScrollableView.h"
63 #include "nsIDocShell.h"
64 #include "nsICanvasFrame.h"
66 #ifdef DEBUG_rods
67 //#define DEBUG_CANVAS_FOCUS
68 #endif
70 #define CANVAS_ABS_POS_CHILD_LIST NS_CONTAINER_LIST_COUNT_INCL_OC
72 // Interface IDs
74 /**
75 * Root frame class.
77 * The root frame is the parent frame for the document element's frame.
78 * It only supports having a single child frame which must be an area
79 * frame
81 class CanvasFrame : public nsHTMLContainerFrame,
82 public nsIScrollPositionListener,
83 public nsICanvasFrame {
84 public:
85 CanvasFrame(nsStyleContext* aContext)
86 : nsHTMLContainerFrame(aContext), mDoPaintFocus(PR_FALSE),
87 mAbsoluteContainer(nsGkAtoms::absoluteList) {}
89 NS_DECL_QUERYFRAME
91 // nsISupports (nsIScrollPositionListener)
92 NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
94 NS_IMETHOD Init(nsIContent* aContent,
95 nsIFrame* aParent,
96 nsIFrame* aPrevInFlow);
97 virtual void Destroy();
99 NS_IMETHOD SetInitialChildList(nsIAtom* aListName,
100 nsFrameList& aChildList);
101 NS_IMETHOD AppendFrames(nsIAtom* aListName,
102 nsFrameList& aFrameList);
103 NS_IMETHOD InsertFrames(nsIAtom* aListName,
104 nsIFrame* aPrevFrame,
105 nsFrameList& aFrameList);
106 NS_IMETHOD RemoveFrame(nsIAtom* aListName,
107 nsIFrame* aOldFrame);
109 virtual nsIAtom* GetAdditionalChildListName(PRInt32 aIndex) const;
110 virtual nsFrameList GetChildList(nsIAtom* aListName) const;
112 virtual nscoord GetMinWidth(nsIRenderingContext *aRenderingContext);
113 virtual nscoord GetPrefWidth(nsIRenderingContext *aRenderingContext);
114 NS_IMETHOD Reflow(nsPresContext* aPresContext,
115 nsHTMLReflowMetrics& aDesiredSize,
116 const nsHTMLReflowState& aReflowState,
117 nsReflowStatus& aStatus);
118 virtual PRBool IsContainingBlock() const { return PR_TRUE; }
119 virtual PRBool IsFrameOfType(PRUint32 aFlags) const
121 return nsHTMLContainerFrame::IsFrameOfType(aFlags &
122 ~(nsIFrame::eCanContainOverflowContainers));
125 NS_IMETHOD BuildDisplayList(nsDisplayListBuilder* aBuilder,
126 const nsRect& aDirtyRect,
127 const nsDisplayListSet& aLists);
129 void PaintFocus(nsIRenderingContext& aRenderingContext, nsPoint aPt);
131 // nsIScrollPositionListener
132 NS_IMETHOD ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
133 virtual void ViewPositionDidChange(nsIScrollableView* aScrollable,
134 nsTArray<nsIWidget::Configuration>* aConfigurations) {}
135 NS_IMETHOD ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY);
137 // nsICanvasFrame
138 NS_IMETHOD SetHasFocus(PRBool aHasFocus);
141 * Get the "type" of the frame
143 * @see nsGkAtoms::canvasFrame
145 virtual nsIAtom* GetType() const;
147 virtual nsresult StealFrame(nsPresContext* aPresContext,
148 nsIFrame* aChild,
149 PRBool aForceNormal)
151 NS_ASSERTION(!aForceNormal, "No-one should be passing this in here");
153 // CanvasFrame keeps overflow container continuations of its child
154 // frame in main child list
155 nsresult rv = nsContainerFrame::StealFrame(aPresContext, aChild, PR_TRUE);
156 if (NS_FAILED(rv)) {
157 rv = nsContainerFrame::StealFrame(aPresContext, aChild);
159 return rv;
162 #ifdef DEBUG
163 NS_IMETHOD GetFrameName(nsAString& aResult) const;
164 #endif
165 NS_IMETHOD GetContentForEvent(nsPresContext* aPresContext,
166 nsEvent* aEvent,
167 nsIContent** aContent);
169 nsRect CanvasArea() const;
171 protected:
172 virtual PRIntn GetSkipSides() const;
174 // Data members
175 PRPackedBool mDoPaintFocus;
176 nsCOMPtr<nsIViewManager> mViewManager;
177 nsAbsoluteContainingBlock mAbsoluteContainer;
179 private:
180 NS_IMETHOD_(nsrefcnt) AddRef() { return NS_OK; }
181 NS_IMETHOD_(nsrefcnt) Release() { return NS_OK; }
185 //----------------------------------------------------------------------
187 nsIFrame*
188 NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
190 return new (aPresShell)CanvasFrame(aContext);
193 NS_IMPL_QUERY_INTERFACE1(CanvasFrame, nsIScrollPositionListener)
195 NS_QUERYFRAME_HEAD(CanvasFrame)
196 NS_QUERYFRAME_ENTRY(nsICanvasFrame)
197 NS_QUERYFRAME_TAIL_INHERITING(nsHTMLContainerFrame)
199 NS_IMETHODIMP
200 CanvasFrame::Init(nsIContent* aContent,
201 nsIFrame* aParent,
202 nsIFrame* aPrevInFlow)
204 nsresult rv = nsHTMLContainerFrame::Init(aContent, aParent, aPrevInFlow);
206 mViewManager = PresContext()->GetPresShell()->GetViewManager();
208 nsIScrollableView* scrollingView = nsnull;
209 mViewManager->GetRootScrollableView(&scrollingView);
210 if (scrollingView) {
211 scrollingView->AddScrollPositionListener(this);
214 return rv;
217 void
218 CanvasFrame::Destroy()
220 mAbsoluteContainer.DestroyFrames(this);
222 nsIScrollableView* scrollingView = nsnull;
223 mViewManager->GetRootScrollableView(&scrollingView);
224 if (scrollingView) {
225 scrollingView->RemoveScrollPositionListener(this);
228 nsHTMLContainerFrame::Destroy();
231 NS_IMETHODIMP
232 CanvasFrame::ScrollPositionWillChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
234 #ifdef DEBUG_CANVAS_FOCUS
236 PRBool hasFocus = PR_FALSE;
237 nsCOMPtr<nsIViewObserver> observer;
238 mViewManager->GetViewObserver(*getter_AddRefs(observer));
239 nsCOMPtr<nsIPresShell> shell = do_QueryInterface(observer);
240 nsCOMPtr<nsPresContext> context;
241 shell->GetPresContext(getter_AddRefs(context));
242 nsCOMPtr<nsISupports> container;
243 context->GetContainer(getter_AddRefs(container));
244 nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
245 if (docShell) {
246 docShell->GetHasFocus(&hasFocus);
248 printf("SPWC: %p HF: %s mDoPaintFocus: %s\n", docShell.get(), hasFocus?"Y":"N", mDoPaintFocus?"Y":"N");
250 #endif
252 if (mDoPaintFocus) {
253 mDoPaintFocus = PR_FALSE;
254 mViewManager->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
256 return NS_OK;
259 NS_IMETHODIMP
260 CanvasFrame::ScrollPositionDidChange(nsIScrollableView* aScrollable, nscoord aX, nscoord aY)
262 return NS_OK;
265 NS_IMETHODIMP
266 CanvasFrame::SetHasFocus(PRBool aHasFocus)
268 if (mDoPaintFocus != aHasFocus) {
269 mDoPaintFocus = aHasFocus;
270 mViewManager->UpdateAllViews(NS_VMREFRESH_NO_SYNC);
272 return NS_OK;
275 NS_IMETHODIMP
276 CanvasFrame::SetInitialChildList(nsIAtom* aListName,
277 nsFrameList& aChildList)
279 if (nsGkAtoms::absoluteList == aListName)
280 return mAbsoluteContainer.SetInitialChildList(this, aListName, aChildList);
282 NS_ASSERTION(aListName || aChildList.IsEmpty() || aChildList.OnlyChild(),
283 "Primary child list can have at most one frame in it");
284 return nsHTMLContainerFrame::SetInitialChildList(aListName, aChildList);
287 NS_IMETHODIMP
288 CanvasFrame::AppendFrames(nsIAtom* aListName,
289 nsFrameList& aFrameList)
291 nsresult rv;
293 if (nsGkAtoms::absoluteList == aListName)
294 return mAbsoluteContainer.AppendFrames(this, aListName, aFrameList);
296 NS_ASSERTION(!aListName, "unexpected child list name");
297 NS_PRECONDITION(mFrames.IsEmpty(), "already have a child frame");
298 if (aListName) {
299 // We only support unnamed principal child list
300 rv = NS_ERROR_INVALID_ARG;
302 } else if (!mFrames.IsEmpty()) {
303 // We only allow a single child frame
304 rv = NS_ERROR_FAILURE;
306 } else {
307 // Insert the new frames
308 NS_ASSERTION(aFrameList.FirstChild() == aFrameList.LastChild(),
309 "Only one principal child frame allowed");
310 #ifdef NS_DEBUG
311 nsFrame::VerifyDirtyBitSet(aFrameList);
312 #endif
313 mFrames.AppendFrames(nsnull, aFrameList);
315 rv = PresContext()->PresShell()->
316 FrameNeedsReflow(this, nsIPresShell::eTreeChange,
317 NS_FRAME_HAS_DIRTY_CHILDREN);
320 return rv;
323 NS_IMETHODIMP
324 CanvasFrame::InsertFrames(nsIAtom* aListName,
325 nsIFrame* aPrevFrame,
326 nsFrameList& aFrameList)
328 nsresult rv;
330 if (nsGkAtoms::absoluteList == aListName)
331 return mAbsoluteContainer.InsertFrames(this, aListName, aPrevFrame, aFrameList);
333 // Because we only support a single child frame inserting is the same
334 // as appending
335 NS_PRECONDITION(!aPrevFrame, "unexpected previous sibling frame");
336 if (aPrevFrame) {
337 rv = NS_ERROR_UNEXPECTED;
338 } else {
339 rv = AppendFrames(aListName, aFrameList);
342 return rv;
345 NS_IMETHODIMP
346 CanvasFrame::RemoveFrame(nsIAtom* aListName,
347 nsIFrame* aOldFrame)
349 nsresult rv;
351 if (nsGkAtoms::absoluteList == aListName)
352 return mAbsoluteContainer.RemoveFrame(this, aListName, aOldFrame);
354 NS_ASSERTION(!aListName, "unexpected child list name");
355 if (aListName) {
356 // We only support the unnamed principal child list
357 rv = NS_ERROR_INVALID_ARG;
359 } else if (aOldFrame == mFrames.FirstChild()) {
360 // It's our one and only child frame
361 // Damage the area occupied by the deleted frame
362 // The child of the canvas probably can't have an outline, but why bother
363 // thinking about that?
364 Invalidate(aOldFrame->GetOverflowRect() + aOldFrame->GetPosition());
366 // Remove the frame and destroy it
367 mFrames.DestroyFrame(aOldFrame);
369 rv = PresContext()->PresShell()->
370 FrameNeedsReflow(this, nsIPresShell::eTreeChange,
371 NS_FRAME_HAS_DIRTY_CHILDREN);
372 } else {
373 rv = NS_ERROR_FAILURE;
376 return rv;
379 nsIAtom*
380 CanvasFrame::GetAdditionalChildListName(PRInt32 aIndex) const
382 if (CANVAS_ABS_POS_CHILD_LIST == aIndex)
383 return nsGkAtoms::absoluteList;
385 return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex);
388 nsFrameList
389 CanvasFrame::GetChildList(nsIAtom* aListName) const
391 if (nsGkAtoms::absoluteList == aListName)
392 return mAbsoluteContainer.GetChildList();
394 return nsHTMLContainerFrame::GetChildList(aListName);
397 nsRect CanvasFrame::CanvasArea() const
399 nsRect result(GetOverflowRect());
401 nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
402 if (scrollableFrame) {
403 nsIScrollableView* scrollableView = scrollableFrame->GetScrollableView();
404 nsRect vcr = scrollableView->View()->GetBounds();
405 result.UnionRect(result, nsRect(nsPoint(0, 0), vcr.Size()));
407 return result;
411 * Override nsDisplayBackground methods so that we pass aBGClipRect to
412 * PaintBackground, covering the whole overflow area.
414 class nsDisplayCanvasBackground : public nsDisplayBackground {
415 public:
416 nsDisplayCanvasBackground(nsIFrame *aFrame)
417 : nsDisplayBackground(aFrame)
421 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
423 CanvasFrame* frame = static_cast<CanvasFrame*>(mFrame);
424 return frame->CanvasArea() + aBuilder->ToReferenceFrame(mFrame);
427 virtual void Paint(nsDisplayListBuilder* aBuilder,
428 nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
430 CanvasFrame* frame = static_cast<CanvasFrame*>(mFrame);
431 nsPoint offset = aBuilder->ToReferenceFrame(mFrame);
432 nsRect bgClipRect = frame->CanvasArea() + offset;
433 nsCSSRendering::PaintBackground(mFrame->PresContext(), *aCtx, mFrame,
434 aDirtyRect,
435 nsRect(offset, mFrame->GetSize()),
436 0, &bgClipRect);
439 NS_DISPLAY_DECL_NAME("CanvasBackground")
443 * A display item to paint the focus ring for the document.
445 * The only reason this can't use nsDisplayGeneric is overriding GetBounds.
447 class nsDisplayCanvasFocus : public nsDisplayItem {
448 public:
449 nsDisplayCanvasFocus(CanvasFrame *aFrame)
450 : nsDisplayItem(aFrame)
454 virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder)
456 // This is an overestimate, but that's not a problem.
457 CanvasFrame* frame = static_cast<CanvasFrame*>(mFrame);
458 return frame->CanvasArea() + aBuilder->ToReferenceFrame(mFrame);
461 virtual void Paint(nsDisplayListBuilder* aBuilder,
462 nsIRenderingContext* aCtx, const nsRect& aDirtyRect)
464 CanvasFrame* frame = static_cast<CanvasFrame*>(mFrame);
465 frame->PaintFocus(*aCtx, aBuilder->ToReferenceFrame(mFrame));
468 NS_DISPLAY_DECL_NAME("CanvasFocus")
471 NS_IMETHODIMP
472 CanvasFrame::BuildDisplayList(nsDisplayListBuilder* aBuilder,
473 const nsRect& aDirtyRect,
474 const nsDisplayListSet& aLists)
476 nsresult rv;
478 if (GetPrevInFlow()) {
479 DisplayOverflowContainers(aBuilder, aDirtyRect, aLists);
482 aBuilder->MarkFramesForDisplayList(this, mAbsoluteContainer.GetChildList(),
483 aDirtyRect);
485 // Force a background to be shown. We may have a background propagated to us,
486 // in which case GetStyleBackground wouldn't have the right background
487 // and the code in nsFrame::DisplayBorderBackgroundOutline might not give us
488 // a background.
489 // We don't have any border or outline, and our background draws over
490 // the overflow area, so just add nsDisplayCanvasBackground instead of
491 // calling DisplayBorderBackgroundOutline.
492 if (IsVisibleForPainting(aBuilder)) {
493 rv = aLists.BorderBackground()->AppendNewToTop(new (aBuilder)
494 nsDisplayCanvasBackground(this));
495 NS_ENSURE_SUCCESS(rv, rv);
498 nsIFrame* kid;
499 for (kid = GetFirstChild(nsnull); kid; kid = kid->GetNextSibling()) {
500 // Put our child into its own pseudo-stack.
501 rv = BuildDisplayListForChild(aBuilder, kid, aDirtyRect, aLists,
502 DISPLAY_CHILD_FORCE_PSEUDO_STACKING_CONTEXT);
503 NS_ENSURE_SUCCESS(rv, rv);
506 #ifdef DEBUG_CANVAS_FOCUS
507 nsCOMPtr<nsIContent> focusContent;
508 aPresContext->EventStateManager()->
509 GetFocusedContent(getter_AddRefs(focusContent));
511 PRBool hasFocus = PR_FALSE;
512 nsCOMPtr<nsISupports> container;
513 aPresContext->GetContainer(getter_AddRefs(container));
514 nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(container));
515 if (docShell) {
516 docShell->GetHasFocus(&hasFocus);
517 printf("%p - CanvasFrame::Paint R:%d,%d,%d,%d DR: %d,%d,%d,%d\n", this,
518 mRect.x, mRect.y, mRect.width, mRect.height,
519 aDirtyRect.x, aDirtyRect.y, aDirtyRect.width, aDirtyRect.height);
521 printf("%p - Focus: %s c: %p DoPaint:%s\n", docShell.get(), hasFocus?"Y":"N",
522 focusContent.get(), mDoPaintFocus?"Y":"N");
523 #endif
525 if (!mDoPaintFocus)
526 return NS_OK;
527 // Only paint the focus if we're visible
528 if (!GetStyleVisibility()->IsVisible())
529 return NS_OK;
531 return aLists.Outlines()->AppendNewToTop(new (aBuilder)
532 nsDisplayCanvasFocus(this));
535 void
536 CanvasFrame::PaintFocus(nsIRenderingContext& aRenderingContext, nsPoint aPt)
538 nsRect focusRect(aPt, GetSize());
540 nsIScrollableFrame *scrollableFrame = do_QueryFrame(GetParent());
541 if (scrollableFrame) {
542 nsIScrollableView* scrollableView = scrollableFrame->GetScrollableView();
543 nsRect vcr = scrollableView->View()->GetBounds();
544 focusRect.width = vcr.width;
545 focusRect.height = vcr.height;
546 nscoord x,y;
547 scrollableView->GetScrollPosition(x, y);
548 focusRect.x += x;
549 focusRect.y += y;
552 // XXX use the root frame foreground color, but should we find BODY frame
553 // for HTML documents?
554 nsIFrame* root = mFrames.FirstChild();
555 const nsStyleColor* color =
556 root ? root->GetStyleContext()->GetStyleColor() :
557 mStyleContext->GetStyleColor();
558 if (!color) {
559 NS_ERROR("current color cannot be found");
560 return;
563 nsCSSRendering::PaintFocus(PresContext(), aRenderingContext,
564 focusRect, color->mColor);
567 /* virtual */ nscoord
568 CanvasFrame::GetMinWidth(nsIRenderingContext *aRenderingContext)
570 nscoord result;
571 DISPLAY_MIN_WIDTH(this, result);
572 if (mFrames.IsEmpty())
573 result = 0;
574 else
575 result = mFrames.FirstChild()->GetMinWidth(aRenderingContext);
576 return result;
579 /* virtual */ nscoord
580 CanvasFrame::GetPrefWidth(nsIRenderingContext *aRenderingContext)
582 nscoord result;
583 DISPLAY_PREF_WIDTH(this, result);
584 if (mFrames.IsEmpty())
585 result = 0;
586 else
587 result = mFrames.FirstChild()->GetPrefWidth(aRenderingContext);
588 return result;
591 NS_IMETHODIMP
592 CanvasFrame::Reflow(nsPresContext* aPresContext,
593 nsHTMLReflowMetrics& aDesiredSize,
594 const nsHTMLReflowState& aReflowState,
595 nsReflowStatus& aStatus)
597 DO_GLOBAL_REFLOW_COUNT("CanvasFrame");
598 DISPLAY_REFLOW(aPresContext, this, aReflowState, aDesiredSize, aStatus);
599 NS_FRAME_TRACE_REFLOW_IN("CanvasFrame::Reflow");
601 // Initialize OUT parameter
602 aStatus = NS_FRAME_COMPLETE;
604 CanvasFrame* prevCanvasFrame = static_cast<CanvasFrame*>
605 (GetPrevInFlow());
606 if (prevCanvasFrame) {
607 nsAutoPtr<nsFrameList> overflow(prevCanvasFrame->StealOverflowFrames());
608 if (overflow) {
609 NS_ASSERTION(overflow->OnlyChild(),
610 "must have doc root as canvas frame's only child");
611 nsHTMLContainerFrame::ReparentFrameViewList(aPresContext, *overflow,
612 prevCanvasFrame, this);
613 // Prepend overflow to the our child list. There may already be
614 // children placeholders for fixed-pos elements, which don't get
615 // reflowed but must not be lost until the canvas frame is destroyed.
616 mFrames.InsertFrames(this, nsnull, *overflow);
620 // Reflow our one and only normal child frame. It's either the root
621 // element's frame or a placeholder for that frame, if the root element
622 // is abs-pos or fixed-pos. We may have additional children which
623 // are placeholders for continuations of fixed-pos content, but those
624 // don't need to be reflowed. The normal child is always comes before
625 // the fixed-pos placeholders, because we insert it at the start
626 // of the child list, above.
627 nsHTMLReflowMetrics kidDesiredSize;
628 if (mFrames.IsEmpty()) {
629 // We have no child frame, so return an empty size
630 aDesiredSize.width = aDesiredSize.height = 0;
631 } else {
632 nsIFrame* kidFrame = mFrames.FirstChild();
633 nsRect oldKidRect = kidFrame->GetRect();
634 PRBool kidDirty = (kidFrame->GetStateBits() & NS_FRAME_IS_DIRTY) != 0;
636 nsHTMLReflowState kidReflowState(aPresContext, aReflowState, kidFrame,
637 nsSize(aReflowState.availableWidth,
638 aReflowState.availableHeight));
640 if (aReflowState.mFlags.mVResize &&
641 (kidFrame->GetStateBits() & NS_FRAME_CONTAINS_RELATIVE_HEIGHT)) {
642 // Tell our kid it's being vertically resized too. Bit of a
643 // hack for framesets.
644 kidReflowState.mFlags.mVResize = PR_TRUE;
647 nsPoint kidPt(kidReflowState.mComputedMargin.left,
648 kidReflowState.mComputedMargin.top);
649 // Apply CSS relative positioning
650 const nsStyleDisplay* styleDisp = kidFrame->GetStyleDisplay();
651 if (NS_STYLE_POSITION_RELATIVE == styleDisp->mPosition) {
652 kidPt += nsPoint(kidReflowState.mComputedOffsets.left,
653 kidReflowState.mComputedOffsets.top);
656 // Reflow the frame
657 ReflowChild(kidFrame, aPresContext, kidDesiredSize, kidReflowState,
658 kidPt.x, kidPt.y, 0, aStatus);
660 // Complete the reflow and position and size the child frame
661 FinishReflowChild(kidFrame, aPresContext, &kidReflowState, kidDesiredSize,
662 kidPt.x, kidPt.y, 0);
664 if (!NS_FRAME_IS_FULLY_COMPLETE(aStatus)) {
665 nsIFrame* nextFrame = kidFrame->GetNextInFlow();
666 NS_ASSERTION(nextFrame || aStatus & NS_FRAME_REFLOW_NEXTINFLOW,
667 "If it's incomplete and has no nif yet, it must flag a nif reflow.");
668 if (!nextFrame) {
669 nsresult rv = nsHTMLContainerFrame::CreateNextInFlow(aPresContext,
670 this, kidFrame, nextFrame);
671 NS_ENSURE_SUCCESS(rv, rv);
672 kidFrame->SetNextSibling(nextFrame->GetNextSibling());
673 nextFrame->SetNextSibling(nsnull);
674 SetOverflowFrames(aPresContext, nextFrame);
675 // Root overflow containers will be normal children of
676 // the canvas frame, but that's ok because there
677 // aren't any other frames we need to isolate them from
678 // during reflow.
680 if (NS_FRAME_OVERFLOW_IS_INCOMPLETE(aStatus)) {
681 nextFrame->AddStateBits(NS_FRAME_IS_OVERFLOW_CONTAINER);
685 // If the child frame was just inserted, then we're responsible for making sure
686 // it repaints
687 if (kidDirty) {
688 // But we have a new child, which will affect our background, so
689 // invalidate our whole rect.
690 // Note: Even though we request to be sized to our child's size, our
691 // scroll frame ensures that we are always the size of the viewport.
692 // Also note: GetPosition() on a CanvasFrame is always going to return
693 // (0, 0). We only want to invalidate GetRect() since GetOverflowRect()
694 // could also include overflow to our top and left (out of the viewport)
695 // which doesn't need to be painted.
696 nsIFrame* viewport = PresContext()->GetPresShell()->GetRootFrame();
697 viewport->Invalidate(nsRect(nsPoint(0, 0), viewport->GetSize()));
698 } else {
699 nsRect newKidRect = kidFrame->GetRect();
700 if (newKidRect.TopLeft() == oldKidRect.TopLeft()) {
701 InvalidateRectDifference(oldKidRect, kidFrame->GetRect());
702 } else {
703 Invalidate(oldKidRect);
704 Invalidate(newKidRect);
708 // Return our desired size. Normally it's what we're told, but
709 // sometimes we can be given an unconstrained height (when a window
710 // is sizing-to-content), and we should compute our desired height.
711 aDesiredSize.width = aReflowState.ComputedWidth();
712 if (aReflowState.ComputedHeight() == NS_UNCONSTRAINEDSIZE) {
713 aDesiredSize.height = kidFrame->GetRect().height +
714 kidReflowState.mComputedMargin.TopBottom();
715 } else {
716 aDesiredSize.height = aReflowState.ComputedHeight();
719 aDesiredSize.mOverflowArea.UnionRect(
720 nsRect(0, 0, aDesiredSize.width, aDesiredSize.height),
721 kidDesiredSize.mOverflowArea + kidPt);
723 if (mAbsoluteContainer.HasAbsoluteFrames()) {
724 PRBool widthChanged = aDesiredSize.width != mRect.width;
725 PRBool heightChanged = aDesiredSize.height != mRect.height;
726 nsRect absPosBounds;
727 mAbsoluteContainer.Reflow(this, aPresContext, aReflowState, aStatus,
728 aDesiredSize.width, aDesiredSize.height,
729 PR_TRUE, widthChanged, heightChanged,
730 &absPosBounds);
731 aDesiredSize.mOverflowArea.UnionRect(aDesiredSize.mOverflowArea, absPosBounds);
735 if (prevCanvasFrame) {
736 ReflowOverflowContainerChildren(aPresContext, aReflowState,
737 aDesiredSize.mOverflowArea, 0,
738 aStatus);
741 FinishAndStoreOverflow(&aDesiredSize);
743 NS_FRAME_TRACE_REFLOW_OUT("CanvasFrame::Reflow", aStatus);
744 NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize);
745 return NS_OK;
748 PRIntn
749 CanvasFrame::GetSkipSides() const
751 return 0;
754 nsIAtom*
755 CanvasFrame::GetType() const
757 return nsGkAtoms::canvasFrame;
760 NS_IMETHODIMP
761 CanvasFrame::GetContentForEvent(nsPresContext* aPresContext,
762 nsEvent* aEvent,
763 nsIContent** aContent)
765 NS_ENSURE_ARG_POINTER(aContent);
766 nsresult rv = nsFrame::GetContentForEvent(aPresContext,
767 aEvent,
768 aContent);
769 if (NS_FAILED(rv) || !*aContent) {
770 nsIFrame* kid = mFrames.FirstChild();
771 if (kid) {
772 rv = kid->GetContentForEvent(aPresContext,
773 aEvent,
774 aContent);
778 return rv;
781 #ifdef DEBUG
782 NS_IMETHODIMP
783 CanvasFrame::GetFrameName(nsAString& aResult) const
785 return MakeFrameName(NS_LITERAL_STRING("Canvas"), aResult);
787 #endif