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.
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"
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"
60 #include "nsIDOMWindowInternal.h"
61 #include "nsIScrollableFrame.h"
62 #include "nsIScrollableView.h"
63 #include "nsIDocShell.h"
64 #include "nsICanvasFrame.h"
67 //#define DEBUG_CANVAS_FOCUS
70 #define CANVAS_ABS_POS_CHILD_LIST NS_CONTAINER_LIST_COUNT_INCL_OC
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
81 class CanvasFrame
: public nsHTMLContainerFrame
,
82 public nsIScrollPositionListener
,
83 public nsICanvasFrame
{
85 CanvasFrame(nsStyleContext
* aContext
)
86 : nsHTMLContainerFrame(aContext
), mDoPaintFocus(PR_FALSE
),
87 mAbsoluteContainer(nsGkAtoms::absoluteList
) {}
91 // nsISupports (nsIScrollPositionListener)
92 NS_IMETHOD
QueryInterface(const nsIID
& aIID
, void** aInstancePtr
);
94 NS_IMETHOD
Init(nsIContent
* aContent
,
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
);
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
,
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
);
157 rv
= nsContainerFrame::StealFrame(aPresContext
, aChild
);
163 NS_IMETHOD
GetFrameName(nsAString
& aResult
) const;
165 NS_IMETHOD
GetContentForEvent(nsPresContext
* aPresContext
,
167 nsIContent
** aContent
);
169 nsRect
CanvasArea() const;
172 virtual PRIntn
GetSkipSides() const;
175 PRPackedBool mDoPaintFocus
;
176 nsCOMPtr
<nsIViewManager
> mViewManager
;
177 nsAbsoluteContainingBlock mAbsoluteContainer
;
180 NS_IMETHOD_(nsrefcnt
) AddRef() { return NS_OK
; }
181 NS_IMETHOD_(nsrefcnt
) Release() { return NS_OK
; }
185 //----------------------------------------------------------------------
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
)
200 CanvasFrame::Init(nsIContent
* aContent
,
202 nsIFrame
* aPrevInFlow
)
204 nsresult rv
= nsHTMLContainerFrame::Init(aContent
, aParent
, aPrevInFlow
);
206 mViewManager
= PresContext()->GetPresShell()->GetViewManager();
208 nsIScrollableView
* scrollingView
= nsnull
;
209 mViewManager
->GetRootScrollableView(&scrollingView
);
211 scrollingView
->AddScrollPositionListener(this);
218 CanvasFrame::Destroy()
220 mAbsoluteContainer
.DestroyFrames(this);
222 nsIScrollableView
* scrollingView
= nsnull
;
223 mViewManager
->GetRootScrollableView(&scrollingView
);
225 scrollingView
->RemoveScrollPositionListener(this);
228 nsHTMLContainerFrame::Destroy();
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
));
246 docShell
->GetHasFocus(&hasFocus
);
248 printf("SPWC: %p HF: %s mDoPaintFocus: %s\n", docShell
.get(), hasFocus
?"Y":"N", mDoPaintFocus
?"Y":"N");
253 mDoPaintFocus
= PR_FALSE
;
254 mViewManager
->UpdateAllViews(NS_VMREFRESH_NO_SYNC
);
260 CanvasFrame::ScrollPositionDidChange(nsIScrollableView
* aScrollable
, nscoord aX
, nscoord aY
)
266 CanvasFrame::SetHasFocus(PRBool aHasFocus
)
268 if (mDoPaintFocus
!= aHasFocus
) {
269 mDoPaintFocus
= aHasFocus
;
270 mViewManager
->UpdateAllViews(NS_VMREFRESH_NO_SYNC
);
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
);
288 CanvasFrame::AppendFrames(nsIAtom
* aListName
,
289 nsFrameList
& aFrameList
)
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");
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
;
307 // Insert the new frames
308 NS_ASSERTION(aFrameList
.FirstChild() == aFrameList
.LastChild(),
309 "Only one principal child frame allowed");
311 nsFrame::VerifyDirtyBitSet(aFrameList
);
313 mFrames
.AppendFrames(nsnull
, aFrameList
);
315 rv
= PresContext()->PresShell()->
316 FrameNeedsReflow(this, nsIPresShell::eTreeChange
,
317 NS_FRAME_HAS_DIRTY_CHILDREN
);
324 CanvasFrame::InsertFrames(nsIAtom
* aListName
,
325 nsIFrame
* aPrevFrame
,
326 nsFrameList
& aFrameList
)
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
335 NS_PRECONDITION(!aPrevFrame
, "unexpected previous sibling frame");
337 rv
= NS_ERROR_UNEXPECTED
;
339 rv
= AppendFrames(aListName
, aFrameList
);
346 CanvasFrame::RemoveFrame(nsIAtom
* aListName
,
351 if (nsGkAtoms::absoluteList
== aListName
)
352 return mAbsoluteContainer
.RemoveFrame(this, aListName
, aOldFrame
);
354 NS_ASSERTION(!aListName
, "unexpected child list name");
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
);
373 rv
= NS_ERROR_FAILURE
;
380 CanvasFrame::GetAdditionalChildListName(PRInt32 aIndex
) const
382 if (CANVAS_ABS_POS_CHILD_LIST
== aIndex
)
383 return nsGkAtoms::absoluteList
;
385 return nsHTMLContainerFrame::GetAdditionalChildListName(aIndex
);
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()));
411 * Override nsDisplayBackground methods so that we pass aBGClipRect to
412 * PaintBackground, covering the whole overflow area.
414 class nsDisplayCanvasBackground
: public nsDisplayBackground
{
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
,
435 nsRect(offset
, mFrame
->GetSize()),
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
{
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")
472 CanvasFrame::BuildDisplayList(nsDisplayListBuilder
* aBuilder
,
473 const nsRect
& aDirtyRect
,
474 const nsDisplayListSet
& aLists
)
478 if (GetPrevInFlow()) {
479 DisplayOverflowContainers(aBuilder
, aDirtyRect
, aLists
);
482 aBuilder
->MarkFramesForDisplayList(this, mAbsoluteContainer
.GetChildList(),
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
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
);
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
));
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");
527 // Only paint the focus if we're visible
528 if (!GetStyleVisibility()->IsVisible())
531 return aLists
.Outlines()->AppendNewToTop(new (aBuilder
)
532 nsDisplayCanvasFocus(this));
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
;
547 scrollableView
->GetScrollPosition(x
, 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();
559 NS_ERROR("current color cannot be found");
563 nsCSSRendering::PaintFocus(PresContext(), aRenderingContext
,
564 focusRect
, color
->mColor
);
567 /* virtual */ nscoord
568 CanvasFrame::GetMinWidth(nsIRenderingContext
*aRenderingContext
)
571 DISPLAY_MIN_WIDTH(this, result
);
572 if (mFrames
.IsEmpty())
575 result
= mFrames
.FirstChild()->GetMinWidth(aRenderingContext
);
579 /* virtual */ nscoord
580 CanvasFrame::GetPrefWidth(nsIRenderingContext
*aRenderingContext
)
583 DISPLAY_PREF_WIDTH(this, result
);
584 if (mFrames
.IsEmpty())
587 result
= mFrames
.FirstChild()->GetPrefWidth(aRenderingContext
);
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
*>
606 if (prevCanvasFrame
) {
607 nsAutoPtr
<nsFrameList
> overflow(prevCanvasFrame
->StealOverflowFrames());
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;
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
);
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.");
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
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
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()));
699 nsRect newKidRect
= kidFrame
->GetRect();
700 if (newKidRect
.TopLeft() == oldKidRect
.TopLeft()) {
701 InvalidateRectDifference(oldKidRect
, kidFrame
->GetRect());
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();
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
;
727 mAbsoluteContainer
.Reflow(this, aPresContext
, aReflowState
, aStatus
,
728 aDesiredSize
.width
, aDesiredSize
.height
,
729 PR_TRUE
, widthChanged
, heightChanged
,
731 aDesiredSize
.mOverflowArea
.UnionRect(aDesiredSize
.mOverflowArea
, absPosBounds
);
735 if (prevCanvasFrame
) {
736 ReflowOverflowContainerChildren(aPresContext
, aReflowState
,
737 aDesiredSize
.mOverflowArea
, 0,
741 FinishAndStoreOverflow(&aDesiredSize
);
743 NS_FRAME_TRACE_REFLOW_OUT("CanvasFrame::Reflow", aStatus
);
744 NS_FRAME_SET_TRUNCATION(aStatus
, aReflowState
, aDesiredSize
);
749 CanvasFrame::GetSkipSides() const
755 CanvasFrame::GetType() const
757 return nsGkAtoms::canvasFrame
;
761 CanvasFrame::GetContentForEvent(nsPresContext
* aPresContext
,
763 nsIContent
** aContent
)
765 NS_ENSURE_ARG_POINTER(aContent
);
766 nsresult rv
= nsFrame::GetContentForEvent(aPresContext
,
769 if (NS_FAILED(rv
) || !*aContent
) {
770 nsIFrame
* kid
= mFrames
.FirstChild();
772 rv
= kid
->GetContentForEvent(aPresContext
,
783 CanvasFrame::GetFrameName(nsAString
& aResult
) const
785 return MakeFrameName(NS_LITERAL_STRING("Canvas"), aResult
);