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