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 to wrap rendering objects that should be scrollable */
8 
9 #ifndef nsGfxScrollFrame_h___
10 #define nsGfxScrollFrame_h___
11 
12 #include "mozilla/Attributes.h"
13 #include "nsContainerFrame.h"
14 #include "nsIAnonymousContentCreator.h"
15 #include "nsBoxFrame.h"
16 #include "nsIScrollableFrame.h"
17 #include "nsIScrollbarMediator.h"
18 #include "nsIStatefulFrame.h"
19 #include "nsThreadUtils.h"
20 #include "nsIReflowCallback.h"
21 #include "nsBoxLayoutState.h"
22 #include "nsQueryFrame.h"
23 #include "nsRefreshDriver.h"
24 #include "nsExpirationTracker.h"
25 #include "TextOverflow.h"
26 #include "ScrollVelocityQueue.h"
27 #include "mozilla/ScrollTypes.h"
28 #include "mozilla/PresState.h"
29 #include "mozilla/layout/ScrollAnchorContainer.h"
30 
31 class nsPresContext;
32 class nsIContent;
33 class nsAtom;
34 class nsIScrollPositionListener;
35 
36 namespace mozilla {
37 class PresShell;
38 struct ScrollReflowInput;
39 namespace layers {
40 class Layer;
41 class LayerManager;
42 }  // namespace layers
43 namespace layout {
44 class ScrollbarActivity;
45 }  // namespace layout
46 
47 class ScrollFrameHelper : public nsIReflowCallback {
48  public:
49   typedef nsIFrame::Sides Sides;
50   typedef mozilla::CSSIntPoint CSSIntPoint;
51   typedef mozilla::layout::ScrollbarActivity ScrollbarActivity;
52   typedef mozilla::layers::FrameMetrics FrameMetrics;
53   typedef mozilla::layers::ScrollableLayerGuid ScrollableLayerGuid;
54   typedef mozilla::layers::ScrollSnapInfo ScrollSnapInfo;
55   typedef mozilla::layers::Layer Layer;
56   typedef mozilla::layers::LayerManager LayerManager;
57   typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
58   using Element = mozilla::dom::Element;
59 
60   class AsyncScroll;
61   class AsyncSmoothMSDScroll;
62 
63   ScrollFrameHelper(nsContainerFrame* aOuter, bool aIsRoot);
64   ~ScrollFrameHelper();
65 
66   mozilla::ScrollStyles GetScrollStylesFromFrame() const;
67   mozilla::layers::OverscrollBehaviorInfo GetOverscrollBehaviorInfo() const;
68 
69   bool IsForTextControlWithNoScrollbars() const;
70 
71   // If a child frame was added or removed on the scrollframe,
72   // reload our child frame list.
73   // We need this if a scrollbar frame is recreated.
74   void ReloadChildFrames();
75 
76   nsresult CreateAnonymousContent(
77       nsTArray<nsIAnonymousContentCreator::ContentInfo>& aElements);
78   void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
79                                 uint32_t aFilter);
80   nsresult FireScrollPortEvent();
81   void PostScrollEndEvent();
82   void FireScrollEndEvent();
83   void PostOverflowEvent();
84   using PostDestroyData = nsIFrame::PostDestroyData;
85   void Destroy(PostDestroyData& aPostDestroyData);
86 
87   void BuildDisplayList(nsDisplayListBuilder* aBuilder,
88                         const nsDisplayListSet& aLists);
89 
90   // Add display items for the top-layer (which includes things like
91   // the fullscreen element, its backdrop, and text selection carets)
92   // to |aLists|.
93   // This is a no-op for scroll frames other than the viewport's
94   // root scroll frame.
95   // This should be called with an nsDisplayListSet that will be
96   // wrapped in the async zoom container, if we're building one.
97   // It should not be called with an ASR setter on the stack, as the
98   // top-layer items handle setting up their own ASRs.
99   void MaybeAddTopLayerItems(nsDisplayListBuilder* aBuilder,
100                              const nsDisplayListSet& aLists);
101 
102   void AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
103                            const nsDisplayListSet& aLists, bool aCreateLayer,
104                            bool aPositioned);
105 
106   bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
107                       Sides aSkipSides, nscoord aRadii[8]) const;
108 
109   // nsIReflowCallback
110   bool ReflowFinished() final;
111   void ReflowCallbackCanceled() final;
112 
113   /**
114    * @note This method might destroy the frame, pres shell and other objects.
115    * Called when the 'curpos' attribute on one of the scrollbars changes.
116    */
117   void CurPosAttributeChanged(nsIContent* aChild, bool aDoScroll = true);
118 
119   void PostScrollEvent(bool aDelayed = false);
120   void FireScrollEvent();
121   void PostScrolledAreaEvent();
122   void FireScrolledAreaEvent();
123 
124   bool IsSmoothScrollingEnabled();
125 
126   /**
127    * @note This method might destroy the frame, pres shell and other objects.
128    */
129   void FinishReflowForScrollbar(Element* aElement, nscoord aMinXY,
130                                 nscoord aMaxXY, nscoord aCurPosXY,
131                                 nscoord aPageIncrement, nscoord aIncrement);
132   /**
133    * @note This method might destroy the frame, pres shell and other objects.
134    */
135   void SetScrollbarEnabled(Element* aElement, nscoord aMaxPos);
136   /**
137    * @note This method might destroy the frame, pres shell and other objects.
138    */
139   void SetCoordAttribute(Element* aElement, nsAtom* aAtom, nscoord aSize);
140 
141   nscoord GetCoordAttribute(nsIFrame* aFrame, nsAtom* aAtom,
142                             nscoord aDefaultValue, nscoord* aRangeStart,
143                             nscoord* aRangeLength);
144 
145   /**
146    * @note This method might destroy the frame, pres shell and other objects.
147    * Update scrollbar curpos attributes to reflect current scroll position
148    */
149   void UpdateScrollbarPosition();
150 
GetLayoutSize()151   nsSize GetLayoutSize() const {
152     if (mIsUsingMinimumScaleSize) {
153       return mICBSize;
154     }
155     return mScrollPort.Size();
156   }
GetScrollPortRect()157   nsRect GetScrollPortRect() const { return mScrollPort; }
GetScrollPosition()158   nsPoint GetScrollPosition() const {
159     return mScrollPort.TopLeft() - mScrolledFrame->GetPosition();
160   }
161   /**
162    * For LTR frames, the logical scroll position is the offset of the top left
163    * corner of the frame from the top left corner of the scroll port (same as
164    * GetScrollPosition).
165    * For RTL frames, it is the offset of the top right corner of the frame from
166    * the top right corner of the scroll port
167    */
GetLogicalScrollPosition()168   nsPoint GetLogicalScrollPosition() const {
169     nsPoint pt;
170     pt.x = IsPhysicalLTR()
171                ? mScrollPort.x - mScrolledFrame->GetPosition().x
172                : mScrollPort.XMost() - mScrolledFrame->GetRect().XMost();
173     pt.y = mScrollPort.y - mScrolledFrame->GetPosition().y;
174     return pt;
175   }
GetApzScrollPosition()176   nsPoint GetApzScrollPosition() const { return mApzScrollPos; }
177   nsRect GetLayoutScrollRange() const;
178   // Get the scroll range assuming the viewport has size (aWidth, aHeight).
179   nsRect GetScrollRange(nscoord aWidth, nscoord aHeight) const;
180   nsSize GetVisualViewportSize() const;
181   nsPoint GetVisualViewportOffset() const;
182   nsRect GetVisualScrollRange() const;
183   nsRect GetScrollRangeForUserInputEvents() const;
184 
185   /**
186    * Return the 'optimal viewing region' as a rect suitable for use by
187    * scroll anchoring. This rect is in the same coordinate space as
188    * 'GetScrollPortRect', and accounts for 'scroll-padding' as defined by:
189    *
190    * https://drafts.csswg.org/css-scroll-snap-1/#optimal-viewing-region
191    */
192   nsRect GetVisualOptimalViewingRect() const;
193 
194   /**
195    * For LTR frames, this is the same as GetVisualViewportOffset().
196    * For RTL frames, we take the offset from the top right corner of the frame
197    * to the top right corner of the visual viewport.
198    */
GetLogicalVisualViewportOffset()199   nsPoint GetLogicalVisualViewportOffset() const {
200     nsPoint pt = GetVisualViewportOffset();
201     if (!IsPhysicalLTR()) {
202       pt.x += GetVisualViewportSize().width - mScrolledFrame->GetRect().width;
203     }
204     return pt;
205   }
206   void ScrollSnap(ScrollMode aMode = ScrollMode::SmoothMsd);
207   void ScrollSnap(const nsPoint& aDestination,
208                   ScrollMode aMode = ScrollMode::SmoothMsd);
209 
HasPendingScrollRestoration()210   bool HasPendingScrollRestoration() const {
211     return mRestorePos != nsPoint(-1, -1);
212   }
213 
IsProcessingScrollEvent()214   bool IsProcessingScrollEvent() const { return mProcessingScrollEvent; }
215 
216  public:
217   static void AsyncScrollCallback(ScrollFrameHelper* aInstance,
218                                   mozilla::TimeStamp aTime);
219   static void AsyncSmoothMSDScrollCallback(ScrollFrameHelper* aInstance,
220                                            mozilla::TimeDuration aDeltaTime);
221   /**
222    * @note This method might destroy the frame, pres shell and other objects.
223    * aRange is the range of allowable scroll positions around the desired
224    * aScrollPosition. Null means only aScrollPosition is allowed.
225    * This is a closed-ended range --- aRange.XMost()/aRange.YMost() are allowed.
226    */
227   void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode,
228                 nsAtom* aOrigin = nullptr, const nsRect* aRange = nullptr,
229                 nsIScrollbarMediator::ScrollSnapMode aSnap =
230                     nsIScrollbarMediator::DISABLE_SNAP);
231   /**
232    * @note This method might destroy the frame, pres shell and other objects.
233    */
234   void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition,
235                          ScrollMode aMode = ScrollMode::Instant,
236                          nsIScrollbarMediator::ScrollSnapMode aSnap =
237                              nsIScrollbarMediator::DEFAULT,
238                          nsAtom* aOrigin = nullptr);
239   /**
240    * @note This method might destroy the frame, pres shell and other objects.
241    */
242   void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
243                                     nsAtom* aOrigin = nullptr);
244 
245   CSSIntPoint GetScrollPositionCSSPixels();
246   /**
247    * @note This method might destroy the frame, pres shell and other objects.
248    */
249   void ScrollToImpl(nsPoint aScrollPosition, const nsRect& aRange,
250                     nsAtom* aOrigin = nullptr);
251   void ScrollVisual();
252   /**
253    * @note This method might destroy the frame, pres shell and other objects.
254    */
255   void ScrollBy(nsIntPoint aDelta, mozilla::ScrollUnit aUnit, ScrollMode aMode,
256                 nsIntPoint* aOverflow, nsAtom* aOrigin = nullptr,
257                 nsIScrollableFrame::ScrollMomentum aMomentum =
258                     nsIScrollableFrame::NOT_MOMENTUM,
259                 nsIScrollbarMediator::ScrollSnapMode aSnap =
260                     nsIScrollbarMediator::DISABLE_SNAP);
261   void ScrollByCSSPixels(const CSSIntPoint& aDelta,
262                          ScrollMode aMode = ScrollMode::Instant,
263                          nsAtom* aOrigin = nullptr,
264                          nsIScrollbarMediator::ScrollSnapMode aSnap =
265                              nsIScrollbarMediator::DEFAULT);
266   /**
267    * @note This method might destroy the frame, pres shell and other objects.
268    */
269   void ScrollToRestoredPosition();
270 
271   enum class LoadingState { Loading, Stopped, Loaded };
272 
273   LoadingState GetPageLoadingState();
274 
275   /**
276    * GetSnapPointForDestination determines which point to snap to after
277    * scrolling. aStartPos gives the position before scrolling and aDestination
278    * gives the position after scrolling, with no snapping. Behaviour is
279    * dependent on the value of aUnit.
280    * Returns true if a suitable snap point could be found and aDestination has
281    * been updated to a valid snapping position.
282    */
283   bool GetSnapPointForDestination(mozilla::ScrollUnit aUnit,
284                                   const nsPoint& aStartPos,
285                                   nsPoint& aDestination);
286 
287   nsMargin GetScrollPadding() const;
288 
289   nsSize GetLineScrollAmount() const;
290   nsSize GetPageScrollAmount() const;
291 
292   mozilla::UniquePtr<mozilla::PresState> SaveState() const;
293   void RestoreState(mozilla::PresState* aState);
294 
GetScrolledFrame()295   nsIFrame* GetScrolledFrame() const { return mScrolledFrame; }
GetScrollbarBox(bool aVertical)296   nsIFrame* GetScrollbarBox(bool aVertical) const {
297     return aVertical ? mVScrollbarBox : mHScrollbarBox;
298   }
299 
AddScrollPositionListener(nsIScrollPositionListener * aListener)300   void AddScrollPositionListener(nsIScrollPositionListener* aListener) {
301     mListeners.AppendElement(aListener);
302   }
RemoveScrollPositionListener(nsIScrollPositionListener * aListener)303   void RemoveScrollPositionListener(nsIScrollPositionListener* aListener) {
304     mListeners.RemoveElement(aListener);
305   }
306 
307   static void SetScrollbarVisibility(nsIFrame* aScrollbar, bool aVisible);
308 
309   /**
310    * GetScrolledRect is designed to encapsulate deciding which
311    * directions of overflow should be reachable by scrolling and which
312    * should not.  Callers should NOT depend on it having any particular
313    * behavior (although nsXULScrollFrame currently does).
314    *
315    * This should only be called when the scrolled frame has been
316    * reflowed with the scroll port size given in mScrollPort.
317    *
318    * Currently it allows scrolling down and to the right for
319    * nsHTMLScrollFrames with LTR directionality and for all
320    * nsXULScrollFrames, and allows scrolling down and to the left for
321    * nsHTMLScrollFrames with RTL directionality.
322    */
323   nsRect GetScrolledRect() const;
324 
325   /**
326    * GetUnsnappedScrolledRectInternal is designed to encapsulate deciding which
327    * directions of overflow should be reachable by scrolling and which
328    * should not.  Callers should NOT depend on it having any particular
329    * behavior (although nsXULScrollFrame currently does).
330    *
331    * Currently it allows scrolling down and to the right for
332    * nsHTMLScrollFrames with LTR directionality and for all
333    * nsXULScrollFrames, and allows scrolling down and to the left for
334    * nsHTMLScrollFrames with RTL directionality.
335    */
336   nsRect GetUnsnappedScrolledRectInternal(const nsRect& aScrolledOverflowArea,
337                                           const nsSize& aScrollPortSize) const;
338 
339   uint32_t GetAvailableScrollingDirectionsForUserInputEvents() const;
340 
GetScrollbarVisibility()341   uint32_t GetScrollbarVisibility() const {
342     return (mHasVerticalScrollbar ? nsIScrollableFrame::VERTICAL : 0) |
343            (mHasHorizontalScrollbar ? nsIScrollableFrame::HORIZONTAL : 0);
344   }
345   nsMargin GetActualScrollbarSizes() const;
346   nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
347   nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState,
348                                            mozilla::WritingMode aVerticalWM);
IsPhysicalLTR()349   bool IsPhysicalLTR() const {
350     return mOuter->GetWritingMode().IsPhysicalLTR();
351   }
IsBidiLTR()352   bool IsBidiLTR() const { return mOuter->GetWritingMode().IsBidiLTR(); }
353 
354  private:
355   // NOTE: Use GetScrollStylesFromFrame() if you want to know `overflow`
356   // and `overflow-behavior` properties.
357   nsIFrame* GetFrameForStyle() const;
358 
359   // This is the for the old unspecced scroll snap implementation.
360   ScrollSnapInfo ComputeOldScrollSnapInfo() const;
361   // This is the for the scroll snap v1 implementation.
362   ScrollSnapInfo ComputeScrollSnapInfo(
363       const Maybe<nsPoint>& aDestination) const;
364 
365   bool NeedsScrollSnap() const;
366 
367  public:
368   bool IsScrollbarOnRight() const;
369   bool IsScrollingActive(nsDisplayListBuilder* aBuilder) const;
IsMaybeAsynchronouslyScrolled()370   bool IsMaybeAsynchronouslyScrolled() const {
371     // If this is true, then we'll build an ASR, and that's what we want
372     // to know I think.
373     return mWillBuildScrollableLayer;
374   }
375   bool IsMaybeScrollingActive() const;
IsProcessingAsyncScroll()376   bool IsProcessingAsyncScroll() const {
377     return mAsyncScroll != nullptr || mAsyncSmoothMSDScroll != nullptr;
378   }
ResetScrollPositionForLayerPixelAlignment()379   void ResetScrollPositionForLayerPixelAlignment() {
380     mScrollPosForLayerPixelAlignment = GetScrollPosition();
381   }
382 
383   bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas);
384 
385   void UpdateSticky();
386 
387   void UpdatePrevScrolledRect();
388 
389   bool IsRectNearlyVisible(const nsRect& aRect) const;
390   nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const;
391 
392   // adjust the scrollbar rectangle aRect to account for any visible resizer.
393   // aHasResizer specifies if there is a content resizer, however this method
394   // will also check if a widget resizer is present as well.
395   void AdjustScrollbarRectForResizer(
396       nsIFrame* aFrame, nsPresContext* aPresContext, nsRect& aRect,
397       bool aHasResizer, mozilla::layers::ScrollDirection aDirection);
398   // returns true if a resizer should be visible
HasResizer()399   bool HasResizer() { return mResizerBox && !mCollapsedResizer; }
400   void LayoutScrollbars(nsBoxLayoutState& aState, const nsRect& aContentArea,
401                         const nsRect& aOldScrollArea);
402 
403   void MarkScrollbarsDirtyForReflow() const;
404 
405   bool IsAlwaysActive() const;
406   void MarkEverScrolled();
407   void MarkRecentlyScrolled();
408   void MarkNotRecentlyScrolled();
GetExpirationState()409   nsExpirationState* GetExpirationState() { return &mActivityExpirationState; }
410 
SetTransformingByAPZ(bool aTransforming)411   void SetTransformingByAPZ(bool aTransforming) {
412     if (mTransformingByAPZ && !aTransforming) {
413       PostScrollEndEvent();
414     }
415     mTransformingByAPZ = aTransforming;
416     if (!mozilla::css::TextOverflow::HasClippedTextOverflow(mOuter) ||
417         mozilla::css::TextOverflow::HasBlockEllipsis(mScrolledFrame)) {
418       // If the block has some overflow marker stuff we should kick off a paint
419       // because we have special behaviour for it when APZ scrolling is active.
420       mOuter->SchedulePaint();
421     }
422   }
IsTransformingByAPZ()423   bool IsTransformingByAPZ() const { return mTransformingByAPZ; }
424   void SetScrollableByAPZ(bool aScrollable);
425   void SetZoomableByAPZ(bool aZoomable);
426   void SetHasOutOfFlowContentInsideFilter();
427 
428   bool UsesOverlayScrollbars() const;
429 
430   // In the case where |aDestination| is given, elements which are entirely out
431   // of view when the scroll position is moved to |aDestination| are not going
432   // to be used for snap positions.
433   ScrollSnapInfo GetScrollSnapInfo(
434       const mozilla::Maybe<nsPoint>& aDestination) const;
435 
436   nsRect RestrictToRootDisplayPort(const nsRect& aDisplayportBase);
437   bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
438                              nsRect* aVisibleRect, nsRect* aDirtyRect,
439                              bool aSetBase,
440                              bool* aDirtyRectHasBeenOverriden = nullptr);
NotifyApzTransaction()441   void NotifyApzTransaction() {
442     mAllowScrollOriginDowngrade = true;
443     mApzScrollPos = GetScrollPosition();
444   }
445   void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort);
446   bool GetDisplayPortAtLastApproximateFrameVisibilityUpdate(
447       nsRect* aDisplayPort);
448 
449   bool AllowDisplayPortExpiration();
450   void TriggerDisplayPortExpiration();
451   void ResetDisplayPortExpiryTimer();
452 
453   void ScheduleSyntheticMouseMove();
454   static void ScrollActivityCallback(nsITimer* aTimer, void* anInstance);
455 
456   void HandleScrollbarStyleSwitching();
457 
LastScrollOrigin()458   nsAtom* LastScrollOrigin() const { return mLastScrollOrigin; }
LastSmoothScrollOrigin()459   nsAtom* LastSmoothScrollOrigin() const { return mLastSmoothScrollOrigin; }
CurrentScrollGeneration()460   uint32_t CurrentScrollGeneration() const { return mScrollGeneration; }
LastScrollDestination()461   nsPoint LastScrollDestination() const { return mDestination; }
ResetScrollInfoIfGeneration(uint32_t aGeneration)462   void ResetScrollInfoIfGeneration(uint32_t aGeneration) {
463     if (aGeneration == mScrollGeneration) {
464       mLastScrollOrigin = nullptr;
465       mLastSmoothScrollOrigin = nullptr;
466     }
467   }
468   bool WantAsyncScroll() const;
469   Maybe<mozilla::layers::ScrollMetadata> ComputeScrollMetadata(
470       LayerManager* aLayerManager, const nsIFrame* aContainerReferenceFrame,
471       const Maybe<ContainerLayerParameters>& aParameters,
472       const mozilla::DisplayItemClip* aClip) const;
473   void ClipLayerToDisplayPort(
474       Layer* aLayer, const mozilla::DisplayItemClip* aClip,
475       const ContainerLayerParameters& aParameters) const;
476 
477   // nsIScrollbarMediator
478   void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection,
479                     nsIScrollbarMediator::ScrollSnapMode aSnap =
480                         nsIScrollbarMediator::DISABLE_SNAP);
481   void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection,
482                      nsIScrollbarMediator::ScrollSnapMode aSnap =
483                          nsIScrollbarMediator::DISABLE_SNAP);
484   void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection,
485                     nsIScrollbarMediator::ScrollSnapMode aSnap =
486                         nsIScrollbarMediator::DISABLE_SNAP);
487   void RepeatButtonScroll(nsScrollbarFrame* aScrollbar);
488   void ThumbMoved(nsScrollbarFrame* aScrollbar, nscoord aOldPos,
489                   nscoord aNewPos);
490   void ScrollbarReleased(nsScrollbarFrame* aScrollbar);
491   void ScrollByUnit(nsScrollbarFrame* aScrollbar, ScrollMode aMode,
492                     int32_t aDirection, mozilla::ScrollUnit aUnit,
493                     nsIScrollbarMediator::ScrollSnapMode aSnap =
494                         nsIScrollbarMediator::DISABLE_SNAP);
ShouldSuppressScrollbarRepaints()495   bool ShouldSuppressScrollbarRepaints() const {
496     return mSuppressScrollbarRepaints;
497   }
498 
499   bool DragScroll(WidgetEvent* aEvent);
500 
501   void AsyncScrollbarDragInitiated(uint64_t aDragBlockId,
502                                    mozilla::layers::ScrollDirection aDirection);
503   void AsyncScrollbarDragRejected();
504 
IsRootScrollFrameOfDocument()505   bool IsRootScrollFrameOfDocument() const { return mIsRoot; }
506 
507   bool SmoothScrollVisual(
508       const nsPoint& aVisualViewportOffset,
509       mozilla::layers::FrameMetrics::ScrollOffsetUpdateType aUpdateType);
510 
511   bool IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior) const;
512 
513   // Update minimum-scale size.  The minimum-scale size will be set/used only
514   // if there is overflow-x:hidden region.
515   void UpdateMinimumScaleSize(const nsRect& aScrollableOverflow,
516                               const nsSize& aICBSize);
517 
518   // Return the scroll frame's "true outer size".
519   // This is mOuter->GetSize(), except when mOuter has been sized to reflect
520   // a virtual (layout) viewport in which case this returns the outer size
521   // used to size the physical (visual) viewport.
522   nsSize TrueOuterSize(nsDisplayListBuilder* aBuilder) const;
523 
524   already_AddRefed<Element> MakeScrollbar(dom::NodeInfo* aNodeInfo,
525                                           bool aVertical,
526                                           AnonymousContentKey& aKey);
527 
528   // owning references to the nsIAnonymousContentCreator-built content
529   nsCOMPtr<Element> mHScrollbarContent;
530   nsCOMPtr<Element> mVScrollbarContent;
531   nsCOMPtr<Element> mScrollCornerContent;
532   nsCOMPtr<Element> mResizerContent;
533 
534   class ScrollEvent;
535   class ScrollEndEvent;
536   class AsyncScrollPortEvent;
537   class ScrolledAreaEvent;
538 
539   RefPtr<ScrollEvent> mScrollEvent;
540   RefPtr<ScrollEndEvent> mScrollEndEvent;
541   nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent;
542   nsRevocableEventPtr<ScrolledAreaEvent> mScrolledAreaEvent;
543   nsIFrame* mHScrollbarBox;
544   nsIFrame* mVScrollbarBox;
545   nsIFrame* mScrolledFrame;
546   nsIFrame* mScrollCornerBox;
547   nsIFrame* mResizerBox;
548   nsContainerFrame* mOuter;
549   const nsIFrame* mReferenceFrameDuringPainting;
550   RefPtr<AsyncScroll> mAsyncScroll;
551   RefPtr<AsyncSmoothMSDScroll> mAsyncSmoothMSDScroll;
552   RefPtr<ScrollbarActivity> mScrollbarActivity;
553   nsTArray<nsIScrollPositionListener*> mListeners;
554   nsAtom* mLastScrollOrigin;
555   nsAtom* mLastSmoothScrollOrigin;
556   Maybe<nsPoint> mApzSmoothScrollDestination;
557   uint32_t mScrollGeneration;
558   // NOTE: On mobile this value might be factoring into overflow:hidden region
559   // in the case of the top level document.
560   nsRect mScrollPort;
561   nsSize mMinimumScaleSize;
562 
563   // Stores the ICB size for the root document if this frame is using the
564   // minimum scale size for |mScrollPort|.
565   nsSize mICBSize;
566 
567   // Where we're currently scrolling to, if we're scrolling asynchronously.
568   // If we're not in the middle of an asynchronous scroll then this is
569   // just the current scroll position. ScrollBy will choose its
570   // destination based on this value.
571   nsPoint mDestination;
572 
573   // A goal position to try to scroll to as content loads. As long as mLastPos
574   // matches the current logical scroll position, we try to scroll to
575   // mRestorePos after every reflow --- because after each time content is
576   // loaded/added to the scrollable element, there will be a reflow.
577   // Note that for frames where layout and visual viewport aren't one and the
578   // same thing, this scroll position will be the logical scroll position of
579   // the *visual* viewport, as its position will be more relevant to the user.
580   nsPoint mRestorePos;
581   // The last logical position we scrolled to while trying to restore
582   // mRestorePos, or 0,0 when this is a new frame. Set to -1,-1 once we've
583   // scrolled for any reason other than trying to restore mRestorePos.
584   // Just as with mRestorePos, this position will be the logical position of
585   // the *visual* viewport where available.
586   nsPoint mLastPos;
587 
588   // The latest scroll position we've sent or received from APZ. This
589   // represents the main thread's best knowledge of the APZ scroll position,
590   // and is used to calculate relative scroll offset updates.
591   nsPoint mApzScrollPos;
592 
593   nsExpirationState mActivityExpirationState;
594 
595   nsCOMPtr<nsITimer> mScrollActivityTimer;
596   nsPoint mScrollPosForLayerPixelAlignment;
597 
598   // The scroll position where we last updated frame visibility.
599   nsPoint mLastUpdateFramesPos;
600   nsRect mDisplayPortAtLastFrameUpdate;
601 
602   nsRect mPrevScrolledRect;
603 
604   ScrollableLayerGuid::ViewID mScrollParentID;
605 
606   // Timer to remove the displayport some time after scrolling has stopped
607   nsCOMPtr<nsITimer> mDisplayPortExpiryTimer;
608 
609   ScrollAnchorContainer mAnchor;
610 
611   bool mAllowScrollOriginDowngrade : 1;
612   bool mHadDisplayPortAtLastFrameUpdate : 1;
613   bool mNeverHasVerticalScrollbar : 1;
614   bool mNeverHasHorizontalScrollbar : 1;
615   bool mHasVerticalScrollbar : 1;
616   bool mHasHorizontalScrollbar : 1;
617   bool mFrameIsUpdatingScrollbar : 1;
618   bool mDidHistoryRestore : 1;
619   // Is this the scrollframe for the document's viewport?
620   bool mIsRoot : 1;
621   // True if we should clip all descendants, false if we should only clip
622   // descendants for which we are the containing block.
623   bool mClipAllDescendants : 1;
624   // If true, don't try to layout the scrollbars in Reflow().  This can be
625   // useful if multiple passes are involved, because we don't want to place the
626   // scrollbars at the wrong size.
627   bool mSuppressScrollbarUpdate : 1;
628   // If true, we skipped a scrollbar layout due to mSuppressScrollbarUpdate
629   // being set at some point.  That means we should lay out scrollbars even if
630   // it might not strictly be needed next time mSuppressScrollbarUpdate is
631   // false.
632   bool mSkippedScrollbarLayout : 1;
633 
634   bool mHadNonInitialReflow : 1;
635   // State used only by PostScrollEvents so we know
636   // which overflow states have changed.
637   bool mHorizontalOverflow : 1;
638   bool mVerticalOverflow : 1;
639   bool mPostedReflowCallback : 1;
640   bool mMayHaveDirtyFixedChildren : 1;
641   // If true, need to actually update our scrollbar attributes in the
642   // reflow callback.
643   bool mUpdateScrollbarAttributes : 1;
644   // If true, we should be prepared to scroll using this scrollframe
645   // by placing descendant content into its own layer(s)
646   bool mHasBeenScrolledRecently : 1;
647   // If true, the resizer is collapsed and not displayed
648   bool mCollapsedResizer : 1;
649 
650   // If true, the scroll frame should always be active because we always build
651   // a scrollable layer. Used for asynchronous scrolling.
652   bool mWillBuildScrollableLayer : 1;
653 
654   // If true, the scroll frame is an ancestor of other scrolling frames, so
655   // we shouldn't expire the displayport on this scrollframe unless those
656   // descendant scrollframes also have their displayports removed.
657   bool mIsScrollParent : 1;
658 
659   // If true, add clipping in ScrollFrameHelper::ClipLayerToDisplayPort.
660   bool mAddClipRectToLayer : 1;
661 
662   // True if this frame has been scrolled at least once
663   bool mHasBeenScrolled : 1;
664 
665   // True if the events synthesized by OSX to produce momentum scrolling should
666   // be ignored.  Reset when the next real, non-synthesized scroll event occurs.
667   bool mIgnoreMomentumScroll : 1;
668 
669   // True if the APZ is in the process of async-transforming this scrollframe,
670   // (as best as we can tell on the main thread, anyway).
671   bool mTransformingByAPZ : 1;
672 
673   // True if APZ can scroll this frame asynchronously (i.e. it has an APZC
674   // set up for this frame and it's not a scrollinfo layer).
675   bool mScrollableByAPZ : 1;
676 
677   // True if the APZ is allowed to zoom this scrollframe.
678   bool mZoomableByAPZ : 1;
679 
680   // True if the scroll frame contains out-of-flow content and is inside
681   // a CSS filter.
682   bool mHasOutOfFlowContentInsideFilter : 1;
683 
684   // True if we don't want the scrollbar to repaint itself right now.
685   bool mSuppressScrollbarRepaints : 1;
686 
687   // True if we are using the minimum scale size instead of ICB for scroll port.
688   bool mIsUsingMinimumScaleSize : 1;
689 
690   // True if the minimum scale size has been changed since the last reflow.
691   bool mMinimumScaleSizeChanged : 1;
692 
693   // True if we're processing an scroll event.
694   bool mProcessingScrollEvent : 1;
695 
696   mozilla::layout::ScrollVelocityQueue mVelocityQueue;
697 
698  protected:
699   class AutoScrollbarRepaintSuppression;
700   friend class AutoScrollbarRepaintSuppression;
701   class AutoScrollbarRepaintSuppression {
702    public:
AutoScrollbarRepaintSuppression(ScrollFrameHelper * aHelper,AutoWeakFrame & aWeakOuter,bool aSuppress)703     AutoScrollbarRepaintSuppression(ScrollFrameHelper* aHelper,
704                                     AutoWeakFrame& aWeakOuter, bool aSuppress)
705         : mHelper(aHelper),
706           mWeakOuter(aWeakOuter),
707           mOldSuppressValue(aHelper->mSuppressScrollbarRepaints) {
708       mHelper->mSuppressScrollbarRepaints = aSuppress;
709     }
710 
~AutoScrollbarRepaintSuppression()711     ~AutoScrollbarRepaintSuppression() {
712       if (mWeakOuter.IsAlive()) {
713         mHelper->mSuppressScrollbarRepaints = mOldSuppressValue;
714       }
715     }
716 
717    private:
718     ScrollFrameHelper* mHelper;
719     AutoWeakFrame& mWeakOuter;
720     bool mOldSuppressValue;
721   };
722 
723   /**
724    * @note This method might destroy the frame, pres shell and other objects.
725    */
726   void ScrollToWithOrigin(nsPoint aScrollPosition, ScrollMode aMode,
727                           nsAtom* aOrigin,  // nullptr indicates "other" origin
728                           const nsRect* aRange,
729                           nsIScrollbarMediator::ScrollSnapMode aSnap =
730                               nsIScrollbarMediator::DISABLE_SNAP);
731 
732   void CompleteAsyncScroll(const nsRect& aRange, nsAtom* aOrigin = nullptr);
733 
734   bool HasPluginFrames();
HasPerspective()735   bool HasPerspective() const { return mOuter->ChildrenHavePerspective(); }
736   bool HasBgAttachmentLocal() const;
737   mozilla::StyleDirection GetScrolledFrameDir() const;
738 
739   // Ask APZ to smooth scroll to |aDestination|.
740   // This method does not clamp the destination; callers should clamp it to
741   // either the layout or the visual scroll range (APZ will happily smooth
742   // scroll to either).
743   void ApzSmoothScrollTo(const nsPoint& aDestination, nsAtom* aOrigin);
744 
745   // Removes any RefreshDriver observers we might have registered.
746   void RemoveObservers();
747 };
748 
749 }  // namespace mozilla
750 
751 /**
752  * The scroll frame creates and manages the scrolling view
753  *
754  * It only supports having a single child frame that typically is an area
755  * frame, but doesn't have to be. The child frame must have a view, though
756  *
757  * Scroll frames don't support incremental changes, i.e. you can't replace
758  * or remove the scrolled frame
759  */
760 class nsHTMLScrollFrame : public nsContainerFrame,
761                           public nsIScrollableFrame,
762                           public nsIAnonymousContentCreator,
763                           public nsIStatefulFrame {
764  public:
765   typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
766   typedef mozilla::CSSIntPoint CSSIntPoint;
767   typedef mozilla::ScrollReflowInput ScrollReflowInput;
768   typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
769   friend nsHTMLScrollFrame* NS_NewHTMLScrollFrame(
770       mozilla::PresShell* aPresShell, ComputedStyle* aStyle, bool aIsRoot);
771 
772   NS_DECL_QUERYFRAME
NS_DECL_FRAMEARENA_HELPERS(nsHTMLScrollFrame)773   NS_DECL_FRAMEARENA_HELPERS(nsHTMLScrollFrame)
774 
775   void BuildDisplayList(nsDisplayListBuilder* aBuilder,
776                         const nsDisplayListSet& aLists) override {
777     mHelper.BuildDisplayList(aBuilder, aLists);
778   }
779 
780   bool TryLayout(ScrollReflowInput* aState, ReflowOutput* aKidMetrics,
781                  bool aAssumeVScroll, bool aAssumeHScroll, bool aForce);
782   bool ScrolledContentDependsOnHeight(ScrollReflowInput* aState);
783   void ReflowScrolledFrame(ScrollReflowInput* aState, bool aAssumeHScroll,
784                            bool aAssumeVScroll, ReflowOutput* aMetrics);
785   void ReflowContents(ScrollReflowInput* aState,
786                       const ReflowOutput& aDesiredSize);
787   void PlaceScrollArea(ScrollReflowInput& aState,
788                        const nsPoint& aScrollPosition);
789   nscoord GetIntrinsicVScrollbarWidth(gfxContext* aRenderingContext);
790 
GetBorderRadii(const nsSize & aFrameSize,const nsSize & aBorderArea,Sides aSkipSides,nscoord aRadii[8])791   bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
792                       Sides aSkipSides, nscoord aRadii[8]) const final {
793     return mHelper.GetBorderRadii(aFrameSize, aBorderArea, aSkipSides, aRadii);
794   }
795 
796   nscoord GetMinISize(gfxContext* aRenderingContext) override;
797   nscoord GetPrefISize(gfxContext* aRenderingContext) override;
798   nsresult GetXULPadding(nsMargin& aPadding) final;
799   bool IsXULCollapsed() final;
800 
801   void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
802               const ReflowInput& aReflowInput,
803               nsReflowStatus& aStatus) override;
804   void DidReflow(nsPresContext* aPresContext,
805                  const ReflowInput* aReflowInput) override;
806 
ComputeCustomOverflow(nsOverflowAreas & aOverflowAreas)807   bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) final {
808     return mHelper.ComputeCustomOverflow(aOverflowAreas);
809   }
810 
811   nscoord GetLogicalBaseline(mozilla::WritingMode aWritingMode) const final;
812 
GetVerticalAlignBaseline(mozilla::WritingMode aWM,nscoord * aBaseline)813   bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
814                                 nscoord* aBaseline) const final {
815     NS_ASSERTION(!aWM.IsOrthogonalTo(GetWritingMode()),
816                  "You should only call this on frames with a WM that's "
817                  "parallel to aWM");
818     *aBaseline = GetLogicalBaseline(aWM);
819     return true;
820   }
821 
822   // Recomputes the scrollable overflow area we store in the helper to take
823   // children that are affected by perpsective set on the outer frame and scroll
824   // at different rates.
825   void AdjustForPerspective(nsRect& aScrollableOverflow);
826 
827   // Called to set the child frames. We typically have three: the scroll area,
828   // the vertical scrollbar, and the horizontal scrollbar.
829   void SetInitialChildList(ChildListID aListID,
830                            nsFrameList& aChildList) override;
831   void AppendFrames(ChildListID aListID, nsFrameList& aFrameList) final;
832   void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
833                     const nsLineList::iterator* aPrevFrameLine,
834                     nsFrameList& aFrameList) final;
835   void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) final;
836 
837   void DestroyFrom(nsIFrame* aDestructRoot, PostDestroyData&) override;
838 
GetScrollTargetFrame()839   nsIScrollableFrame* GetScrollTargetFrame() final { return this; }
840 
GetContentInsertionFrame()841   nsContainerFrame* GetContentInsertionFrame() override {
842     return mHelper.GetScrolledFrame()->GetContentInsertionFrame();
843   }
844 
DoesClipChildren()845   bool DoesClipChildren() final { return true; }
846 
GetPositionOfChildIgnoringScrolling(const nsIFrame * aChild)847   nsPoint GetPositionOfChildIgnoringScrolling(const nsIFrame* aChild) final {
848     nsPoint pt = aChild->GetPosition();
849     if (aChild == mHelper.GetScrolledFrame()) pt += GetScrollPosition();
850     return pt;
851   }
852 
853   // nsIAnonymousContentCreator
854   nsresult CreateAnonymousContent(nsTArray<ContentInfo>&) final;
855   void AppendAnonymousContentTo(nsTArray<nsIContent*>&, uint32_t aFilter) final;
856 
857   // nsIScrollableFrame
GetScrolledFrame()858   nsIFrame* GetScrolledFrame() const final {
859     return mHelper.GetScrolledFrame();
860   }
GetScrollStyles()861   mozilla::ScrollStyles GetScrollStyles() const override {
862     return mHelper.GetScrollStylesFromFrame();
863   }
IsForTextControlWithNoScrollbars()864   bool IsForTextControlWithNoScrollbars() const final {
865     return mHelper.IsForTextControlWithNoScrollbars();
866   }
GetOverscrollBehaviorInfo()867   mozilla::layers::OverscrollBehaviorInfo GetOverscrollBehaviorInfo()
868       const final {
869     return mHelper.GetOverscrollBehaviorInfo();
870   }
GetAvailableScrollingDirectionsForUserInputEvents()871   uint32_t GetAvailableScrollingDirectionsForUserInputEvents() const final {
872     return mHelper.GetAvailableScrollingDirectionsForUserInputEvents();
873   }
GetScrollbarVisibility()874   uint32_t GetScrollbarVisibility() const final {
875     return mHelper.GetScrollbarVisibility();
876   }
GetActualScrollbarSizes()877   nsMargin GetActualScrollbarSizes() const final {
878     return mHelper.GetActualScrollbarSizes();
879   }
GetDesiredScrollbarSizes(nsBoxLayoutState * aState)880   nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) final {
881     return mHelper.GetDesiredScrollbarSizes(aState);
882   }
GetDesiredScrollbarSizes(nsPresContext * aPresContext,gfxContext * aRC)883   nsMargin GetDesiredScrollbarSizes(nsPresContext* aPresContext,
884                                     gfxContext* aRC) final {
885     nsBoxLayoutState bls(aPresContext, aRC, 0);
886     return GetDesiredScrollbarSizes(&bls);
887   }
GetNondisappearingScrollbarWidth(nsPresContext * aPresContext,gfxContext * aRC,mozilla::WritingMode aWM)888   nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext,
889                                            gfxContext* aRC,
890                                            mozilla::WritingMode aWM) final {
891     nsBoxLayoutState bls(aPresContext, aRC, 0);
892     return mHelper.GetNondisappearingScrollbarWidth(&bls, aWM);
893   }
GetLayoutSize()894   nsSize GetLayoutSize() const final { return mHelper.GetLayoutSize(); }
GetScrolledRect()895   nsRect GetScrolledRect() const final { return mHelper.GetScrolledRect(); }
GetScrollPortRect()896   nsRect GetScrollPortRect() const final { return mHelper.GetScrollPortRect(); }
GetScrollPosition()897   nsPoint GetScrollPosition() const final {
898     return mHelper.GetScrollPosition();
899   }
GetLogicalScrollPosition()900   nsPoint GetLogicalScrollPosition() const final {
901     return mHelper.GetLogicalScrollPosition();
902   }
GetApzScrollPosition()903   nsPoint GetApzScrollPosition() const final {
904     return mHelper.GetApzScrollPosition();
905   }
GetScrollRange()906   nsRect GetScrollRange() const final { return mHelper.GetLayoutScrollRange(); }
GetVisualViewportSize()907   nsSize GetVisualViewportSize() const final {
908     return mHelper.GetVisualViewportSize();
909   }
GetVisualViewportOffset()910   nsPoint GetVisualViewportOffset() const final {
911     return mHelper.GetVisualViewportOffset();
912   }
GetVisualScrollRange()913   nsRect GetVisualScrollRange() const final {
914     return mHelper.GetVisualScrollRange();
915   }
GetScrollRangeForUserInputEvents()916   nsRect GetScrollRangeForUserInputEvents() const final {
917     return mHelper.GetScrollRangeForUserInputEvents();
918   }
GetLineScrollAmount()919   nsSize GetLineScrollAmount() const final {
920     return mHelper.GetLineScrollAmount();
921   }
GetPageScrollAmount()922   nsSize GetPageScrollAmount() const final {
923     return mHelper.GetPageScrollAmount();
924   }
GetScrollPadding()925   nsMargin GetScrollPadding() const final { return mHelper.GetScrollPadding(); }
926   /**
927    * @note This method might destroy the frame, pres shell and other objects.
928    */
929   void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode,
930                 const nsRect* aRange = nullptr,
931                 nsIScrollbarMediator::ScrollSnapMode aSnap =
932                     nsIScrollbarMediator::DISABLE_SNAP) final {
933     mHelper.ScrollTo(aScrollPosition, aMode, nsGkAtoms::other, aRange, aSnap);
934   }
935   /**
936    * @note This method might destroy the frame, pres shell and other objects.
937    */
938   void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition,
939                          ScrollMode aMode = ScrollMode::Instant,
940                          nsIScrollbarMediator::ScrollSnapMode aSnap =
941                              nsIScrollbarMediator::DEFAULT,
942                          nsAtom* aOrigin = nullptr) final {
943     mHelper.ScrollToCSSPixels(aScrollPosition, aMode, aSnap, aOrigin);
944   }
945   void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
946                                     nsAtom* aOrigin = nullptr) final {
947     mHelper.ScrollToCSSPixelsApproximate(aScrollPosition, aOrigin);
948   }
949   /**
950    * @note This method might destroy the frame, pres shell and other objects.
951    */
GetScrollPositionCSSPixels()952   CSSIntPoint GetScrollPositionCSSPixels() final {
953     return mHelper.GetScrollPositionCSSPixels();
954   }
955   /**
956    * @note This method might destroy the frame, pres shell and other objects.
957    */
958   void ScrollBy(nsIntPoint aDelta, mozilla::ScrollUnit aUnit, ScrollMode aMode,
959                 nsIntPoint* aOverflow, nsAtom* aOrigin = nullptr,
960                 nsIScrollableFrame::ScrollMomentum aMomentum =
961                     nsIScrollableFrame::NOT_MOMENTUM,
962                 nsIScrollbarMediator::ScrollSnapMode aSnap =
963                     nsIScrollbarMediator::DISABLE_SNAP) final {
964     mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin, aMomentum,
965                      aSnap);
966   }
967   void ScrollByCSSPixels(const CSSIntPoint& aDelta,
968                          ScrollMode aMode = ScrollMode::Instant,
969                          nsAtom* aOrigin = nullptr,
970                          nsIScrollbarMediator::ScrollSnapMode aSnap =
971                              nsIScrollbarMediator::DEFAULT) final {
972     mHelper.ScrollByCSSPixels(aDelta, aMode, aOrigin, aSnap);
973   }
ScrollSnap()974   void ScrollSnap() final { mHelper.ScrollSnap(); }
975   /**
976    * @note This method might destroy the frame, pres shell and other objects.
977    */
ScrollToRestoredPosition()978   void ScrollToRestoredPosition() final { mHelper.ScrollToRestoredPosition(); }
AddScrollPositionListener(nsIScrollPositionListener * aListener)979   void AddScrollPositionListener(nsIScrollPositionListener* aListener) final {
980     mHelper.AddScrollPositionListener(aListener);
981   }
RemoveScrollPositionListener(nsIScrollPositionListener * aListener)982   void RemoveScrollPositionListener(
983       nsIScrollPositionListener* aListener) final {
984     mHelper.RemoveScrollPositionListener(aListener);
985   }
986   /**
987    * @note This method might destroy the frame, pres shell and other objects.
988    */
CurPosAttributeChanged(nsIContent * aChild)989   void CurPosAttributeChanged(nsIContent* aChild) final {
990     mHelper.CurPosAttributeChanged(aChild);
991   }
PostScrolledAreaEventForCurrentArea()992   NS_IMETHOD PostScrolledAreaEventForCurrentArea() final {
993     mHelper.PostScrolledAreaEvent();
994     return NS_OK;
995   }
IsScrollingActive(nsDisplayListBuilder * aBuilder)996   bool IsScrollingActive(nsDisplayListBuilder* aBuilder) final {
997     return mHelper.IsScrollingActive(aBuilder);
998   }
IsMaybeScrollingActive()999   bool IsMaybeScrollingActive() const final {
1000     return mHelper.IsMaybeScrollingActive();
1001   }
IsMaybeAsynchronouslyScrolled()1002   bool IsMaybeAsynchronouslyScrolled() final {
1003     return mHelper.IsMaybeAsynchronouslyScrolled();
1004   }
IsProcessingAsyncScroll()1005   bool IsProcessingAsyncScroll() final {
1006     return mHelper.IsProcessingAsyncScroll();
1007   }
ResetScrollPositionForLayerPixelAlignment()1008   void ResetScrollPositionForLayerPixelAlignment() final {
1009     mHelper.ResetScrollPositionForLayerPixelAlignment();
1010   }
DidHistoryRestore()1011   bool DidHistoryRestore() const final { return mHelper.mDidHistoryRestore; }
ClearDidHistoryRestore()1012   void ClearDidHistoryRestore() final { mHelper.mDidHistoryRestore = false; }
MarkEverScrolled()1013   void MarkEverScrolled() final { mHelper.MarkEverScrolled(); }
IsRectNearlyVisible(const nsRect & aRect)1014   bool IsRectNearlyVisible(const nsRect& aRect) final {
1015     return mHelper.IsRectNearlyVisible(aRect);
1016   }
ExpandRectToNearlyVisible(const nsRect & aRect)1017   nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const final {
1018     return mHelper.ExpandRectToNearlyVisible(aRect);
1019   }
LastScrollOrigin()1020   nsAtom* LastScrollOrigin() final { return mHelper.LastScrollOrigin(); }
LastSmoothScrollOrigin()1021   nsAtom* LastSmoothScrollOrigin() final {
1022     return mHelper.LastSmoothScrollOrigin();
1023   }
CurrentScrollGeneration()1024   uint32_t CurrentScrollGeneration() final {
1025     return mHelper.CurrentScrollGeneration();
1026   }
LastScrollDestination()1027   nsPoint LastScrollDestination() final {
1028     return mHelper.LastScrollDestination();
1029   }
ResetScrollInfoIfGeneration(uint32_t aGeneration)1030   void ResetScrollInfoIfGeneration(uint32_t aGeneration) final {
1031     mHelper.ResetScrollInfoIfGeneration(aGeneration);
1032   }
WantAsyncScroll()1033   bool WantAsyncScroll() const final { return mHelper.WantAsyncScroll(); }
ComputeScrollMetadata(LayerManager * aLayerManager,const nsIFrame * aContainerReferenceFrame,const Maybe<ContainerLayerParameters> & aParameters,const mozilla::DisplayItemClip * aClip)1034   mozilla::Maybe<mozilla::layers::ScrollMetadata> ComputeScrollMetadata(
1035       LayerManager* aLayerManager, const nsIFrame* aContainerReferenceFrame,
1036       const Maybe<ContainerLayerParameters>& aParameters,
1037       const mozilla::DisplayItemClip* aClip) const final {
1038     return mHelper.ComputeScrollMetadata(
1039         aLayerManager, aContainerReferenceFrame, aParameters, aClip);
1040   }
ClipLayerToDisplayPort(Layer * aLayer,const mozilla::DisplayItemClip * aClip,const ContainerLayerParameters & aParameters)1041   void ClipLayerToDisplayPort(
1042       Layer* aLayer, const mozilla::DisplayItemClip* aClip,
1043       const ContainerLayerParameters& aParameters) const final {
1044     mHelper.ClipLayerToDisplayPort(aLayer, aClip, aParameters);
1045   }
MarkScrollbarsDirtyForReflow()1046   void MarkScrollbarsDirtyForReflow() const final {
1047     mHelper.MarkScrollbarsDirtyForReflow();
1048   }
DecideScrollableLayer(nsDisplayListBuilder * aBuilder,nsRect * aVisibleRect,nsRect * aDirtyRect,bool aSetBase)1049   bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
1050                              nsRect* aVisibleRect, nsRect* aDirtyRect,
1051                              bool aSetBase) final {
1052     return mHelper.DecideScrollableLayer(aBuilder, aVisibleRect, aDirtyRect,
1053                                          aSetBase);
1054   }
NotifyApzTransaction()1055   void NotifyApzTransaction() final { mHelper.NotifyApzTransaction(); }
NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort)1056   void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort) final {
1057     mHelper.NotifyApproximateFrameVisibilityUpdate(aIgnoreDisplayPort);
1058   }
GetDisplayPortAtLastApproximateFrameVisibilityUpdate(nsRect * aDisplayPort)1059   bool GetDisplayPortAtLastApproximateFrameVisibilityUpdate(
1060       nsRect* aDisplayPort) final {
1061     return mHelper.GetDisplayPortAtLastApproximateFrameVisibilityUpdate(
1062         aDisplayPort);
1063   }
TriggerDisplayPortExpiration()1064   void TriggerDisplayPortExpiration() final {
1065     mHelper.TriggerDisplayPortExpiration();
1066   }
1067 
1068   // nsIStatefulFrame
SaveState()1069   mozilla::UniquePtr<mozilla::PresState> SaveState() final {
1070     return mHelper.SaveState();
1071   }
RestoreState(mozilla::PresState * aState)1072   NS_IMETHOD RestoreState(mozilla::PresState* aState) final {
1073     NS_ENSURE_ARG_POINTER(aState);
1074     mHelper.RestoreState(aState);
1075     return NS_OK;
1076   }
1077 
1078   // nsIScrollbarMediator
1079   void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection,
1080                     nsIScrollbarMediator::ScrollSnapMode aSnap =
1081                         nsIScrollbarMediator::DISABLE_SNAP) final {
1082     mHelper.ScrollByPage(aScrollbar, aDirection, aSnap);
1083   }
1084   void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection,
1085                      nsIScrollbarMediator::ScrollSnapMode aSnap =
1086                          nsIScrollbarMediator::DISABLE_SNAP) final {
1087     mHelper.ScrollByWhole(aScrollbar, aDirection, aSnap);
1088   }
1089   void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection,
1090                     nsIScrollbarMediator::ScrollSnapMode aSnap =
1091                         nsIScrollbarMediator::DISABLE_SNAP) final {
1092     mHelper.ScrollByLine(aScrollbar, aDirection, aSnap);
1093   }
RepeatButtonScroll(nsScrollbarFrame * aScrollbar)1094   void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) final {
1095     mHelper.RepeatButtonScroll(aScrollbar);
1096   }
ThumbMoved(nsScrollbarFrame * aScrollbar,nscoord aOldPos,nscoord aNewPos)1097   void ThumbMoved(nsScrollbarFrame* aScrollbar, nscoord aOldPos,
1098                   nscoord aNewPos) final {
1099     mHelper.ThumbMoved(aScrollbar, aOldPos, aNewPos);
1100   }
ScrollbarReleased(nsScrollbarFrame * aScrollbar)1101   void ScrollbarReleased(nsScrollbarFrame* aScrollbar) final {
1102     mHelper.ScrollbarReleased(aScrollbar);
1103   }
VisibilityChanged(bool aVisible)1104   void VisibilityChanged(bool aVisible) final {}
GetScrollbarBox(bool aVertical)1105   nsIFrame* GetScrollbarBox(bool aVertical) final {
1106     return mHelper.GetScrollbarBox(aVertical);
1107   }
1108   void ScrollbarActivityStarted() const final;
1109   void ScrollbarActivityStopped() const final;
1110 
IsScrollbarOnRight()1111   bool IsScrollbarOnRight() const final { return mHelper.IsScrollbarOnRight(); }
1112 
ShouldSuppressScrollbarRepaints()1113   bool ShouldSuppressScrollbarRepaints() const final {
1114     return mHelper.ShouldSuppressScrollbarRepaints();
1115   }
1116 
SetTransformingByAPZ(bool aTransforming)1117   void SetTransformingByAPZ(bool aTransforming) final {
1118     mHelper.SetTransformingByAPZ(aTransforming);
1119   }
IsTransformingByAPZ()1120   bool IsTransformingByAPZ() const final {
1121     return mHelper.IsTransformingByAPZ();
1122   }
SetScrollableByAPZ(bool aScrollable)1123   void SetScrollableByAPZ(bool aScrollable) final {
1124     mHelper.SetScrollableByAPZ(aScrollable);
1125   }
SetZoomableByAPZ(bool aZoomable)1126   void SetZoomableByAPZ(bool aZoomable) final {
1127     mHelper.SetZoomableByAPZ(aZoomable);
1128   }
SetHasOutOfFlowContentInsideFilter()1129   void SetHasOutOfFlowContentInsideFilter() final {
1130     mHelper.SetHasOutOfFlowContentInsideFilter();
1131   }
1132 
GetScrollSnapInfo()1133   ScrollSnapInfo GetScrollSnapInfo() const final {
1134     return mHelper.GetScrollSnapInfo(Nothing());
1135   }
1136 
DragScroll(mozilla::WidgetEvent * aEvent)1137   bool DragScroll(mozilla::WidgetEvent* aEvent) final {
1138     return mHelper.DragScroll(aEvent);
1139   }
1140 
AsyncScrollbarDragInitiated(uint64_t aDragBlockId,mozilla::layers::ScrollDirection aDirection)1141   void AsyncScrollbarDragInitiated(
1142       uint64_t aDragBlockId,
1143       mozilla::layers::ScrollDirection aDirection) final {
1144     return mHelper.AsyncScrollbarDragInitiated(aDragBlockId, aDirection);
1145   }
1146 
AsyncScrollbarDragRejected()1147   void AsyncScrollbarDragRejected() final {
1148     return mHelper.AsyncScrollbarDragRejected();
1149   }
1150 
IsRootScrollFrameOfDocument()1151   bool IsRootScrollFrameOfDocument() const final {
1152     return mHelper.IsRootScrollFrameOfDocument();
1153   }
1154 
Anchor()1155   const ScrollAnchorContainer* Anchor() const final { return &mHelper.mAnchor; }
1156 
Anchor()1157   ScrollAnchorContainer* Anchor() final { return &mHelper.mAnchor; }
1158 
1159   // Return the scrolled frame.
AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox> & aResult)1160   void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) final {
1161     aResult.AppendElement(OwnedAnonBox(mHelper.GetScrolledFrame()));
1162   }
1163 
SmoothScrollVisual(const nsPoint & aVisualViewportOffset,mozilla::layers::FrameMetrics::ScrollOffsetUpdateType aUpdateType)1164   bool SmoothScrollVisual(
1165       const nsPoint& aVisualViewportOffset,
1166       mozilla::layers::FrameMetrics::ScrollOffsetUpdateType aUpdateType) final {
1167     return mHelper.SmoothScrollVisual(aVisualViewportOffset, aUpdateType);
1168   }
1169 
IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior)1170   bool IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior) const final {
1171     return mHelper.IsSmoothScroll(aBehavior);
1172   }
1173 
1174 #ifdef DEBUG_FRAME_DUMP
1175   nsresult GetFrameName(nsAString& aResult) const override;
1176 #endif
1177 
1178 #ifdef ACCESSIBILITY
1179   mozilla::a11y::AccType AccessibleType() override;
1180 #endif
1181 
1182  protected:
nsHTMLScrollFrame(ComputedStyle * aStyle,nsPresContext * aPresContext,bool aIsRoot)1183   nsHTMLScrollFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
1184                     bool aIsRoot)
1185       : nsHTMLScrollFrame(aStyle, aPresContext, kClassID, aIsRoot) {}
1186 
1187   nsHTMLScrollFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
1188                     nsIFrame::ClassID aID, bool aIsRoot);
SetSuppressScrollbarUpdate(bool aSuppress)1189   void SetSuppressScrollbarUpdate(bool aSuppress) {
1190     mHelper.mSuppressScrollbarUpdate = aSuppress;
1191   }
1192   bool GuessHScrollbarNeeded(const ScrollReflowInput& aState);
1193   bool GuessVScrollbarNeeded(const ScrollReflowInput& aState);
1194 
IsScrollbarUpdateSuppressed()1195   bool IsScrollbarUpdateSuppressed() const {
1196     return mHelper.mSuppressScrollbarUpdate;
1197   }
1198 
1199   // Return whether we're in an "initial" reflow.  Some reflows with
1200   // NS_FRAME_FIRST_REFLOW set are NOT "initial" as far as we're concerned.
1201   bool InInitialReflow() const;
1202 
1203   /**
1204    * Override this to return false if computed bsize/min-bsize/max-bsize
1205    * should NOT be propagated to child content.
1206    * nsListControlFrame uses this.
1207    */
ShouldPropagateComputedBSizeToScrolledContent()1208   virtual bool ShouldPropagateComputedBSizeToScrolledContent() const {
1209     return true;
1210   }
1211 
1212  private:
1213   friend class mozilla::ScrollFrameHelper;
1214   ScrollFrameHelper mHelper;
1215 };
1216 
1217 /**
1218  * The scroll frame creates and manages the scrolling view
1219  *
1220  * It only supports having a single child frame that typically is an area
1221  * frame, but doesn't have to be. The child frame must have a view, though
1222  *
1223  * Scroll frames don't support incremental changes, i.e. you can't replace
1224  * or remove the scrolled frame
1225  */
1226 class nsXULScrollFrame final : public nsBoxFrame,
1227                                public nsIScrollableFrame,
1228                                public nsIAnonymousContentCreator,
1229                                public nsIStatefulFrame {
1230  public:
1231   typedef mozilla::ScrollFrameHelper ScrollFrameHelper;
1232   typedef mozilla::CSSIntPoint CSSIntPoint;
1233   typedef mozilla::layout::ScrollAnchorContainer ScrollAnchorContainer;
1234 
1235   NS_DECL_QUERYFRAME
1236   NS_DECL_FRAMEARENA_HELPERS(nsXULScrollFrame)
1237 
1238   friend nsXULScrollFrame* NS_NewXULScrollFrame(mozilla::PresShell* aPresShell,
1239                                                 ComputedStyle* aStyle,
1240                                                 bool aIsRoot,
1241                                                 bool aClipAllDescendants);
1242 
BuildDisplayList(nsDisplayListBuilder * aBuilder,const nsDisplayListSet & aLists)1243   void BuildDisplayList(nsDisplayListBuilder* aBuilder,
1244                         const nsDisplayListSet& aLists) final {
1245     mHelper.BuildDisplayList(aBuilder, aLists);
1246   }
1247 
1248   // XXXldb Is this actually used?
1249 #if 0
1250   nscoord GetMinISize(gfxContext *aRenderingContext) final;
1251 #endif
1252 
ComputeCustomOverflow(nsOverflowAreas & aOverflowAreas)1253   bool ComputeCustomOverflow(nsOverflowAreas& aOverflowAreas) final {
1254     return mHelper.ComputeCustomOverflow(aOverflowAreas);
1255   }
1256 
GetVerticalAlignBaseline(mozilla::WritingMode aWM,nscoord * aBaseline)1257   bool GetVerticalAlignBaseline(mozilla::WritingMode aWM,
1258                                 nscoord* aBaseline) const final {
1259     *aBaseline = GetLogicalBaseline(aWM);
1260     return true;
1261   }
1262 
1263   // Called to set the child frames. We typically have three: the scroll area,
1264   // the vertical scrollbar, and the horizontal scrollbar.
1265   void SetInitialChildList(ChildListID aListID, nsFrameList& aChildList) final;
1266   void AppendFrames(ChildListID aListID, nsFrameList& aFrameList) final;
1267   void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
1268                     const nsLineList::iterator* aPrevFrameLine,
1269                     nsFrameList& aFrameList) final;
1270   void RemoveFrame(ChildListID aListID, nsIFrame* aOldFrame) final;
1271 
1272   void DestroyFrom(nsIFrame* aDestructRoot,
1273                    PostDestroyData& aPostDestroyData) final;
1274 
GetScrollTargetFrame()1275   nsIScrollableFrame* GetScrollTargetFrame() final { return this; }
1276 
GetContentInsertionFrame()1277   nsContainerFrame* GetContentInsertionFrame() final {
1278     return mHelper.GetScrolledFrame()->GetContentInsertionFrame();
1279   }
1280 
DoesClipChildren()1281   bool DoesClipChildren() final { return true; }
1282 
GetPositionOfChildIgnoringScrolling(const nsIFrame * aChild)1283   nsPoint GetPositionOfChildIgnoringScrolling(const nsIFrame* aChild) final {
1284     nsPoint pt = aChild->GetPosition();
1285     if (aChild == mHelper.GetScrolledFrame())
1286       pt += mHelper.GetLogicalScrollPosition();
1287     return pt;
1288   }
1289 
1290   // nsIAnonymousContentCreator
1291   nsresult CreateAnonymousContent(nsTArray<ContentInfo>& aElements) final;
1292   void AppendAnonymousContentTo(nsTArray<nsIContent*>& aElements,
1293                                 uint32_t aFilter) final;
1294 
1295   nsSize GetXULMinSize(nsBoxLayoutState& aBoxLayoutState) final;
1296   nsSize GetXULPrefSize(nsBoxLayoutState& aBoxLayoutState) final;
1297   nsSize GetXULMaxSize(nsBoxLayoutState& aBoxLayoutState) final;
1298   nscoord GetXULBoxAscent(nsBoxLayoutState& aBoxLayoutState) final;
1299 
1300   NS_IMETHOD DoXULLayout(nsBoxLayoutState& aBoxLayoutState) final;
1301   nsresult GetXULPadding(nsMargin& aPadding) final;
1302 
GetBorderRadii(const nsSize & aFrameSize,const nsSize & aBorderArea,Sides aSkipSides,nscoord aRadii[8])1303   bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
1304                       Sides aSkipSides, nscoord aRadii[8]) const final {
1305     return mHelper.GetBorderRadii(aFrameSize, aBorderArea, aSkipSides, aRadii);
1306   }
1307 
1308   nsresult XULLayout(nsBoxLayoutState& aState);
1309   void LayoutScrollArea(nsBoxLayoutState& aState,
1310                         const nsPoint& aScrollPosition);
1311 
1312   static bool AddRemoveScrollbar(bool& aHasScrollbar, nscoord& aXY,
1313                                  nscoord& aSize, nscoord aSbSize,
1314                                  bool aOnRightOrBottom, bool aAdd);
1315 
1316   bool AddRemoveScrollbar(nsBoxLayoutState& aState, bool aOnRightOrBottom,
1317                           bool aHorizontal, bool aAdd);
1318 
1319   bool AddHorizontalScrollbar(nsBoxLayoutState& aState, bool aOnBottom);
1320   bool AddVerticalScrollbar(nsBoxLayoutState& aState, bool aOnRight);
1321   void RemoveHorizontalScrollbar(nsBoxLayoutState& aState, bool aOnBottom);
1322   void RemoveVerticalScrollbar(nsBoxLayoutState& aState, bool aOnRight);
1323 
1324   static void AdjustReflowInputForPrintPreview(nsBoxLayoutState& aState,
1325                                                bool& aSetBack);
1326   static void AdjustReflowInputBack(nsBoxLayoutState& aState, bool aSetBack);
1327 
1328   // nsIScrollableFrame
GetScrolledFrame()1329   nsIFrame* GetScrolledFrame() const final {
1330     return mHelper.GetScrolledFrame();
1331   }
GetScrollStyles()1332   mozilla::ScrollStyles GetScrollStyles() const final {
1333     return mHelper.GetScrollStylesFromFrame();
1334   }
IsForTextControlWithNoScrollbars()1335   bool IsForTextControlWithNoScrollbars() const final {
1336     return mHelper.IsForTextControlWithNoScrollbars();
1337   }
GetOverscrollBehaviorInfo()1338   mozilla::layers::OverscrollBehaviorInfo GetOverscrollBehaviorInfo()
1339       const final {
1340     return mHelper.GetOverscrollBehaviorInfo();
1341   }
GetAvailableScrollingDirectionsForUserInputEvents()1342   uint32_t GetAvailableScrollingDirectionsForUserInputEvents() const final {
1343     return mHelper.GetAvailableScrollingDirectionsForUserInputEvents();
1344   }
GetScrollbarVisibility()1345   uint32_t GetScrollbarVisibility() const final {
1346     return mHelper.GetScrollbarVisibility();
1347   }
GetActualScrollbarSizes()1348   nsMargin GetActualScrollbarSizes() const final {
1349     return mHelper.GetActualScrollbarSizes();
1350   }
GetDesiredScrollbarSizes(nsBoxLayoutState * aState)1351   nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) final {
1352     return mHelper.GetDesiredScrollbarSizes(aState);
1353   }
GetDesiredScrollbarSizes(nsPresContext * aPresContext,gfxContext * aRC)1354   nsMargin GetDesiredScrollbarSizes(nsPresContext* aPresContext,
1355                                     gfxContext* aRC) final {
1356     nsBoxLayoutState bls(aPresContext, aRC, 0);
1357     return GetDesiredScrollbarSizes(&bls);
1358   }
GetNondisappearingScrollbarWidth(nsPresContext * aPresContext,gfxContext * aRC,mozilla::WritingMode aWM)1359   nscoord GetNondisappearingScrollbarWidth(nsPresContext* aPresContext,
1360                                            gfxContext* aRC,
1361                                            mozilla::WritingMode aWM) final {
1362     nsBoxLayoutState bls(aPresContext, aRC, 0);
1363     return mHelper.GetNondisappearingScrollbarWidth(&bls, aWM);
1364   }
GetLayoutSize()1365   nsSize GetLayoutSize() const final { return mHelper.GetLayoutSize(); }
GetScrolledRect()1366   nsRect GetScrolledRect() const final { return mHelper.GetScrolledRect(); }
GetScrollPortRect()1367   nsRect GetScrollPortRect() const final { return mHelper.GetScrollPortRect(); }
GetScrollPosition()1368   nsPoint GetScrollPosition() const final {
1369     return mHelper.GetScrollPosition();
1370   }
GetLogicalScrollPosition()1371   nsPoint GetLogicalScrollPosition() const final {
1372     return mHelper.GetLogicalScrollPosition();
1373   }
GetApzScrollPosition()1374   nsPoint GetApzScrollPosition() const final {
1375     return mHelper.GetApzScrollPosition();
1376   }
GetScrollRange()1377   nsRect GetScrollRange() const final { return mHelper.GetLayoutScrollRange(); }
GetVisualViewportSize()1378   nsSize GetVisualViewportSize() const final {
1379     return mHelper.GetVisualViewportSize();
1380   }
GetVisualViewportOffset()1381   nsPoint GetVisualViewportOffset() const final {
1382     return mHelper.GetVisualViewportOffset();
1383   }
GetVisualScrollRange()1384   nsRect GetVisualScrollRange() const final {
1385     return mHelper.GetVisualScrollRange();
1386   }
GetScrollRangeForUserInputEvents()1387   nsRect GetScrollRangeForUserInputEvents() const final {
1388     return mHelper.GetScrollRangeForUserInputEvents();
1389   }
GetLineScrollAmount()1390   nsSize GetLineScrollAmount() const final {
1391     return mHelper.GetLineScrollAmount();
1392   }
GetPageScrollAmount()1393   nsSize GetPageScrollAmount() const final {
1394     return mHelper.GetPageScrollAmount();
1395   }
GetScrollPadding()1396   nsMargin GetScrollPadding() const final { return mHelper.GetScrollPadding(); }
1397   /**
1398    * @note This method might destroy the frame, pres shell and other objects.
1399    */
1400   void ScrollTo(
1401       nsPoint aScrollPosition, ScrollMode aMode, const nsRect* aRange = nullptr,
1402       ScrollSnapMode aSnap = nsIScrollbarMediator::DISABLE_SNAP) final {
1403     mHelper.ScrollTo(aScrollPosition, aMode, nsGkAtoms::other, aRange, aSnap);
1404   }
1405   /**
1406    * @note This method might destroy the frame, pres shell and other objects.
1407    */
1408   void ScrollToCSSPixels(const CSSIntPoint& aScrollPosition,
1409                          ScrollMode aMode = ScrollMode::Instant,
1410                          nsIScrollbarMediator::ScrollSnapMode aSnap =
1411                              nsIScrollbarMediator::DISABLE_SNAP,
1412                          nsAtom* aOrigin = nullptr) final {
1413     mHelper.ScrollToCSSPixels(aScrollPosition, aMode, aSnap, aOrigin);
1414   }
1415   void ScrollToCSSPixelsApproximate(const mozilla::CSSPoint& aScrollPosition,
1416                                     nsAtom* aOrigin = nullptr) final {
1417     mHelper.ScrollToCSSPixelsApproximate(aScrollPosition, aOrigin);
1418   }
GetScrollPositionCSSPixels()1419   CSSIntPoint GetScrollPositionCSSPixels() final {
1420     return mHelper.GetScrollPositionCSSPixels();
1421   }
1422   /**
1423    * @note This method might destroy the frame, pres shell and other objects.
1424    */
1425   void ScrollBy(nsIntPoint aDelta, mozilla::ScrollUnit aUnit, ScrollMode aMode,
1426                 nsIntPoint* aOverflow, nsAtom* aOrigin = nullptr,
1427                 nsIScrollableFrame::ScrollMomentum aMomentum =
1428                     nsIScrollableFrame::NOT_MOMENTUM,
1429                 nsIScrollbarMediator::ScrollSnapMode aSnap =
1430                     nsIScrollbarMediator::DISABLE_SNAP) final {
1431     mHelper.ScrollBy(aDelta, aUnit, aMode, aOverflow, aOrigin, aMomentum,
1432                      aSnap);
1433   }
1434   void ScrollByCSSPixels(const CSSIntPoint& aDelta,
1435                          ScrollMode aMode = ScrollMode::Instant,
1436                          nsAtom* aOrigin = nullptr,
1437                          nsIScrollbarMediator::ScrollSnapMode aSnap =
1438                              nsIScrollbarMediator::DEFAULT) final {
1439     mHelper.ScrollByCSSPixels(aDelta, aMode, aOrigin, aSnap);
1440   }
ScrollSnap()1441   void ScrollSnap() final { mHelper.ScrollSnap(); }
1442   /**
1443    * @note This method might destroy the frame, pres shell and other objects.
1444    */
ScrollToRestoredPosition()1445   void ScrollToRestoredPosition() final { mHelper.ScrollToRestoredPosition(); }
AddScrollPositionListener(nsIScrollPositionListener * aListener)1446   void AddScrollPositionListener(nsIScrollPositionListener* aListener) final {
1447     mHelper.AddScrollPositionListener(aListener);
1448   }
RemoveScrollPositionListener(nsIScrollPositionListener * aListener)1449   void RemoveScrollPositionListener(
1450       nsIScrollPositionListener* aListener) final {
1451     mHelper.RemoveScrollPositionListener(aListener);
1452   }
1453   /**
1454    * @note This method might destroy the frame, pres shell and other objects.
1455    */
CurPosAttributeChanged(nsIContent * aChild)1456   void CurPosAttributeChanged(nsIContent* aChild) final {
1457     mHelper.CurPosAttributeChanged(aChild);
1458   }
PostScrolledAreaEventForCurrentArea()1459   NS_IMETHOD PostScrolledAreaEventForCurrentArea() final {
1460     mHelper.PostScrolledAreaEvent();
1461     return NS_OK;
1462   }
IsScrollingActive(nsDisplayListBuilder * aBuilder)1463   bool IsScrollingActive(nsDisplayListBuilder* aBuilder) final {
1464     return mHelper.IsScrollingActive(aBuilder);
1465   }
IsMaybeScrollingActive()1466   bool IsMaybeScrollingActive() const final {
1467     return mHelper.IsMaybeScrollingActive();
1468   }
IsMaybeAsynchronouslyScrolled()1469   bool IsMaybeAsynchronouslyScrolled() final {
1470     return mHelper.IsMaybeAsynchronouslyScrolled();
1471   }
IsProcessingAsyncScroll()1472   bool IsProcessingAsyncScroll() final {
1473     return mHelper.IsProcessingAsyncScroll();
1474   }
ResetScrollPositionForLayerPixelAlignment()1475   void ResetScrollPositionForLayerPixelAlignment() final {
1476     mHelper.ResetScrollPositionForLayerPixelAlignment();
1477   }
DidHistoryRestore()1478   bool DidHistoryRestore() const final { return mHelper.mDidHistoryRestore; }
ClearDidHistoryRestore()1479   void ClearDidHistoryRestore() final { mHelper.mDidHistoryRestore = false; }
MarkEverScrolled()1480   void MarkEverScrolled() final { mHelper.MarkEverScrolled(); }
IsRectNearlyVisible(const nsRect & aRect)1481   bool IsRectNearlyVisible(const nsRect& aRect) final {
1482     return mHelper.IsRectNearlyVisible(aRect);
1483   }
ExpandRectToNearlyVisible(const nsRect & aRect)1484   nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const final {
1485     return mHelper.ExpandRectToNearlyVisible(aRect);
1486   }
LastScrollOrigin()1487   nsAtom* LastScrollOrigin() final { return mHelper.LastScrollOrigin(); }
LastSmoothScrollOrigin()1488   nsAtom* LastSmoothScrollOrigin() final {
1489     return mHelper.LastSmoothScrollOrigin();
1490   }
CurrentScrollGeneration()1491   uint32_t CurrentScrollGeneration() final {
1492     return mHelper.CurrentScrollGeneration();
1493   }
LastScrollDestination()1494   nsPoint LastScrollDestination() final {
1495     return mHelper.LastScrollDestination();
1496   }
ResetScrollInfoIfGeneration(uint32_t aGeneration)1497   void ResetScrollInfoIfGeneration(uint32_t aGeneration) final {
1498     mHelper.ResetScrollInfoIfGeneration(aGeneration);
1499   }
WantAsyncScroll()1500   bool WantAsyncScroll() const final { return mHelper.WantAsyncScroll(); }
ComputeScrollMetadata(LayerManager * aLayerManager,const nsIFrame * aContainerReferenceFrame,const Maybe<ContainerLayerParameters> & aParameters,const mozilla::DisplayItemClip * aClip)1501   mozilla::Maybe<mozilla::layers::ScrollMetadata> ComputeScrollMetadata(
1502       LayerManager* aLayerManager, const nsIFrame* aContainerReferenceFrame,
1503       const Maybe<ContainerLayerParameters>& aParameters,
1504       const mozilla::DisplayItemClip* aClip) const final {
1505     return mHelper.ComputeScrollMetadata(
1506         aLayerManager, aContainerReferenceFrame, aParameters, aClip);
1507   }
ClipLayerToDisplayPort(Layer * aLayer,const mozilla::DisplayItemClip * aClip,const ContainerLayerParameters & aParameters)1508   void ClipLayerToDisplayPort(
1509       Layer* aLayer, const mozilla::DisplayItemClip* aClip,
1510       const ContainerLayerParameters& aParameters) const final {
1511     mHelper.ClipLayerToDisplayPort(aLayer, aClip, aParameters);
1512   }
MarkScrollbarsDirtyForReflow()1513   void MarkScrollbarsDirtyForReflow() const final {
1514     mHelper.MarkScrollbarsDirtyForReflow();
1515   }
1516 
1517   // nsIStatefulFrame
SaveState()1518   mozilla::UniquePtr<mozilla::PresState> SaveState() final {
1519     return mHelper.SaveState();
1520   }
RestoreState(mozilla::PresState * aState)1521   NS_IMETHOD RestoreState(mozilla::PresState* aState) final {
1522     NS_ENSURE_ARG_POINTER(aState);
1523     mHelper.RestoreState(aState);
1524     return NS_OK;
1525   }
1526 
IsFrameOfType(uint32_t aFlags)1527   bool IsFrameOfType(uint32_t aFlags) const final {
1528     // Override bogus IsFrameOfType in nsBoxFrame.
1529     if (aFlags & (nsIFrame::eReplacedContainsBlock | nsIFrame::eReplaced))
1530       return false;
1531     return nsBoxFrame::IsFrameOfType(aFlags);
1532   }
1533 
1534   void ScrollByPage(nsScrollbarFrame* aScrollbar, int32_t aDirection,
1535                     nsIScrollbarMediator::ScrollSnapMode aSnap =
1536                         nsIScrollbarMediator::DISABLE_SNAP) final {
1537     mHelper.ScrollByPage(aScrollbar, aDirection, aSnap);
1538   }
1539   void ScrollByWhole(nsScrollbarFrame* aScrollbar, int32_t aDirection,
1540                      nsIScrollbarMediator::ScrollSnapMode aSnap =
1541                          nsIScrollbarMediator::DISABLE_SNAP) final {
1542     mHelper.ScrollByWhole(aScrollbar, aDirection, aSnap);
1543   }
1544   void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection,
1545                     nsIScrollbarMediator::ScrollSnapMode aSnap =
1546                         nsIScrollbarMediator::DISABLE_SNAP) final {
1547     mHelper.ScrollByLine(aScrollbar, aDirection, aSnap);
1548   }
RepeatButtonScroll(nsScrollbarFrame * aScrollbar)1549   void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) final {
1550     mHelper.RepeatButtonScroll(aScrollbar);
1551   }
ThumbMoved(nsScrollbarFrame * aScrollbar,nscoord aOldPos,nscoord aNewPos)1552   void ThumbMoved(nsScrollbarFrame* aScrollbar, nscoord aOldPos,
1553                   nscoord aNewPos) final {
1554     mHelper.ThumbMoved(aScrollbar, aOldPos, aNewPos);
1555   }
ScrollbarReleased(nsScrollbarFrame * aScrollbar)1556   void ScrollbarReleased(nsScrollbarFrame* aScrollbar) final {
1557     mHelper.ScrollbarReleased(aScrollbar);
1558   }
VisibilityChanged(bool aVisible)1559   void VisibilityChanged(bool aVisible) final {}
GetScrollbarBox(bool aVertical)1560   nsIFrame* GetScrollbarBox(bool aVertical) final {
1561     return mHelper.GetScrollbarBox(aVertical);
1562   }
1563 
1564   void ScrollbarActivityStarted() const final;
1565   void ScrollbarActivityStopped() const final;
1566 
IsScrollbarOnRight()1567   bool IsScrollbarOnRight() const final { return mHelper.IsScrollbarOnRight(); }
1568 
ShouldSuppressScrollbarRepaints()1569   bool ShouldSuppressScrollbarRepaints() const final {
1570     return mHelper.ShouldSuppressScrollbarRepaints();
1571   }
1572 
SetTransformingByAPZ(bool aTransforming)1573   void SetTransformingByAPZ(bool aTransforming) final {
1574     mHelper.SetTransformingByAPZ(aTransforming);
1575   }
IsTransformingByAPZ()1576   bool IsTransformingByAPZ() const final {
1577     return mHelper.IsTransformingByAPZ();
1578   }
SetScrollableByAPZ(bool aScrollable)1579   void SetScrollableByAPZ(bool aScrollable) final {
1580     mHelper.SetScrollableByAPZ(aScrollable);
1581   }
SetZoomableByAPZ(bool aZoomable)1582   void SetZoomableByAPZ(bool aZoomable) final {
1583     mHelper.SetZoomableByAPZ(aZoomable);
1584   }
SetHasOutOfFlowContentInsideFilter()1585   void SetHasOutOfFlowContentInsideFilter() final {
1586     mHelper.SetHasOutOfFlowContentInsideFilter();
1587   }
DecideScrollableLayer(nsDisplayListBuilder * aBuilder,nsRect * aVisibleRect,nsRect * aDirtyRect,bool aSetBase)1588   bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
1589                              nsRect* aVisibleRect, nsRect* aDirtyRect,
1590                              bool aSetBase) final {
1591     return mHelper.DecideScrollableLayer(aBuilder, aVisibleRect, aDirtyRect,
1592                                          aSetBase);
1593   }
NotifyApzTransaction()1594   void NotifyApzTransaction() final { mHelper.NotifyApzTransaction(); }
NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort)1595   void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort) final {
1596     mHelper.NotifyApproximateFrameVisibilityUpdate(aIgnoreDisplayPort);
1597   }
GetDisplayPortAtLastApproximateFrameVisibilityUpdate(nsRect * aDisplayPort)1598   bool GetDisplayPortAtLastApproximateFrameVisibilityUpdate(
1599       nsRect* aDisplayPort) final {
1600     return mHelper.GetDisplayPortAtLastApproximateFrameVisibilityUpdate(
1601         aDisplayPort);
1602   }
TriggerDisplayPortExpiration()1603   void TriggerDisplayPortExpiration() final {
1604     mHelper.TriggerDisplayPortExpiration();
1605   }
1606 
GetScrollSnapInfo()1607   ScrollSnapInfo GetScrollSnapInfo() const final {
1608     return mHelper.GetScrollSnapInfo(Nothing());
1609   }
1610 
DragScroll(mozilla::WidgetEvent * aEvent)1611   bool DragScroll(mozilla::WidgetEvent* aEvent) final {
1612     return mHelper.DragScroll(aEvent);
1613   }
1614 
AsyncScrollbarDragInitiated(uint64_t aDragBlockId,mozilla::layers::ScrollDirection aDirection)1615   void AsyncScrollbarDragInitiated(
1616       uint64_t aDragBlockId,
1617       mozilla::layers::ScrollDirection aDirection) final {
1618     return mHelper.AsyncScrollbarDragInitiated(aDragBlockId, aDirection);
1619   }
1620 
AsyncScrollbarDragRejected()1621   void AsyncScrollbarDragRejected() final {
1622     return mHelper.AsyncScrollbarDragRejected();
1623   }
1624 
IsRootScrollFrameOfDocument()1625   bool IsRootScrollFrameOfDocument() const final {
1626     return mHelper.IsRootScrollFrameOfDocument();
1627   }
1628 
Anchor()1629   const ScrollAnchorContainer* Anchor() const final { return &mHelper.mAnchor; }
1630 
Anchor()1631   ScrollAnchorContainer* Anchor() final { return &mHelper.mAnchor; }
1632 
1633   // Return the scrolled frame.
AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox> & aResult)1634   void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) final {
1635     aResult.AppendElement(OwnedAnonBox(mHelper.GetScrolledFrame()));
1636   }
1637 
SmoothScrollVisual(const nsPoint & aVisualViewportOffset,mozilla::layers::FrameMetrics::ScrollOffsetUpdateType aUpdateType)1638   bool SmoothScrollVisual(
1639       const nsPoint& aVisualViewportOffset,
1640       mozilla::layers::FrameMetrics::ScrollOffsetUpdateType aUpdateType) final {
1641     return mHelper.SmoothScrollVisual(aVisualViewportOffset, aUpdateType);
1642   }
1643 
IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior)1644   bool IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior) const final {
1645     return mHelper.IsSmoothScroll(aBehavior);
1646   }
1647 
1648 #ifdef DEBUG_FRAME_DUMP
1649   nsresult GetFrameName(nsAString& aResult) const final;
1650 #endif
1651 
1652  protected:
1653   nsXULScrollFrame(ComputedStyle*, nsPresContext*, bool aIsRoot,
1654                    bool aClipAllDescendants);
1655 
1656   void ClampAndSetBounds(nsBoxLayoutState& aState, nsRect& aRect,
1657                          nsPoint aScrollPosition,
1658                          bool aRemoveOverflowAreas = false) {
1659     /*
1660      * For RTL frames, restore the original scrolled position of the right
1661      * edge, then subtract the current width to find the physical position.
1662      */
1663     if (!mHelper.IsPhysicalLTR()) {
1664       aRect.x = mHelper.mScrollPort.XMost() - aScrollPosition.x - aRect.width;
1665     }
1666     mHelper.mScrolledFrame->SetXULBounds(aState, aRect, aRemoveOverflowAreas);
1667   }
1668 
1669  private:
1670   friend class mozilla::ScrollFrameHelper;
1671   ScrollFrameHelper mHelper;
1672 };
1673 
1674 #endif /* nsGfxScrollFrame_h___ */
1675