michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* rendering object that goes directly inside the document's scrollbars */ michael@0: michael@0: #ifndef nsCanvasFrame_h___ michael@0: #define nsCanvasFrame_h___ michael@0: michael@0: #include "mozilla/Attributes.h" michael@0: #include "mozilla/EventForwards.h" michael@0: #include "nsContainerFrame.h" michael@0: #include "nsIScrollPositionListener.h" michael@0: #include "nsDisplayList.h" michael@0: michael@0: class nsPresContext; michael@0: class nsRenderingContext; michael@0: michael@0: /** michael@0: * Root frame class. michael@0: * michael@0: * The root frame is the parent frame for the document element's frame. michael@0: * It only supports having a single child frame which must be an area michael@0: * frame michael@0: */ michael@0: class nsCanvasFrame : public nsContainerFrame, michael@0: public nsIScrollPositionListener michael@0: { michael@0: public: michael@0: nsCanvasFrame(nsStyleContext* aContext) michael@0: : nsContainerFrame(aContext), michael@0: mDoPaintFocus(false), michael@0: mAddedScrollPositionListener(false) {} michael@0: michael@0: NS_DECL_QUERYFRAME_TARGET(nsCanvasFrame) michael@0: NS_DECL_QUERYFRAME michael@0: NS_DECL_FRAMEARENA_HELPERS michael@0: michael@0: michael@0: virtual void DestroyFrom(nsIFrame* aDestructRoot) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult SetInitialChildList(ChildListID aListID, michael@0: nsFrameList& aChildList) MOZ_OVERRIDE; michael@0: virtual nsresult AppendFrames(ChildListID aListID, michael@0: nsFrameList& aFrameList) MOZ_OVERRIDE; michael@0: virtual nsresult InsertFrames(ChildListID aListID, michael@0: nsIFrame* aPrevFrame, michael@0: nsFrameList& aFrameList) MOZ_OVERRIDE; michael@0: virtual nsresult RemoveFrame(ChildListID aListID, michael@0: nsIFrame* aOldFrame) MOZ_OVERRIDE; michael@0: michael@0: virtual nscoord GetMinWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; michael@0: virtual nscoord GetPrefWidth(nsRenderingContext *aRenderingContext) MOZ_OVERRIDE; michael@0: virtual nsresult Reflow(nsPresContext* aPresContext, michael@0: nsHTMLReflowMetrics& aDesiredSize, michael@0: const nsHTMLReflowState& aReflowState, michael@0: nsReflowStatus& aStatus) MOZ_OVERRIDE; michael@0: virtual bool IsFrameOfType(uint32_t aFlags) const MOZ_OVERRIDE michael@0: { michael@0: return nsContainerFrame::IsFrameOfType(aFlags & michael@0: ~(nsIFrame::eCanContainOverflowContainers)); michael@0: } michael@0: michael@0: /** SetHasFocus tells the CanvasFrame to draw with focus ring michael@0: * @param aHasFocus true to show focus ring, false to hide it michael@0: */ michael@0: NS_IMETHOD SetHasFocus(bool aHasFocus); michael@0: michael@0: virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder, michael@0: const nsRect& aDirtyRect, michael@0: const nsDisplayListSet& aLists) MOZ_OVERRIDE; michael@0: michael@0: void PaintFocus(nsRenderingContext& aRenderingContext, nsPoint aPt); michael@0: michael@0: // nsIScrollPositionListener michael@0: virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) MOZ_OVERRIDE; michael@0: virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) MOZ_OVERRIDE {} michael@0: michael@0: /** michael@0: * Get the "type" of the frame michael@0: * michael@0: * @see nsGkAtoms::canvasFrame michael@0: */ michael@0: virtual nsIAtom* GetType() const MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult StealFrame(nsIFrame* aChild, bool aForceNormal) MOZ_OVERRIDE michael@0: { michael@0: NS_ASSERTION(!aForceNormal, "No-one should be passing this in here"); michael@0: michael@0: // nsCanvasFrame keeps overflow container continuations of its child michael@0: // frame in main child list michael@0: nsresult rv = nsContainerFrame::StealFrame(aChild, true); michael@0: if (NS_FAILED(rv)) { michael@0: rv = nsContainerFrame::StealFrame(aChild); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: #ifdef DEBUG_FRAME_DUMP michael@0: virtual nsresult GetFrameName(nsAString& aResult) const MOZ_OVERRIDE; michael@0: #endif michael@0: virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent, michael@0: nsIContent** aContent) MOZ_OVERRIDE; michael@0: michael@0: nsRect CanvasArea() const; michael@0: michael@0: protected: michael@0: // Data members michael@0: bool mDoPaintFocus; michael@0: bool mAddedScrollPositionListener; michael@0: }; michael@0: michael@0: /** michael@0: * Override nsDisplayBackground methods so that we pass aBGClipRect to michael@0: * PaintBackground, covering the whole overflow area. michael@0: * We can also paint an "extra background color" behind the normal michael@0: * background. michael@0: */ michael@0: class nsDisplayCanvasBackgroundColor : public nsDisplayItem { michael@0: public: michael@0: nsDisplayCanvasBackgroundColor(nsDisplayListBuilder* aBuilder, nsIFrame *aFrame) michael@0: : nsDisplayItem(aBuilder, aFrame) michael@0: , mColor(NS_RGBA(0,0,0,0)) michael@0: { michael@0: } michael@0: michael@0: virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder, michael@0: nsRegion* aVisibleRegion, michael@0: const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE michael@0: { michael@0: return NS_GET_A(mColor) > 0; michael@0: } michael@0: virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder, michael@0: bool* aSnap) MOZ_OVERRIDE michael@0: { michael@0: if (NS_GET_A(mColor) == 255) { michael@0: return nsRegion(GetBounds(aBuilder, aSnap)); michael@0: } michael@0: return nsRegion(); michael@0: } michael@0: virtual bool IsUniform(nsDisplayListBuilder* aBuilder, nscolor* aColor) MOZ_OVERRIDE michael@0: { michael@0: *aColor = mColor; michael@0: return true; michael@0: } michael@0: virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE michael@0: { michael@0: nsCanvasFrame* frame = static_cast(mFrame); michael@0: *aSnap = true; michael@0: return frame->CanvasArea() + ToReferenceFrame(); michael@0: } michael@0: virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect, michael@0: HitTestState* aState, nsTArray *aOutFrames) MOZ_OVERRIDE michael@0: { michael@0: // We need to override so we don't consider border-radius. michael@0: aOutFrames->AppendElement(mFrame); michael@0: } michael@0: michael@0: virtual nsDisplayItemGeometry* AllocateGeometry(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE michael@0: { michael@0: return new nsDisplayItemBoundsGeometry(this, aBuilder); michael@0: } michael@0: michael@0: virtual void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder, michael@0: const nsDisplayItemGeometry* aGeometry, michael@0: nsRegion* aInvalidRegion) MOZ_OVERRIDE michael@0: { michael@0: const nsDisplayItemBoundsGeometry* geometry = static_cast(aGeometry); michael@0: ComputeInvalidationRegionDifference(aBuilder, geometry, aInvalidRegion); michael@0: } michael@0: michael@0: virtual void Paint(nsDisplayListBuilder* aBuilder, michael@0: nsRenderingContext* aCtx) MOZ_OVERRIDE; michael@0: michael@0: void SetExtraBackgroundColor(nscolor aColor) michael@0: { michael@0: mColor = aColor; michael@0: } michael@0: michael@0: NS_DISPLAY_DECL_NAME("CanvasBackgroundColor", TYPE_CANVAS_BACKGROUND_COLOR) michael@0: michael@0: private: michael@0: nscolor mColor; michael@0: }; michael@0: michael@0: class nsDisplayCanvasBackgroundImage : public nsDisplayBackgroundImage { michael@0: public: michael@0: nsDisplayCanvasBackgroundImage(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame, michael@0: uint32_t aLayer, const nsStyleBackground* aBg) michael@0: : nsDisplayBackgroundImage(aBuilder, aFrame, aLayer, aBg) michael@0: {} michael@0: michael@0: virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; michael@0: michael@0: virtual void NotifyRenderingChanged() MOZ_OVERRIDE michael@0: { michael@0: mFrame->Properties().Delete(nsIFrame::CachedBackgroundImage()); michael@0: mFrame->Properties().Delete(nsIFrame::CachedBackgroundImageDT()); michael@0: } michael@0: michael@0: virtual bool ShouldFixToViewport(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE michael@0: { michael@0: // Put background-attachment:fixed canvas background images in their own michael@0: // compositing layer. Since we know their background painting area can't michael@0: // change (unless the viewport size itself changes), async scrolling michael@0: // will work well. michael@0: return mBackgroundStyle->mLayers[mLayer].mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED && michael@0: !mBackgroundStyle->mLayers[mLayer].mImage.IsEmpty(); michael@0: } michael@0: michael@0: // We still need to paint a background color as well as an image for this item, michael@0: // so we can't support this yet. michael@0: virtual bool SupportsOptimizingToImage() MOZ_OVERRIDE { return false; } michael@0: michael@0: michael@0: NS_DISPLAY_DECL_NAME("CanvasBackgroundImage", TYPE_CANVAS_BACKGROUND_IMAGE) michael@0: }; michael@0: michael@0: class nsDisplayCanvasThemedBackground : public nsDisplayThemedBackground { michael@0: public: michael@0: nsDisplayCanvasThemedBackground(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame) michael@0: : nsDisplayThemedBackground(aBuilder, aFrame) michael@0: {} michael@0: michael@0: virtual void Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) MOZ_OVERRIDE; michael@0: michael@0: NS_DISPLAY_DECL_NAME("CanvasThemedBackground", TYPE_CANVAS_THEMED_BACKGROUND) michael@0: }; michael@0: michael@0: #endif /* nsCanvasFrame_h___ */