1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 /* rendering object that goes directly inside the document's scrollbars */
8 
9 #ifndef nsCanvasFrame_h___
10 #define nsCanvasFrame_h___
11 
12 #include "mozilla/Attributes.h"
13 #include "mozilla/EventForwards.h"
14 #include "nsContainerFrame.h"
15 #include "nsIScrollPositionListener.h"
16 #include "nsDisplayList.h"
17 #include "nsIAnonymousContentCreator.h"
18 #include "gfxPrefs.h"
19 
20 class nsPresContext;
21 class gfxContext;
22 
23 /**
24  * Root frame class.
25  *
26  * The root frame is the parent frame for the document element's frame.
27  * It only supports having a single child frame which must be an area
28  * frame.
29  * @note nsCanvasFrame keeps overflow container continuations of its child
30  * frame in the main child list.
31  */
32 class nsCanvasFrame final : public nsContainerFrame,
33                             public nsIScrollPositionListener,
34                             public nsIAnonymousContentCreator {
35  public:
nsCanvasFrame(nsStyleContext * aContext)36   explicit nsCanvasFrame(nsStyleContext* aContext)
37       : nsContainerFrame(aContext, kClassID),
38         mDoPaintFocus(false),
39         mAddedScrollPositionListener(false) {}
40 
41   NS_DECL_QUERYFRAME
42   NS_DECL_FRAMEARENA_HELPERS(nsCanvasFrame)
43 
44   virtual void DestroyFrom(nsIFrame* aDestructRoot,
45                            PostDestroyData& aPostDestroyData) override;
46 
47   virtual void SetInitialChildList(ChildListID aListID,
48                                    nsFrameList& aChildList) override;
49   virtual void AppendFrames(ChildListID aListID,
50                             nsFrameList& aFrameList) override;
51   virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
52                             nsFrameList& aFrameList) override;
53 #ifdef DEBUG
54   virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
55 #endif
56 
57   virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
58   virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
59   virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
60                       const ReflowInput& aReflowInput,
61                       nsReflowStatus& aStatus) override;
IsFrameOfType(uint32_t aFlags)62   virtual bool IsFrameOfType(uint32_t aFlags) const override {
63     return nsContainerFrame::IsFrameOfType(
64         aFlags & ~(nsIFrame::eCanContainOverflowContainers));
65   }
66 
67   // nsIAnonymousContentCreator
68   virtual nsresult CreateAnonymousContent(
69       nsTArray<ContentInfo>& aElements) override;
70   virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
71                                         uint32_t aFilter) override;
72 
GetCustomContentContainer()73   mozilla::dom::Element* GetCustomContentContainer() const {
74     return mCustomContentContainer;
75   }
76 
77   /**
78    * Unhide the CustomContentContainer. This call only has an effect if
79    * mCustomContentContainer is non-null.
80    */
81   void ShowCustomContentContainer();
82 
83   /**
84    * Hide the CustomContentContainer. This call only has an effect if
85    * mCustomContentContainer is non-null.
86    */
87   void HideCustomContentContainer();
88 
89   /** SetHasFocus tells the CanvasFrame to draw with focus ring
90    *  @param aHasFocus true to show focus ring, false to hide it
91    */
92   NS_IMETHOD SetHasFocus(bool aHasFocus);
93 
94   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
95                                 const nsDisplayListSet& aLists) override;
96 
97   void PaintFocus(mozilla::gfx::DrawTarget* aRenderingContext, nsPoint aPt);
98 
99   // nsIScrollPositionListener
100   virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) override;
ScrollPositionDidChange(nscoord aX,nscoord aY)101   virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) override {}
102 
103 #ifdef DEBUG_FRAME_DUMP
104   virtual nsresult GetFrameName(nsAString& aResult) const override;
105 #endif
106   virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
107                                       nsIContent** aContent) override;
108 
109   nsRect CanvasArea() const;
110 
111  protected:
112   // Utility function to propagate the WritingMode from our first child to
113   // 'this' and all its ancestors.
114   void MaybePropagateRootElementWritingMode();
115 
116   // Data members
117   bool mDoPaintFocus;
118   bool mAddedScrollPositionListener;
119 
120   nsCOMPtr<mozilla::dom::Element> mCustomContentContainer;
121 };
122 
123 /**
124  * Override nsDisplayBackground methods so that we pass aBGClipRect to
125  * PaintBackground, covering the whole overflow area.
126  * We can also paint an "extra background color" behind the normal
127  * background.
128  */
129 class nsDisplayCanvasBackgroundColor : public nsDisplaySolidColorBase {
130  public:
nsDisplayCanvasBackgroundColor(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)131   nsDisplayCanvasBackgroundColor(nsDisplayListBuilder* aBuilder,
132                                  nsIFrame* aFrame)
133       : nsDisplaySolidColorBase(aBuilder, aFrame, NS_RGBA(0, 0, 0, 0)) {}
134 
ComputeVisibility(nsDisplayListBuilder * aBuilder,nsRegion * aVisibleRegion)135   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
136                                  nsRegion* aVisibleRegion) override {
137     return NS_GET_A(mColor) > 0;
138   }
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)139   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
140                            bool* aSnap) const override {
141     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
142     *aSnap = true;
143     return frame->CanvasArea() + ToReferenceFrame();
144   }
HitTest(nsDisplayListBuilder * aBuilder,const nsRect & aRect,HitTestState * aState,nsTArray<nsIFrame * > * aOutFrames)145   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
146                        HitTestState* aState,
147                        nsTArray<nsIFrame*>* aOutFrames) override {
148     // We need to override so we don't consider border-radius.
149     aOutFrames->AppendElement(mFrame);
150   }
151   virtual already_AddRefed<Layer> BuildLayer(
152       nsDisplayListBuilder* aBuilder, LayerManager* aManager,
153       const ContainerLayerParameters& aContainerParameters) override;
154   virtual bool CreateWebRenderCommands(
155       mozilla::wr::DisplayListBuilder& aBuilder,
156       mozilla::wr::IpcResourceUpdateQueue& aResources,
157       const StackingContextHelper& aSc,
158       mozilla::layers::WebRenderLayerManager* aManager,
159       nsDisplayListBuilder* aDisplayListBuilder) override;
GetLayerState(nsDisplayListBuilder * aBuilder,LayerManager * aManager,const ContainerLayerParameters & aParameters)160   virtual LayerState GetLayerState(
161       nsDisplayListBuilder* aBuilder, LayerManager* aManager,
162       const ContainerLayerParameters& aParameters) override {
163     if (ShouldUseAdvancedLayer(
164             aManager, gfxPrefs::LayersAllowCanvasBackgroundColorLayers) ||
165         ForceActiveLayers()) {
166       return mozilla::LAYER_ACTIVE;
167     }
168     return mozilla::LAYER_NONE;
169   }
170   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
171 
SetExtraBackgroundColor(nscolor aColor)172   void SetExtraBackgroundColor(nscolor aColor) { mColor = aColor; }
173 
174   NS_DISPLAY_DECL_NAME("CanvasBackgroundColor", TYPE_CANVAS_BACKGROUND_COLOR)
175 #ifdef MOZ_DUMP_PAINTING
176   virtual void WriteDebugInfo(std::stringstream& aStream) override;
177 #endif
178 };
179 
180 class nsDisplayCanvasBackgroundImage : public nsDisplayBackgroundImage {
181  public:
nsDisplayCanvasBackgroundImage(nsDisplayListBuilder * aBuilder,const InitData & aInitData)182   explicit nsDisplayCanvasBackgroundImage(nsDisplayListBuilder* aBuilder,
183                                           const InitData& aInitData)
184       : nsDisplayBackgroundImage(aBuilder, aInitData) {}
185 
186   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
187 
188   // We still need to paint a background color as well as an image for this
189   // item, so we can't support this yet.
SupportsOptimizingToImage()190   virtual bool SupportsOptimizingToImage() const override { return false; }
191 
192   bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
193                                   const nsRect& aClipRect, gfxRect* aDestRect);
194 
195   NS_DISPLAY_DECL_NAME("CanvasBackgroundImage", TYPE_CANVAS_BACKGROUND_IMAGE)
196 };
197 
198 class nsDisplayCanvasThemedBackground : public nsDisplayThemedBackground {
199  public:
nsDisplayCanvasThemedBackground(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)200   nsDisplayCanvasThemedBackground(nsDisplayListBuilder* aBuilder,
201                                   nsIFrame* aFrame)
202       : nsDisplayThemedBackground(aBuilder, aFrame,
203                                   aFrame->GetRectRelativeToSelf() +
204                                       aBuilder->ToReferenceFrame(aFrame)) {}
205 
206   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
207 
208   NS_DISPLAY_DECL_NAME("CanvasThemedBackground", TYPE_CANVAS_THEMED_BACKGROUND)
209 };
210 
211 #endif /* nsCanvasFrame_h___ */
212