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 "nsIPopupContainer.h"
17 #include "nsDisplayList.h"
18 #include "nsIAnonymousContentCreator.h"
19 
20 class nsPresContext;
21 class gfxContext;
22 class nsPopupSetFrame;
23 
24 /**
25  * Root frame class.
26  *
27  * The root frame is the parent frame for the document element's frame.
28  * It only supports having a single child frame which must be an area
29  * frame.
30  * @note nsCanvasFrame keeps overflow container continuations of its child
31  * frame in the main child list.
32  */
33 class nsCanvasFrame final : public nsContainerFrame,
34                             public nsIScrollPositionListener,
35                             public nsIAnonymousContentCreator,
36                             public nsIPopupContainer {
37   using Element = mozilla::dom::Element;
38 
39  public:
nsCanvasFrame(ComputedStyle * aStyle,nsPresContext * aPresContext)40   explicit nsCanvasFrame(ComputedStyle* aStyle, nsPresContext* aPresContext)
41       : nsContainerFrame(aStyle, aPresContext, kClassID),
42         mDoPaintFocus(false),
43         mAddedScrollPositionListener(false),
44         mPopupSetFrame(nullptr) {}
45 
46   NS_DECL_QUERYFRAME
47   NS_DECL_FRAMEARENA_HELPERS(nsCanvasFrame)
48 
49   nsPopupSetFrame* GetPopupSetFrame() override;
50   void SetPopupSetFrame(nsPopupSetFrame* aPopupSet) override;
51   Element* GetDefaultTooltip() override;
52   void SetDefaultTooltip(Element* aTooltip) override;
53 
54   virtual void DestroyFrom(nsIFrame* aDestructRoot,
55                            PostDestroyData& aPostDestroyData) override;
56 
57   virtual void SetInitialChildList(ChildListID aListID,
58                                    nsFrameList& aChildList) override;
59   virtual void AppendFrames(ChildListID aListID,
60                             nsFrameList& aFrameList) override;
61   virtual void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
62                             const nsLineList::iterator* aPrevFrameLine,
63                             nsFrameList& aFrameList) override;
64 #ifdef DEBUG
65   virtual void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) override;
66 #endif
67 
68   virtual nscoord GetMinISize(gfxContext* aRenderingContext) override;
69   virtual nscoord GetPrefISize(gfxContext* aRenderingContext) override;
70   virtual void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
71                       const ReflowInput& aReflowInput,
72                       nsReflowStatus& aStatus) override;
IsFrameOfType(uint32_t aFlags)73   virtual bool IsFrameOfType(uint32_t aFlags) const override {
74     return nsContainerFrame::IsFrameOfType(
75         aFlags & ~(nsIFrame::eCanContainOverflowContainers));
76   }
77 
78   // nsIAnonymousContentCreator
79   virtual nsresult CreateAnonymousContent(
80       nsTArray<ContentInfo>& aElements) override;
81   virtual void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
82                                         uint32_t aFilter) override;
83 
GetCustomContentContainer()84   Element* GetCustomContentContainer() const { return mCustomContentContainer; }
85 
86   /**
87    * Unhide the CustomContentContainer. This call only has an effect if
88    * mCustomContentContainer is non-null.
89    */
90   void ShowCustomContentContainer();
91 
92   /**
93    * Hide the CustomContentContainer. This call only has an effect if
94    * mCustomContentContainer is non-null.
95    */
96   void HideCustomContentContainer();
97 
98   /** SetHasFocus tells the CanvasFrame to draw with focus ring
99    *  @param aHasFocus true to show focus ring, false to hide it
100    */
101   NS_IMETHOD SetHasFocus(bool aHasFocus);
102 
103   virtual void BuildDisplayList(nsDisplayListBuilder* aBuilder,
104                                 const nsDisplayListSet& aLists) override;
105 
106   void PaintFocus(mozilla::gfx::DrawTarget* aRenderingContext, nsPoint aPt);
107 
108   // nsIScrollPositionListener
109   virtual void ScrollPositionWillChange(nscoord aX, nscoord aY) override;
ScrollPositionDidChange(nscoord aX,nscoord aY)110   virtual void ScrollPositionDidChange(nscoord aX, nscoord aY) override {}
111 
112 #ifdef DEBUG_FRAME_DUMP
113   virtual nsresult GetFrameName(nsAString& aResult) const override;
114 #endif
115   virtual nsresult GetContentForEvent(mozilla::WidgetEvent* aEvent,
116                                       nsIContent** aContent) override;
117 
118   nsRect CanvasArea() const;
119 
120  protected:
121   // Data members
122   bool mDoPaintFocus;
123   bool mAddedScrollPositionListener;
124 
125   nsCOMPtr<Element> mCustomContentContainer;
126 
127  private:
128   nsPopupSetFrame* mPopupSetFrame;
129   nsCOMPtr<Element> mPopupgroupContent;
130   nsCOMPtr<Element> mTooltipContent;
131 };
132 
133 namespace mozilla {
134 /**
135  * Override nsDisplayBackground methods so that we pass aBGClipRect to
136  * PaintBackground, covering the whole overflow area.
137  * We can also paint an "extra background color" behind the normal
138  * background.
139  */
140 class nsDisplayCanvasBackgroundColor final : public nsDisplaySolidColorBase {
141  public:
nsDisplayCanvasBackgroundColor(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)142   nsDisplayCanvasBackgroundColor(nsDisplayListBuilder* aBuilder,
143                                  nsIFrame* aFrame)
144       : nsDisplaySolidColorBase(aBuilder, aFrame, NS_RGBA(0, 0, 0, 0)) {}
145 
GetBounds(nsDisplayListBuilder * aBuilder,bool * aSnap)146   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder,
147                            bool* aSnap) const override {
148     nsCanvasFrame* frame = static_cast<nsCanvasFrame*>(mFrame);
149     *aSnap = true;
150     return frame->CanvasArea() + ToReferenceFrame();
151   }
HitTest(nsDisplayListBuilder * aBuilder,const nsRect & aRect,HitTestState * aState,nsTArray<nsIFrame * > * aOutFrames)152   virtual void HitTest(nsDisplayListBuilder* aBuilder, const nsRect& aRect,
153                        HitTestState* aState,
154                        nsTArray<nsIFrame*>* aOutFrames) override {
155     // We need to override so we don't consider border-radius.
156     aOutFrames->AppendElement(mFrame);
157   }
158   virtual bool CreateWebRenderCommands(
159       mozilla::wr::DisplayListBuilder& aBuilder,
160       mozilla::wr::IpcResourceUpdateQueue& aResources,
161       const StackingContextHelper& aSc,
162       mozilla::layers::RenderRootStateManager* aManager,
163       nsDisplayListBuilder* aDisplayListBuilder) override;
164   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
165 
SetExtraBackgroundColor(nscolor aColor)166   void SetExtraBackgroundColor(nscolor aColor) { mColor = aColor; }
167 
168   NS_DISPLAY_DECL_NAME("CanvasBackgroundColor", TYPE_CANVAS_BACKGROUND_COLOR)
169 
170   virtual void WriteDebugInfo(std::stringstream& aStream) override;
171 };
172 
173 class nsDisplayCanvasBackgroundImage : public nsDisplayBackgroundImage {
174  public:
nsDisplayCanvasBackgroundImage(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame,const InitData & aInitData)175   explicit nsDisplayCanvasBackgroundImage(nsDisplayListBuilder* aBuilder,
176                                           nsIFrame* aFrame,
177                                           const InitData& aInitData)
178       : nsDisplayBackgroundImage(aBuilder, aFrame, aInitData) {}
179 
180   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
181 
182   // We still need to paint a background color as well as an image for this
183   // item, so we can't support this yet.
SupportsOptimizingToImage()184   virtual bool SupportsOptimizingToImage() const override { return false; }
185 
186   bool IsSingleFixedPositionImage(nsDisplayListBuilder* aBuilder,
187                                   const nsRect& aClipRect, gfxRect* aDestRect);
188 
189   NS_DISPLAY_DECL_NAME("CanvasBackgroundImage", TYPE_CANVAS_BACKGROUND_IMAGE)
190 };
191 
192 class nsDisplayCanvasThemedBackground : public nsDisplayThemedBackground {
193  public:
nsDisplayCanvasThemedBackground(nsDisplayListBuilder * aBuilder,nsIFrame * aFrame)194   nsDisplayCanvasThemedBackground(nsDisplayListBuilder* aBuilder,
195                                   nsIFrame* aFrame)
196       : nsDisplayThemedBackground(aBuilder, aFrame,
197                                   aFrame->GetRectRelativeToSelf() +
198                                       aBuilder->ToReferenceFrame(aFrame)) {
199     nsDisplayThemedBackground::Init(aBuilder);
200   }
201 
202   virtual void Paint(nsDisplayListBuilder* aBuilder, gfxContext* aCtx) override;
203 
204   NS_DISPLAY_DECL_NAME("CanvasThemedBackground", TYPE_CANVAS_THEMED_BACKGROUND)
205 };
206 
207 }  // namespace mozilla
208 
209 #endif /* nsCanvasFrame_h___ */
210