tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ScrollContainerFrame.h (61869B)


      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 mozilla_ScrollContainerFrame_h_
     10 #define mozilla_ScrollContainerFrame_h_
     11 
     12 #include "FrameMetrics.h"
     13 #include "ScrollVelocityQueue.h"
     14 #include "mozilla/Attributes.h"
     15 #include "mozilla/ScrollOrigin.h"
     16 #include "mozilla/ScrollTypes.h"
     17 #include "mozilla/dom/WindowBinding.h"  // for mozilla::dom::ScrollBehavior
     18 #include "mozilla/layout/ScrollAnchorContainer.h"
     19 #include "nsContainerFrame.h"
     20 #include "nsExpirationTracker.h"
     21 #include "nsIAnonymousContentCreator.h"
     22 #include "nsIReflowCallback.h"
     23 #include "nsIScrollbarMediator.h"
     24 #include "nsIStatefulFrame.h"
     25 #include "nsQueryFrame.h"
     26 #include "nsThreadUtils.h"
     27 
     28 class nsPresContext;
     29 class nsIContent;
     30 class nsAtom;
     31 class AutoContainsBlendModeCapturer;
     32 
     33 namespace mozilla {
     34 struct nsDisplayListCollection;
     35 class PresShell;
     36 class PresState;
     37 enum class PhysicalAxis : uint8_t;
     38 enum class StyleScrollbarWidth : uint8_t;
     39 class ScrollContainerFrame;
     40 class ScrollPositionUpdate;
     41 class StickyScrollContainer;
     42 struct ScrollReflowInput;
     43 struct ScrollStyles;
     44 struct StyleScrollSnapAlign;
     45 namespace layers {
     46 class Layer;
     47 class WebRenderLayerManager;
     48 }  // namespace layers
     49 namespace layout {
     50 class ScrollbarActivity;
     51 }  // namespace layout
     52 
     53 }  // namespace mozilla
     54 
     55 mozilla::ScrollContainerFrame* NS_NewScrollContainerFrame(
     56    mozilla::PresShell* aPresShell, mozilla::ComputedStyle* aStyle,
     57    bool aIsRoot);
     58 
     59 namespace mozilla {
     60 
     61 /**
     62 * The scroll frame creates and manages the scrolling view
     63 *
     64 * It only supports having a single child frame that typically is an area
     65 * frame, but doesn't have to be. The child frame must have a view, though
     66 *
     67 * Scroll frames don't support incremental changes, i.e. you can't replace
     68 * or remove the scrolled frame
     69 */
     70 class ScrollContainerFrame : public nsContainerFrame,
     71                             public nsIScrollbarMediator,
     72                             public nsIAnonymousContentCreator,
     73                             public nsIReflowCallback,
     74                             public nsIStatefulFrame {
     75 public:
     76  using CSSPoint = mozilla::CSSPoint;
     77  using Element = dom::Element;
     78  using ScrollAnchorContainer = layout::ScrollAnchorContainer;
     79  using SnapTargetSet = nsTHashSet<RefPtr<nsIContent>>;
     80 
     81  friend ScrollContainerFrame* ::NS_NewScrollContainerFrame(
     82      mozilla::PresShell* aPresShell, ComputedStyle* aStyle, bool aIsRoot);
     83  friend class layout::ScrollAnchorContainer;
     84 
     85  NS_DECL_QUERYFRAME
     86  NS_DECL_FRAMEARENA_HELPERS(ScrollContainerFrame)
     87 
     88  void BuildDisplayList(nsDisplayListBuilder* aBuilder,
     89                        const nsDisplayListSet& aLists) override;
     90 
     91  // Return the sum of inline-size of the scrollbar gutters (if any) at the
     92  // inline-start and inline-end edges of the scroll frame (for a potential
     93  // scrollbar that scrolls in the block axis).
     94  nscoord IntrinsicScrollbarGutterSizeAtInlineEdges() const;
     95 
     96  // Return the size of space created by scrollbar-gutter or actual scrollbars,
     97  // assuming that the content is *not* overflowing the container. In other
     98  // words, this space is created by stable scrollbar-gutter or by scrollbars
     99  // due to "overflow: scroll".
    100  nsMargin IntrinsicScrollbarGutterSize() const;
    101 
    102  // Compute stable scrollbar-gutter from scrollbar-width and scrollbar-gutter
    103  // properties.
    104  //
    105  // Note: this method doesn't consider overflow property and the space created
    106  // by the actual scrollbars. That is, if scrollbar-gutter is 'auto', this
    107  // method just returns empty result.
    108  nsMargin ComputeStableScrollbarGutter(
    109      const StyleScrollbarWidth& aStyleScrollbarWidth,
    110      const StyleScrollbarGutter& aStyleScrollbarGutter) const;
    111 
    112  bool GetBorderRadii(const nsSize& aFrameSize, const nsSize& aBorderArea,
    113                      nsIFrame::Sides aSkipSides,
    114                      nsRectCornerRadii&) const final;
    115 
    116  nscoord IntrinsicISize(const IntrinsicSizeInput& aInput,
    117                         IntrinsicISizeType aType) override;
    118 
    119  void Reflow(nsPresContext* aPresContext, ReflowOutput& aDesiredSize,
    120              const ReflowInput& aReflowInput,
    121              nsReflowStatus& aStatus) override;
    122  void DidReflow(nsPresContext* aPresContext,
    123                 const ReflowInput* aReflowInput) override;
    124 
    125  bool ComputeCustomOverflow(OverflowAreas& aOverflowAreas) final;
    126 
    127  BaselineSharingGroup GetDefaultBaselineSharingGroup() const override;
    128  nscoord SynthesizeFallbackBaseline(
    129      WritingMode aWM, BaselineSharingGroup aBaselineGroup) const override;
    130  Maybe<nscoord> GetNaturalBaselineBOffset(
    131      WritingMode aWM, BaselineSharingGroup aBaselineGroup,
    132      BaselineExportContext aExportContext) const override;
    133 
    134  StickyScrollContainer* GetStickyContainer() const {
    135    return mStickyContainer.get();
    136  }
    137  StickyScrollContainer& EnsureStickyContainer();
    138 
    139  // Recomputes the scrollable overflow area we store in the helper to take
    140  // children that are affected by perpsective set on the outer frame and scroll
    141  // at different rates.
    142  void AdjustForPerspective(nsRect& aScrollableOverflow);
    143 
    144  // Called to set the child frames. We typically have three: the scroll area,
    145  // the vertical scrollbar, and the horizontal scrollbar.
    146  void SetInitialChildList(ChildListID aListID,
    147                           nsFrameList&& aChildList) override;
    148  void AppendFrames(ChildListID aListID, nsFrameList&& aFrameList) final;
    149  void InsertFrames(ChildListID aListID, nsIFrame* aPrevFrame,
    150                    const nsLineList::iterator* aPrevFrameLine,
    151                    nsFrameList&& aFrameList) final;
    152  void RemoveFrame(DestroyContext&, ChildListID, nsIFrame*) final;
    153 
    154  void DidSetComputedStyle(ComputedStyle* aOldComputedStyle) final;
    155 
    156  void Destroy(DestroyContext&) override;
    157 
    158  ScrollContainerFrame* GetScrollTargetFrame() const final {
    159    return const_cast<ScrollContainerFrame*>(this);
    160  }
    161 
    162  nsContainerFrame* GetContentInsertionFrame() override {
    163    return GetScrolledFrame()->GetContentInsertionFrame();
    164  }
    165 
    166  nsPoint GetPositionOfChildIgnoringScrolling(const nsIFrame* aChild) final {
    167    nsPoint pt = aChild->GetPosition();
    168    if (aChild == GetScrolledFrame()) {
    169      pt += GetScrollPosition();
    170    }
    171    return pt;
    172  }
    173 
    174  // nsIAnonymousContentCreator
    175  nsresult CreateAnonymousContent(nsTArray<ContentInfo>&) final;
    176  void AppendAnonymousContentTo(nsTArray<nsIContent*>&, uint32_t aFilter) final;
    177 
    178  /**
    179   * Get the frame for the content that we are scrolling within
    180   * this scrollable frame.
    181   */
    182  nsIFrame* GetScrolledFrame() const { return mScrolledFrame; }
    183 
    184  /**
    185   * Get the overflow styles (StyleOverflow::Scroll, StyleOverflow::Hidden, or
    186   * StyleOverflow::Auto) governing the horizontal and vertical scrollbars for
    187   * this frame.
    188   *
    189   * This is special because they can be propagated from the <body> element,
    190   * unlike other styles.
    191   */
    192  ScrollStyles GetScrollStyles() const;
    193 
    194  /**
    195   * Returns whether we already have anonymous content nodes for all our needed
    196   * scrollbar parts (or a superset thereof).
    197   */
    198  bool HasAllNeededScrollbars() const {
    199    return GetCurrentAnonymousContent().contains(GetNeededAnonymousContent());
    200  }
    201 
    202  struct PerAxisScrollDirections {
    203    bool mToRight = false;
    204    bool mToBottom = false;
    205  };
    206 
    207  static PerAxisScrollDirections ComputePerAxisScrollDirections(
    208      const nsIFrame* aScrolledFrame);
    209 
    210  /**
    211   * Get the overscroll-behavior styles.
    212   */
    213  layers::OverscrollBehaviorInfo GetOverscrollBehaviorInfo() const;
    214 
    215  /**
    216   * Return the scrollbars which are visible. It's OK to call this during reflow
    217   * of the scrolled contents, in which case it will reflect the current
    218   * assumptions about scrollbar visibility.
    219   */
    220  layers::ScrollDirections GetScrollbarVisibility() const {
    221    layers::ScrollDirections result;
    222    if (mHasHorizontalScrollbar) {
    223      result += layers::ScrollDirection::eHorizontal;
    224    }
    225    if (mHasVerticalScrollbar) {
    226      result += layers::ScrollDirection::eVertical;
    227    }
    228    return result;
    229  }
    230 
    231  /**
    232   * Returns the directions in which scrolling is allowed (if the scroll range
    233   * is at least one device pixel in that direction).
    234   */
    235  layers::ScrollDirections GetAvailableScrollingDirections() const;
    236 
    237  /**
    238   * Returns the directions in which scrolling is allowed when taking into
    239   * account the visual viewport size and overflow hidden. (An (apz) zoomed in
    240   * overflow hidden scrollframe is actually user scrollable.)
    241   */
    242  layers::ScrollDirections GetAvailableScrollingDirectionsForUserInputEvents()
    243      const;
    244 
    245  /**
    246   * Return the actual sizes of all possible scrollbars. Returns 0 for scrollbar
    247   * positions that don't have a scrollbar or where the scrollbar is not
    248   * visible. Do not call this while this frame's descendants are being
    249   * reflowed, it won't be accurate.
    250   * INCLUDE_VISUAL_VIEWPORT_SCROLLBARS means we include the size of layout
    251   * scrollbars that are only visible to scroll the visual viewport inside the
    252   * layout viewport (ie the layout viewport cannot be scrolled) even though
    253   * there is no layout space set aside for these scrollbars.
    254   */
    255  enum class ScrollbarSizesOptions { NONE, INCLUDE_VISUAL_VIEWPORT_SCROLLBARS };
    256  nsMargin GetActualScrollbarSizes(
    257      ScrollbarSizesOptions aOptions = ScrollbarSizesOptions::NONE) const;
    258 
    259  /**
    260   * Return the sizes of all scrollbars assuming that any scrollbars that could
    261   * be visible due to overflowing content, are. This can be called during
    262   * reflow of the scrolled contents.
    263   */
    264  nsMargin GetDesiredScrollbarSizes() const;
    265 
    266  /**
    267   * Get the layout size of this frame.
    268   * Note that this is a value which is not expanded by the minimum scale size.
    269   * For scroll frames other than the root content document's scroll frame, this
    270   * value will be the same as GetScrollPortRect().Size().
    271   *
    272   * This value is used for Element.clientWidth and clientHeight.
    273   */
    274  nsSize GetLayoutSize() const {
    275    if (mIsUsingMinimumScaleSize) {
    276      return mICBSize;
    277    }
    278    return mScrollPort.Size();
    279  }
    280 
    281  /**
    282   * Get the size used for window.innerWidth or innerHeight.
    283   * This works only for the root scroll container.
    284   */
    285  nsSize GetSizeForWindowInnerSize() const;
    286 
    287  /**
    288   * GetScrolledRect is designed to encapsulate deciding which
    289   * directions of overflow should be reachable by scrolling and which
    290   * should not.  Callers should NOT depend on it having any particular
    291   * behavior.
    292   *
    293   * This should only be called when the scrolled frame has been
    294   * reflowed with the scroll port size given in mScrollPort.
    295   *
    296   * Currently it allows scrolling down and to the right for
    297   * ScrollContainerFrames with LTR directionality, and allows scrolling down
    298   * and to the left for ScrollContainerFrames with RTL directionality.
    299   */
    300  nsRect GetScrolledRect() const;
    301 
    302  /**
    303   * Get the area of the scrollport relative to the origin of this frame's
    304   * border-box.
    305   * This is the area of this frame minus border and scrollbars.
    306   */
    307  nsRect GetScrollPortRect() const { return mScrollPort; }
    308  nsRect GetScrollPortRectAccountingForDynamicToolbar() const {
    309    auto rect = mScrollPort;
    310    if (mIsRoot) {
    311      rect.height += PresContext()->GetBimodalDynamicToolbarHeightInAppUnits();
    312    }
    313    return rect;
    314  }
    315  nsRect GetScrollPortRectAccountingForMaxDynamicToolbar() const;
    316 
    317  nsSize GetScrolledFrameSizeAccountingForDynamicToolbar() const {
    318    auto size = mScrolledFrame->GetContentRectRelativeToSelf().Size();
    319    if (mIsRoot) {
    320      size.height += PresContext()->GetBimodalDynamicToolbarHeightInAppUnits();
    321    }
    322    return size;
    323  }
    324 
    325  /**
    326   * Get the offset of the scrollport origin relative to the scrolled
    327   * frame origin. Typically the position will be non-negative.
    328   * This will always be a multiple of device pixels.
    329   */
    330  nsPoint GetScrollPosition() const {
    331    return mScrollPort.TopLeft() - mScrolledFrame->GetPosition();
    332  }
    333 
    334  /**
    335   * For LTR frames, the logical scroll position is the offset of the top left
    336   * corner of the frame from the top left corner of the scroll port (same as
    337   * GetScrollPosition).
    338   * For RTL frames, it is the offset of the top right corner of the frame from
    339   * the top right corner of the scroll port.
    340   */
    341  nsPoint GetLogicalScrollPosition() const {
    342    nsPoint pt;
    343    pt.x = IsPhysicalLTR()
    344               ? mScrollPort.x - mScrolledFrame->GetPosition().x
    345               : mScrollPort.XMost() - mScrolledFrame->GetRect().XMost();
    346    pt.y = mScrollPort.y - mScrolledFrame->GetPosition().y;
    347    return pt;
    348  }
    349 
    350  /**
    351   * Get the area that must contain the scroll position. Typically
    352   * (but not always, e.g. for RTL content) x and y will be 0, and
    353   * width or height will be nonzero if the content can be scrolled in
    354   * that direction. Since scroll positions must be a multiple of
    355   * device pixels, the range extrema will also be a multiple of
    356   * device pixels.
    357   */
    358  nsRect GetScrollRange() const { return GetLayoutScrollRange(); }
    359 
    360  /**
    361   * Get the size of the view port to use when clamping the scroll
    362   * position.
    363   */
    364  nsSize GetVisualViewportSize() const;
    365 
    366  /**
    367   * Returns the offset of the visual viewport relative to
    368   * the origin of the scrolled content. Note that only the RCD-RSF
    369   * has a distinct visual viewport; for other scroll frames, the
    370   * visual viewport always coincides with the layout viewport, and
    371   * consequently the offset this function returns is equal to
    372   * GetScrollPosition().
    373   */
    374  nsPoint GetVisualViewportOffset() const;
    375 
    376  /**
    377   * Set the visual viewport offset associated with a root scroll frame. This is
    378   * only valid when called on a root scroll frame and will assert otherwise.
    379   * aRepaint indicates if we need to ask for a main thread paint if this
    380   * changes scrollbar positions or not. For example, if the compositor has
    381   * already put the scrollbars at this position then they don't need to move so
    382   * we can skip the repaint. Returns true if the offset changed and the scroll
    383   * frame is still alive after this call.
    384   */
    385  bool SetVisualViewportOffset(const nsPoint& aOffset, bool aRepaint);
    386  /**
    387   * Get the area that must contain the visual viewport offset.
    388   */
    389  nsRect GetVisualScrollRange() const;
    390 
    391  /**
    392   * Like GetVisualScrollRange but also takes into account overflow: hidden.
    393   */
    394  nsRect GetScrollRangeForUserInputEvents() const;
    395 
    396  /**
    397   * Return how much we would try to scroll by in each direction if
    398   * asked to scroll by one "line" vertically and horizontally.
    399   */
    400  nsSize GetLineScrollAmount() const;
    401  /**
    402   * Return how much we would try to scroll by in each direction if
    403   * asked to scroll by one "page" vertically and horizontally.
    404   */
    405  nsSize GetPageScrollAmount() const;
    406 
    407  /**
    408   * Return scroll-padding value of this frame.
    409   */
    410  nsMargin GetScrollPadding() const;
    411 
    412  /**
    413   * @note This method might destroy the frame, pres shell and other objects.
    414   * Clamps aScrollPosition to GetScrollRange and sets the scroll position
    415   * to that value.
    416   * @param aRange If non-null, specifies area which contains aScrollPosition
    417   * and can be used for choosing a performance-optimized scroll position.
    418   * Any point within this area can be chosen.
    419   * The choosen point will be as close as possible to aScrollPosition.
    420   */
    421  void ScrollTo(nsPoint aScrollPosition, ScrollMode aMode,
    422                const nsRect* aRange = nullptr,
    423                ScrollSnapFlags aSnapFlags = ScrollSnapFlags::Disabled,
    424                ScrollTriggeredByScript aTriggeredByScript =
    425                    ScrollTriggeredByScript::No) {
    426    return ScrollToInternal(aScrollPosition, aMode, ScrollOrigin::Other, aRange,
    427                            aSnapFlags, aTriggeredByScript);
    428  }
    429 
    430  /**
    431   * @note This method might destroy the frame, pres shell and other objects.
    432   * Scrolls to a particular position in integer CSS pixels.
    433   * Keeps the exact current horizontal or vertical position if the current
    434   * position, rounded to CSS pixels, matches aScrollPosition. If
    435   * aScrollPosition.x/y is different from the current CSS pixel position,
    436   * makes sure we only move in the direction given by the difference.
    437   *
    438   * When aMode is SMOOTH, INSTANT, or NORMAL, GetRoundedScrollPositionCSSPixels
    439   * (the scroll position after rounding to CSS pixels) will be exactly
    440   * aScrollPosition at the end of the scroll animation.
    441   *
    442   * When aMode is SMOOTH_MSD, intermediate animation frames may be outside the
    443   * range and / or moving in any direction; GetRoundedScrollPositionCSSPixels
    444   * will be exactly aScrollPosition at the end of the scroll animation unless
    445   * the SMOOTH_MSD animation is interrupted.
    446   */
    447  void ScrollToCSSPixels(const CSSPoint& aScrollPosition,
    448                         ScrollMode aMode = ScrollMode::Instant);
    449 
    450  /**
    451   * @note This method might destroy the frame, pres shell and other objects.
    452   * Scrolls to a particular position in float CSS pixels.
    453   * This does not guarantee that GetRoundedScrollPositionCSSPixels equals
    454   * aScrollPosition afterward. It tries to scroll as close to
    455   * aScrollPosition as possible while scrolling by an integer
    456   * number of layer pixels (so the operation is fast and looks clean).
    457   */
    458  void ScrollToCSSPixelsForApz(const CSSPoint& aScrollPosition,
    459                               ScrollSnapTargetIds&& aLastSnapTargetIds);
    460 
    461  /**
    462   * Returns the scroll position in integer CSS pixels, rounded to the nearest
    463   * pixel.
    464   */
    465  CSSIntPoint GetRoundedScrollPositionCSSPixels();
    466 
    467  /**
    468   * Returns the scroll position in CSS pixels.
    469   */
    470  CSSPoint GetScrollPositionCSSPixels() const {
    471    return CSSPoint::FromAppUnits(GetScrollPosition());
    472  }
    473 
    474  /**
    475   * Some platforms (OSX) may generate additional scrolling events even
    476   * after the user has stopped scrolling, simulating a momentum scrolling
    477   * effect resulting from fling gestures.
    478   * SYNTHESIZED_MOMENTUM_EVENT indicates that the scrolling is being requested
    479   * by such a synthesized event and may be ignored if another scroll has
    480   * been started since the last actual user input.
    481   */
    482  enum ScrollMomentum { NOT_MOMENTUM, SYNTHESIZED_MOMENTUM_EVENT };
    483 
    484  /**
    485   * @note This method might destroy the frame, pres shell and other objects.
    486   * Modifies the current scroll position by aDelta units given by aUnit,
    487   * clamping it to GetScrollRange. If WHOLE is specified as the unit,
    488   * content is scrolled all the way in the direction(s) given by aDelta.
    489   * @param aOverflow if non-null, returns the amount that scrolling
    490   * was clamped by in each direction (how far we moved the scroll position
    491   * to bring it back into the legal range). This is never negative. The
    492   * values are in device pixels.
    493   */
    494  void ScrollBy(nsIntPoint aDelta, ScrollUnit aUnit, ScrollMode aMode,
    495                nsIntPoint* aOverflow = nullptr,
    496                ScrollOrigin aOrigin = ScrollOrigin::NotSpecified,
    497                ScrollMomentum aMomentum = NOT_MOMENTUM,
    498                ScrollSnapFlags aSnapFlags = ScrollSnapFlags::Disabled);
    499 
    500  void ScrollByCSSPixels(const CSSPoint& aDelta,
    501                         ScrollMode aMode = ScrollMode::Instant) {
    502    return ScrollByCSSPixelsInternal(aDelta, aMode);
    503  }
    504 
    505  /**
    506   * Perform scroll snapping, possibly resulting in a smooth scroll to
    507   * maintain the scroll snap position constraints.  Velocity sampled from
    508   * main thread scrolling is used to determine best matching snap point
    509   * when called after a fling gesture on a trackpad or mouse wheel.
    510   */
    511  void ScrollSnap() { return ScrollSnap(ScrollMode::SmoothMsd); }
    512 
    513  /**
    514   * @note This method might destroy the frame, pres shell and other objects.
    515   * This tells the scroll frame to try scrolling to the scroll
    516   * position that was restored from the history. This must be called
    517   * at least once after state has been restored. It is called by the
    518   * scrolled frame itself during reflow, but sometimes state can be
    519   * restored after reflows are done...
    520   * XXX should we take an aMode parameter here? Currently it's instant.
    521   */
    522  void ScrollToRestoredPosition();
    523 
    524  bool NeedRestorePosition() const {
    525    return mRestorePos.y != -1 && mLastPos.x != -1 && mLastPos.y != -1;
    526  }
    527 
    528  /**
    529   * @note This method might destroy the frame, pres shell and other objects.
    530   * Internal method used by scrollbars to notify their scrolling
    531   * container of changes.
    532   */
    533  void ScrollbarCurPosChanged(bool aDoScroll = true);
    534 
    535  /**
    536   * Allows the docshell to request that the scroll frame post an event
    537   * after being restored from history.
    538   */
    539  NS_IMETHOD PostScrolledAreaEventForCurrentArea() final {
    540    PostScrolledAreaEvent();
    541    return NS_OK;
    542  }
    543 
    544  /**
    545   * Returns true if this scrollframe is being "actively scrolled".
    546   * This basically means that we should allocate resources in the
    547   * expectation that scrolling is going to happen.
    548   */
    549  bool IsScrollingActive() const;
    550 
    551  /**
    552   * Returns true if this scroll frame might be scrolled
    553   * asynchronously by the compositor.
    554   */
    555  bool IsMaybeAsynchronouslyScrolled() const {
    556    // If this is true, then we'll build an ASR, and that's what we want
    557    // to know I think.
    558    return mWillBuildScrollableLayer;
    559  }
    560 
    561  /**
    562   * Was the current presentation state for this frame restored from history?
    563   */
    564  bool DidHistoryRestore() const { return mDidHistoryRestore; }
    565 
    566  /**
    567   * Clear the flag so that DidHistoryRestore() returns false until the next
    568   * RestoreState call.
    569   * @see nsIStatefulFrame::RestoreState
    570   */
    571  void ClearDidHistoryRestore() { mDidHistoryRestore = false; }
    572 
    573  /**
    574   * Mark the frame as having been scrolled at least once, so that it remains
    575   * active and we can also start storing its scroll position when saving state.
    576   */
    577  void MarkEverScrolled();
    578 
    579  /**
    580   * Determine if the passed in rect is nearly visible according to the frame
    581   * visibility heuristics for how close it is to the visible scrollport.
    582   */
    583  bool IsRectNearlyVisible(const nsRect& aRect) const;
    584 
    585  /**
    586   * Expand the given rect taking into account which directions we can scroll
    587   * and how far we want to expand for frame visibility purposes.
    588   */
    589  nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const;
    590 
    591  /**
    592   * Returns the origin that triggered the last instant scroll. Will equal
    593   * ScrollOrigin::Apz when the compositor's replica frame metrics includes the
    594   * latest instant scroll.
    595   */
    596  ScrollOrigin LastScrollOrigin() const { return mLastScrollOrigin; }
    597 
    598  /**
    599   * Gets the async scroll animation state of this scroll frame.
    600   *
    601   * There are five possible kinds that can overlap.
    602   * MainThread means async scroll animated by the main thread.
    603   * APZ scroll animations that are requested from the main thread go through
    604   * three states: 1) pending, when the main thread has recorded that it wants
    605   * apz to do a scroll animation, 2) requested, when the main thread has sent
    606   * the request to the compositor (but it hasn't necessarily arrived yet), and
    607   * 3) in progress, after apz has responded to the main thread that it got the
    608   * request.
    609   * TriggeredByScript means that the async scroll animation was triggered by
    610   * script, e.g. Element.scrollTo().
    611   */
    612  enum class AnimationState {
    613    MainThread,        // mAsyncScroll || mAsyncSmoothMSDScroll
    614    APZPending,        // mScrollUpdates.LastElement() is Smooth or SmoothMsd
    615    APZRequested,      // mApzAnimationRequested
    616    APZInProgress,     // mCurrentAPZScrollAnimationType !=
    617                       // APZScrollAniationType::No
    618    TriggeredByScript  // The animation was triggered with
    619                       // ScrollTriggeredByScript::Yes
    620  };
    621  EnumSet<AnimationState> ScrollAnimationState() const;
    622 
    623  /**
    624   * Returns the current generation counter for the scrollframe. This counter
    625   * increments every time the scroll position is set.
    626   */
    627  MainThreadScrollGeneration CurrentScrollGeneration() const {
    628    return mScrollGeneration;
    629  }
    630 
    631  /**
    632   * The APZ scroll generation associated with the last APZ scroll offset for
    633   * which we processed a repaint request.
    634   */
    635  APZScrollGeneration ScrollGenerationOnApz() const {
    636    return mScrollGenerationOnApz;
    637  }
    638 
    639  /**
    640   * LastScrollDestination returns the destination of the most recently
    641   * requested smooth scroll animation.
    642   */
    643  nsPoint LastScrollDestination() { return mDestination; }
    644 
    645  /**
    646   * Returns the list of scroll position updates since the last call to
    647   * NotifyApzTransaction().
    648   */
    649  nsTArray<ScrollPositionUpdate> GetScrollUpdates() const;
    650 
    651  /**
    652   * Returns true if the scroll frame has any scroll position updates since
    653   * the last call to NotifyApzTransaction().
    654   */
    655  bool HasScrollUpdates() const { return !mScrollUpdates.IsEmpty(); }
    656 
    657  /**
    658   * Clears the "origin of last scroll" property stored in this frame, if
    659   * the generation counter passed in matches the current scroll generation
    660   * counter, and clears the "origin of last smooth scroll" property if the
    661   * generation counter matches. It also resets whether there's an ongoing apz
    662   * animation.
    663   */
    664  enum class InScrollingGesture : bool { No, Yes };
    665  void ResetScrollInfoIfNeeded(const MainThreadScrollGeneration& aGeneration,
    666                               const APZScrollGeneration& aGenerationOnApz,
    667                               APZScrollAnimationType aAPZScrollAnimationType,
    668                               InScrollingGesture aInScrollingGesture);
    669 
    670  /**
    671   * Determine whether it is desirable to be able to asynchronously scroll this
    672   * scroll frame.
    673   */
    674  bool WantAsyncScroll() const;
    675 
    676  /**
    677   * Returns the ScrollMetadata contributed by this frame, if there is one.
    678   */
    679  Maybe<layers::ScrollMetadata> ComputeScrollMetadata(
    680      layers::WebRenderLayerManager* aLayerManager, const nsIFrame* aItemFrame,
    681      const nsPoint& aOffsetToReferenceFrame) const;
    682 
    683  /**
    684   * Mark the scrollbar frames for reflow.
    685   */
    686  void MarkScrollbarsDirtyForReflow() const;
    687 
    688  /**
    689   * Invalidate the scrollbar after the marks have been changed.
    690   */
    691  void InvalidateScrollbars() const;
    692 
    693  /**
    694   * @note This method might destroy the frame, pres shell and other objects.
    695   * Update scrollbar to reflect current scroll position
    696   */
    697  void UpdateScrollbarPosition();
    698 
    699  void SetTransformingByAPZ(bool aTransforming);
    700  bool IsTransformingByAPZ() const { return mTransformingByAPZ; }
    701 
    702  /**
    703   * Notify this scroll frame that it can be scrolled by APZ. In particular,
    704   * this is called *after* the APZ code has created an APZC for this scroll
    705   * frame and verified that it is not a scrollinfo layer. Therefore, setting an
    706   * async transform on it is actually user visible.
    707   */
    708  void SetScrollableByAPZ(bool aScrollable);
    709 
    710  /**
    711   * Notify this scroll frame that it can be zoomed by APZ.
    712   */
    713  void SetZoomableByAPZ(bool aZoomable);
    714 
    715  /**
    716   * Mark this scroll frame as having out-of-flow content inside a CSS filter.
    717   * Such content will move incorrectly during async-scrolling; to mitigate
    718   * this, paint skipping is disabled for such scroll frames.
    719   */
    720  void SetHasOutOfFlowContentInsideFilter();
    721 
    722  /**
    723   * Determine if we should build a scrollable layer for this scroll frame and
    724   * return the result. It will also record this result on the scroll frame.
    725   * Pass the visible rect in aVisibleRect. On return it will be set to the
    726   * displayport if there is one.
    727   * Pass the dirty rect in aDirtyRect. On return it will be set to the
    728   * dirty rect inside the displayport (ie the dirty rect that should be used).
    729   * This function will set the display port base rect if aSetBase is true.
    730   * aSetBase is only allowed to be false if there has been a call with it
    731   * set to true before on the same paint.
    732   */
    733  bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
    734                             nsRect* aVisibleRect, nsRect* aDirtyRect,
    735                             bool aSetBase) {
    736    return DecideScrollableLayer(aBuilder, aVisibleRect, aDirtyRect, aSetBase,
    737                                 nullptr);
    738  }
    739 
    740  /**
    741   * Like DecideScrollableLayer but skips computing dirty/visible rects and
    742   * setting the base rect. In addition, this always ensures a display port is
    743   * set if this scroll frame could async scroll. DecideScrollableLayer only
    744   * sets a display port in that situation if ShouldActivateAllScrollFrames
    745   * returns true. However you should only call this function is
    746   * ShouldActivateAllScrollFrames returns true anyways.
    747   * */
    748  bool DecideScrollableLayerEnsureDisplayport(nsDisplayListBuilder* aBuilder);
    749 
    750  /**
    751   * Notify the scrollframe that the current scroll offset and origin have been
    752   * sent over in a layers transaction.
    753   *
    754   * This sets a flag on the scrollframe that indicates subsequent changes
    755   * to the scroll position by "weaker" origins are permitted to overwrite the
    756   * the scroll origin. Scroll origins that
    757   * nsLayoutUtils::CanScrollOriginClobberApz returns false for are considered
    758   * "weaker" than scroll origins for which that function returns true.
    759   *
    760   * This function must be called for a scrollframe after all calls to
    761   * ComputeScrollMetadata in a layers transaction have been completed.
    762   *
    763   */
    764  void NotifyApzTransaction();
    765 
    766  /**
    767   * Notification that this scroll frame is getting its frame visibility
    768   * updated. aIgnoreDisplayPort indicates that the display port was ignored
    769   * (because there was no suitable base rect)
    770   */
    771  void NotifyApproximateFrameVisibilityUpdate(bool aIgnoreDisplayPort);
    772 
    773  /**
    774   * Returns true if this scroll frame had a display port at the last frame
    775   * visibility update and fills in aDisplayPort with that displayport. Returns
    776   * false otherwise, and doesn't touch aDisplayPort.
    777   */
    778  bool GetDisplayPortAtLastApproximateFrameVisibilityUpdate(
    779      nsRect* aDisplayPort);
    780 
    781  /**
    782   * This is called when a descendant scrollframe's has its displayport expired.
    783   * This function will check to see if this scrollframe may safely expire its
    784   * own displayport and schedule a timer to do that if it is safe.
    785   */
    786  void TriggerDisplayPortExpiration();
    787 
    788  /**
    789   * Returns information required to determine where to snap to after a scroll.
    790   */
    791  ScrollSnapInfo GetScrollSnapInfo();
    792 
    793  void TryResnap();
    794 
    795  /**
    796   * Post a pending re-snap request if the given |aFrame| is one of the snap
    797   * points on the last scroll operation.
    798   */
    799  void PostPendingResnapIfNeeded(const nsIFrame* aFrame);
    800  void PostPendingResnap();
    801 
    802  /**
    803   * Returns a pair of the scroll-snap-align property value both on X and Y axes
    804   * for the given |aFrame| considering the scroll-snap-type of this scroll
    805   * container. For example, if the scroll-snap-type is `none`, the pair of
    806   * scroll-snap-align is also `none none`.
    807   */
    808  using PhysicalScrollSnapAlign =
    809      std::pair<StyleScrollSnapAlignKeyword, StyleScrollSnapAlignKeyword>;
    810  PhysicalScrollSnapAlign GetScrollSnapAlignFor(const nsIFrame* aFrame) const;
    811 
    812  /**
    813   * Given the drag event aEvent, determine whether the mouse is near the edge
    814   * of the scrollable area, and scroll the view in the direction of that edge
    815   * if so. If scrolling occurred, true is returned. When false is returned, the
    816   * caller should look for an ancestor to scroll.
    817   */
    818  bool DragScroll(WidgetEvent* aEvent);
    819 
    820  void AsyncScrollbarDragInitiated(uint64_t aDragBlockId,
    821                                   layers::ScrollDirection aDirection);
    822  void AsyncScrollbarDragRejected();
    823 
    824  /**
    825   * Returns whether this scroll frame is the root scroll frame of the document
    826   * that it is in. Note that some documents don't have root scroll frames at
    827   * all (ie XUL documents) even though they may contain other scroll frames.
    828   */
    829  bool IsRootScrollFrameOfDocument() const { return mIsRoot; }
    830 
    831  /**
    832   * Returns the paint sequence number if this scroll frame was the first
    833   * scrollable frame for the paint.
    834   */
    835  Maybe<uint32_t> IsFirstScrollableFrameSequenceNumber() const {
    836    return mIsFirstScrollableFrameSequenceNumber;
    837  }
    838 
    839  /**
    840   * Set the paint sequence number for the paint in which this was the first
    841   * scrollable frame that was encountered.
    842   */
    843  void SetIsFirstScrollableFrameSequenceNumber(Maybe<uint32_t> aValue) {
    844    mIsFirstScrollableFrameSequenceNumber = aValue;
    845  }
    846 
    847  /**
    848   * Returns the scroll anchor associated with this scrollable frame. This is
    849   * never null.
    850   */
    851  const ScrollAnchorContainer* Anchor() const { return &mAnchor; }
    852  ScrollAnchorContainer* Anchor() { return &mAnchor; }
    853 
    854  bool SmoothScrollVisual(
    855      const nsPoint& aVisualViewportOffset,
    856      layers::FrameMetrics::ScrollOffsetUpdateType aUpdateType,
    857      ScrollMode aMode);
    858 
    859  /**
    860   * Returns true if this scroll frame should perform smooth scroll with the
    861   * given |aBehavior|.
    862   */
    863  bool IsSmoothScroll(
    864      dom::ScrollBehavior aBehavior = dom::ScrollBehavior::Auto) const;
    865 
    866  /**
    867   * Returns the ScrollMode that this scroll frame should use for a
    868   * programmatic scroll governed by CSSOM-View `scroll-behavior`.
    869   * This includes most programmatic scrolls but not scroll snapping.
    870   */
    871  ScrollMode ScrollModeForScrollBehavior(
    872      dom::ScrollBehavior aBehavior = dom::ScrollBehavior::Auto) const;
    873 
    874  static nscoord GetNonOverlayScrollbarSize(const nsPresContext*,
    875                                            StyleScrollbarWidth);
    876 
    877  void ScrollByCSSPixelsInternal(
    878      const CSSPoint& aDelta, ScrollMode aMode = ScrollMode::Instant,
    879      // This ScrollByCSSPixels is mainly used for Element.scrollBy and
    880      // Window.scrollBy. An exception is the transmogrification of
    881      // ScrollToCSSPixels.
    882      ScrollSnapFlags aSnapFlags = ScrollSnapFlags::IntendedDirection |
    883                                   ScrollSnapFlags::IntendedEndPosition);
    884 
    885  // nsIReflowCallback
    886  bool ReflowFinished() override;
    887  void ReflowCallbackCanceled() final;
    888 
    889  // nsIStatefulFrame
    890  UniquePtr<PresState> SaveState() final;
    891  NS_IMETHOD RestoreState(PresState* aState) final;
    892 
    893  // nsIScrollbarMediator
    894  void ScrollByPage(
    895      nsScrollbarFrame* aScrollbar, int32_t aDirection,
    896      ScrollSnapFlags aSnapFlags = ScrollSnapFlags::Disabled) final;
    897  void ScrollByWhole(
    898      nsScrollbarFrame* aScrollbar, int32_t aDirection,
    899      ScrollSnapFlags aSnapFlags = ScrollSnapFlags::Disabled) final;
    900  void ScrollByLine(nsScrollbarFrame* aScrollbar, int32_t aDirection,
    901                    ScrollSnapFlags = ScrollSnapFlags::Disabled) final;
    902  void ScrollByUnit(nsScrollbarFrame* aScrollbar, ScrollMode aMode,
    903                    int32_t aDirection, ScrollUnit aUnit,
    904                    ScrollSnapFlags = ScrollSnapFlags::Disabled) final;
    905  void RepeatButtonScroll(nsScrollbarFrame* aScrollbar) final;
    906  void ThumbMoved(nsScrollbarFrame* aScrollbar, nscoord aOldPos,
    907                  nscoord aNewPos) final;
    908  void ScrollbarReleased(nsScrollbarFrame* aScrollbar) final;
    909  void VisibilityChanged(bool aVisible) final {}
    910  nsScrollbarFrame* GetScrollbarBox(bool aVertical) final {
    911    return aVertical ? mVScrollbarBox : mHScrollbarBox;
    912  }
    913  void ScrollbarActivityStarted() const final;
    914  void ScrollbarActivityStopped() const final;
    915  bool IsScrollbarOnRight() const final;
    916  bool ShouldSuppressScrollbarRepaints() const final {
    917    return mSuppressScrollbarRepaints;
    918  }
    919 
    920  // Return the scrolled frame.
    921  void AppendDirectlyOwnedAnonBoxes(nsTArray<OwnedAnonBox>& aResult) final {
    922    aResult.AppendElement(OwnedAnonBox(GetScrolledFrame()));
    923  }
    924 
    925 #ifdef DEBUG_FRAME_DUMP
    926  nsresult GetFrameName(nsAString& aResult) const override;
    927 #endif
    928 
    929 #ifdef ACCESSIBILITY
    930  a11y::AccType AccessibleType() override;
    931 #endif
    932 
    933  static void AsyncScrollCallback(ScrollContainerFrame* aInstance,
    934                                  TimeStamp aTime);
    935  static void AsyncSmoothMSDScrollCallback(ScrollContainerFrame* aInstance,
    936                                           TimeDuration aDeltaTime);
    937  /**
    938   * @note This method might destroy the frame, pres shell and other objects.
    939   * aRange is the range of allowable scroll positions around the desired
    940   * aScrollPosition. Null means only aScrollPosition is allowed.
    941   * This is a closed-ended range --- aRange.XMost()/aRange.YMost() are allowed.
    942   */
    943  void ScrollToInternal(
    944      nsPoint aScrollPosition, ScrollMode aMode,
    945      ScrollOrigin aOrigin = ScrollOrigin::NotSpecified,
    946      const nsRect* aRange = nullptr,
    947      ScrollSnapFlags aSnapFlags = ScrollSnapFlags::Disabled,
    948      ScrollTriggeredByScript aTriggeredByScript = ScrollTriggeredByScript::No);
    949  /**
    950   * @note This method might destroy the frame, pres shell and other objects.
    951   */
    952  void ScrollToImpl(
    953      nsPoint aPt, const nsRect& aRange,
    954      ScrollOrigin aOrigin = ScrollOrigin::NotSpecified,
    955      ScrollTriggeredByScript aTriggeredByScript = ScrollTriggeredByScript::No);
    956  void ScrollVisual();
    957 
    958  enum class LoadingState { Loading, Stopped, Loaded };
    959 
    960  LoadingState GetPageLoadingState();
    961 
    962  /**
    963   * GetSnapPointForDestination determines which point to snap to after
    964   * scrolling. aStartPos gives the position before scrolling and aDestination
    965   * gives the position after scrolling, with no snapping. Behaviour is
    966   * dependent on the value of aUnit.
    967   * Returns true if a suitable snap point could be found and aDestination has
    968   * been updated to a valid snapping position.
    969   */
    970  Maybe<SnapDestination> GetSnapPointForDestination(
    971      ScrollUnit aUnit, ScrollSnapFlags aFlags, const nsPoint& aStartPos,
    972      const nsPoint& aDestination);
    973 
    974  Maybe<SnapDestination> GetSnapPointForResnap();
    975  bool NeedsResnap();
    976 
    977  void SetLastSnapTargetIds(UniquePtr<ScrollSnapTargetIds> aId);
    978 
    979  static void SetScrollbarVisibility(nsIFrame* aScrollbar, bool aVisible);
    980 
    981  /**
    982   * GetUnsnappedScrolledRectInternal is designed to encapsulate deciding which
    983   * directions of overflow should be reachable by scrolling and which
    984   * should not.  Callers should NOT depend on it having any particular
    985   * behavior.
    986   *
    987   * Currently it allows scrolling down and to the right for
    988   * ScrollContainerFrames with LTR directionality, and allows scrolling down
    989   * and to the left for ScrollContainerFrames with RTL directionality.
    990   */
    991  nsRect GetUnsnappedScrolledRectInternal(const nsRect& aScrolledOverflowArea,
    992                                          const nsSize& aScrollPortSize) const;
    993 
    994  bool IsPhysicalLTR() const { return GetWritingMode().IsPhysicalLTR(); }
    995  bool IsBidiLTR() const { return GetWritingMode().IsBidiLTR(); }
    996 
    997  bool IsAlwaysActive() const;
    998  void MarkRecentlyScrolled();
    999  void MarkNotRecentlyScrolled();
   1000  nsExpirationState* GetExpirationState() { return &mActivityExpirationState; }
   1001 
   1002  bool UsesOverlayScrollbars() const;
   1003  bool IsLastSnappedTarget(const nsIFrame* aFrame) const;
   1004 
   1005  // If aBuilder is non-null, returns the value cached on aBuilder. Pass null
   1006  // for aBuilder to get the correct value to cache on a new builder or new
   1007  // frame of painting, or if you need the correct value outside of paint time.
   1008  static bool ShouldActivateAllScrollFrames(nsDisplayListBuilder* aBuilder,
   1009                                            nsIFrame* aFrame);
   1010  nsRect RestrictToRootDisplayPort(const nsRect& aDisplayportBase);
   1011  bool DecideScrollableLayer(nsDisplayListBuilder* aBuilder,
   1012                             nsRect* aVisibleRect, nsRect* aDirtyRect,
   1013                             bool aSetBase, bool* aDirtyRectHasBeenOverriden);
   1014  bool AllowDisplayPortExpiration();
   1015  void ResetDisplayPortExpiryTimer();
   1016 
   1017  void ScheduleSyntheticMouseMove();
   1018  static void ScrollActivityCallback(nsITimer* aTimer, void* anInstance);
   1019 
   1020  void HandleScrollbarStyleSwitching();
   1021 
   1022  bool IsApzAnimationInProgress() const {
   1023    return mCurrentAPZScrollAnimationType != APZScrollAnimationType::No;
   1024  }
   1025  nsPoint LastScrollDestination() const { return mDestination; }
   1026 
   1027  bool IsLastScrollUpdateAnimating() const;
   1028  bool IsLastScrollUpdateTriggeredByScriptAnimating() const;
   1029 
   1030  // Update minimum-scale size.  The minimum-scale size will be set/used only
   1031  // if there is overflow-x:hidden region.
   1032  void UpdateMinimumScaleSize(const nsRect& aScrollableOverflow,
   1033                              const nsSize& aICBSize);
   1034 
   1035  // Return the scroll frame's "true outer size".
   1036  // This is GetSize(), except when we've been sized to reflect a virtual
   1037  // (layout) viewport in which case this returns the outer size used to size
   1038  // the physical (visual) viewport.
   1039  nsSize TrueOuterSize(nsDisplayListBuilder* aBuilder) const;
   1040 
   1041  already_AddRefed<Element> MakeScrollbar(dom::NodeInfo* aNodeInfo,
   1042                                          bool aVertical,
   1043                                          AnonymousContentKey& aKey);
   1044 
   1045  void AppendScrollUpdate(const ScrollPositionUpdate& aUpdate);
   1046 
   1047  bool HasBeenScrolled() const { return mHasBeenScrolled; }
   1048 
   1049 protected:
   1050  ScrollContainerFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
   1051                       bool aIsRoot)
   1052      : ScrollContainerFrame(aStyle, aPresContext, kClassID, aIsRoot) {}
   1053  ScrollContainerFrame(ComputedStyle* aStyle, nsPresContext* aPresContext,
   1054                       nsIFrame::ClassID aID, bool aIsRoot);
   1055  ~ScrollContainerFrame();
   1056  bool GuessHScrollbarNeeded(const ScrollReflowInput& aState);
   1057  bool GuessVScrollbarNeeded(const ScrollReflowInput& aState);
   1058 
   1059  // Return whether we're in an "initial" reflow.  Some reflows with
   1060  // NS_FRAME_FIRST_REFLOW set are NOT "initial" as far as we're concerned.
   1061  bool InInitialReflow() const;
   1062 
   1063  bool TryLayout(ScrollReflowInput& aState, ReflowOutput* aKidMetrics,
   1064                 bool aAssumeHScroll, bool aAssumeVScroll, bool aForce);
   1065 
   1066  // Return true if ReflowScrolledFrame is going to do something different based
   1067  // on the presence of a horizontal scrollbar in a horizontal writing mode or a
   1068  // vertical scrollbar in a vertical writing mode.
   1069  bool ScrolledContentDependsOnBSize(const ScrollReflowInput& aState) const;
   1070 
   1071  void ReflowScrolledFrame(ScrollReflowInput& aState, bool aAssumeHScroll,
   1072                           bool aAssumeVScroll, ReflowOutput* aMetrics);
   1073  void ReflowContents(ScrollReflowInput& aState,
   1074                      const ReflowOutput& aDesiredSize);
   1075  void PlaceScrollArea(ScrollReflowInput& aState,
   1076                       const nsPoint& aScrollPosition);
   1077 
   1078  void UpdateSticky();
   1079  void UpdatePrevScrolledRect();
   1080 
   1081  // adjust the scrollbar rectangle aRect to account for any visible resizer.
   1082  // aHasResizer specifies if there is a content resizer, however this method
   1083  // will also check if a widget resizer is present as well.
   1084  void AdjustScrollbarRectForResizer(nsIFrame* aFrame,
   1085                                     nsPresContext* aPresContext, nsRect& aRect,
   1086                                     bool aHasResizer,
   1087                                     layers::ScrollDirection aDirection);
   1088  void LayoutScrollbars(ScrollReflowInput& aState,
   1089                        const nsRect& aInsideBorderArea,
   1090                        const nsRect& aOldScrollPort);
   1091 
   1092  void LayoutScrollbarPartAtRect(const ScrollReflowInput&,
   1093                                 ReflowInput& aKidReflowInput, const nsRect&);
   1094 
   1095  /**
   1096   * Override this to return false if computed bsize/min-bsize/max-bsize
   1097   * should NOT be propagated to child content.
   1098   * nsListControlFrame uses this.
   1099   */
   1100  virtual bool ShouldPropagateComputedBSizeToScrolledContent() const {
   1101    return true;
   1102  }
   1103 
   1104  PhysicalAxes GetOverflowAxes() const;
   1105 
   1106  MOZ_CAN_RUN_SCRIPT nsresult FireScrollPortEvent();
   1107  void PostScrollEndEvent();
   1108  MOZ_CAN_RUN_SCRIPT void FireScrollEndEvent();
   1109  void PostOverflowEvent();
   1110 
   1111  // Add display items for the top-layer (which includes things like
   1112  // the fullscreen element, its backdrop, and text selection carets)
   1113  // to |aLists|.
   1114  // This is a no-op for scroll frames other than the viewport's
   1115  // root scroll frame.
   1116  // This should be called with an nsDisplayListSet that will be
   1117  // wrapped in the async zoom container, if we're building one.
   1118  // It should not be called with an ASR setter on the stack, as the
   1119  // top-layer items handle setting up their own ASRs.
   1120  void MaybeCreateTopLayerAndWrapRootItems(
   1121      nsDisplayListBuilder*, nsDisplayListCollection&, bool aCreateAsyncZoom,
   1122      bool aCapturedByViewTransition,
   1123      AutoContainsBlendModeCapturer* aAsyncZoomBlendCapture,
   1124      const nsRect& aAsyncZoomClipRect, const nsRectCornerRadii* aRadii);
   1125 
   1126  void AppendScrollPartsTo(nsDisplayListBuilder* aBuilder,
   1127                           const nsDisplayListSet& aLists, bool aCreateLayer,
   1128                           bool aPositioned);
   1129 
   1130  void PostScrollEvent();
   1131  MOZ_CAN_RUN_SCRIPT void FireScrollEvent();
   1132  void PostScrolledAreaEvent();
   1133  MOZ_CAN_RUN_SCRIPT void FireScrolledAreaEvent();
   1134 
   1135  void FinishReflowForScrollbar(nsScrollbarFrame*, nscoord aMinXY,
   1136                                nscoord aMaxXY, nscoord aCurPosXY,
   1137                                nscoord aPageIncrement);
   1138  void ActivityOccurred();
   1139 
   1140  nsRect GetLayoutScrollRange() const;
   1141  // Get the scroll range assuming the viewport has size (aWidth, aHeight).
   1142  nsRect GetScrollRange(nscoord aWidth, nscoord aHeight) const;
   1143 
   1144  const nsRect& ScrollPort() const { return mScrollPort; }
   1145  void SetScrollPort(const nsRect& aNewScrollPort) {
   1146    if (!mScrollPort.IsEqualEdges(aNewScrollPort)) {
   1147      mMayScheduleScrollAnimations = true;
   1148    }
   1149    mScrollPort = aNewScrollPort;
   1150  }
   1151 
   1152  /**
   1153   * Return the 'optimal viewing region' as a rect suitable for use by
   1154   * scroll anchoring. This rect is in the same coordinate space as
   1155   * 'GetScrollPortRect', and accounts for 'scroll-padding' as defined by:
   1156   *
   1157   * https://drafts.csswg.org/css-scroll-snap-1/#optimal-viewing-region
   1158   */
   1159  nsRect GetVisualOptimalViewingRect() const;
   1160 
   1161  /**
   1162   * For LTR frames, this is the same as GetVisualViewportOffset().
   1163   * For RTL frames, we take the offset from the top right corner of the frame
   1164   * to the top right corner of the visual viewport.
   1165   */
   1166  nsPoint GetLogicalVisualViewportOffset() const {
   1167    nsPoint pt = GetVisualViewportOffset();
   1168    if (!IsPhysicalLTR()) {
   1169      pt.x += GetVisualViewportSize().width - mScrolledFrame->GetRect().width;
   1170    }
   1171    return pt;
   1172  }
   1173  void ScrollSnap(ScrollMode aMode);
   1174  void ScrollSnap(const nsPoint& aDestination,
   1175                  ScrollMode aMode = ScrollMode::SmoothMsd);
   1176 
   1177  bool HasPendingScrollRestoration() const {
   1178    return mRestorePos != nsPoint(-1, -1);
   1179  }
   1180 
   1181  bool IsProcessingScrollEvent() const { return mProcessingScrollEvent; }
   1182 
   1183  class AutoScrollbarRepaintSuppression;
   1184  friend class AutoScrollbarRepaintSuppression;
   1185  class AutoScrollbarRepaintSuppression {
   1186   public:
   1187    AutoScrollbarRepaintSuppression(ScrollContainerFrame* aFrame,
   1188                                    AutoWeakFrame& aWeakOuter, bool aSuppress)
   1189        : mFrame(aFrame),
   1190          mWeakOuter(aWeakOuter),
   1191          mOldSuppressValue(aFrame->mSuppressScrollbarRepaints) {
   1192      mFrame->mSuppressScrollbarRepaints = aSuppress;
   1193    }
   1194 
   1195    ~AutoScrollbarRepaintSuppression() {
   1196      if (mWeakOuter.IsAlive()) {
   1197        mFrame->mSuppressScrollbarRepaints = mOldSuppressValue;
   1198      }
   1199    }
   1200 
   1201   private:
   1202    ScrollContainerFrame* mFrame;
   1203    AutoWeakFrame& mWeakOuter;
   1204    bool mOldSuppressValue;
   1205  };
   1206 
   1207  struct ScrollOperationParams {
   1208    ScrollOperationParams(const ScrollOperationParams&) = delete;
   1209    ScrollOperationParams(ScrollMode aMode, ScrollOrigin aOrigin)
   1210        : mMode(aMode), mOrigin(aOrigin) {}
   1211    ScrollOperationParams(ScrollMode aMode, ScrollOrigin aOrigin,
   1212                          ScrollSnapTargetIds&& aSnapTargetIds)
   1213        : ScrollOperationParams(aMode, aOrigin) {
   1214      mTargetIds = std::move(aSnapTargetIds);
   1215    }
   1216    ScrollOperationParams(ScrollMode aMode, ScrollOrigin aOrigin,
   1217                          ScrollSnapFlags aSnapFlags,
   1218                          ScrollTriggeredByScript aTriggeredByScript)
   1219        : ScrollOperationParams(aMode, aOrigin) {
   1220      mSnapFlags = aSnapFlags;
   1221      mTriggeredByScript = aTriggeredByScript;
   1222    }
   1223 
   1224    ScrollMode mMode;
   1225    ScrollOrigin mOrigin;
   1226    ScrollSnapFlags mSnapFlags = ScrollSnapFlags::Disabled;
   1227    ScrollTriggeredByScript mTriggeredByScript = ScrollTriggeredByScript::No;
   1228    ScrollSnapTargetIds mTargetIds;
   1229 
   1230    bool IsInstant() const { return mMode == ScrollMode::Instant; }
   1231    bool IsSmoothMsd() const { return mMode == ScrollMode::SmoothMsd; }
   1232    bool IsSmooth() const { return mMode == ScrollMode::Smooth; }
   1233    bool IsScrollSnapDisabled() const {
   1234      return mSnapFlags == ScrollSnapFlags::Disabled;
   1235    }
   1236  };
   1237 
   1238  /**
   1239   * @note This method might destroy the frame, pres shell and other objects.
   1240   *
   1241   * A caller can ask this ScrollToWithOrigin() function to perform snapping by
   1242   * passing in aParams.mSnapFlags != ScrollSnapFlags::Disabled. Alternatively,
   1243   * a caller may want to do its own snapping, in which case it should pass
   1244   * ScrollSnapFlags::Disabled and populate aParams.mTargetIds based on the
   1245   * result of the snapping.
   1246   */
   1247  void ScrollToWithOrigin(nsPoint aScrollPosition, const nsRect* aRange,
   1248                          ScrollOperationParams&& aParams);
   1249 
   1250  void CompleteAsyncScroll(const nsPoint& aStartPosition, const nsRect& aRange,
   1251                           UniquePtr<ScrollSnapTargetIds> aSnapTargetIds,
   1252                           ScrollOrigin aOrigin = ScrollOrigin::NotSpecified);
   1253 
   1254  bool HasPerspective() const { return ChildrenHavePerspective(); }
   1255  bool HasBgAttachmentLocal() const;
   1256  StyleDirection GetScrolledFrameDir() const;
   1257  static StyleDirection GetScrolledFrameDir(const nsIFrame*);
   1258 
   1259  // Ask APZ to smooth scroll to |aDestination|.
   1260  // This method does not clamp the destination; callers should clamp it to
   1261  // either the layout or the visual scroll range (APZ will happily smooth
   1262  // scroll to either).
   1263  void ApzSmoothScrollTo(const nsPoint& aDestination, ScrollMode, ScrollOrigin,
   1264                         ScrollTriggeredByScript,
   1265                         UniquePtr<ScrollSnapTargetIds> aSnapTargetIds,
   1266                         ViewportType aViewportToScroll);
   1267 
   1268  // Check whether APZ can scroll in the provided directions, keeping in mind
   1269  // that APZ currently cannot scroll along axes which are overflow:hidden.
   1270  bool CanApzScrollInTheseDirections(layers::ScrollDirections aDirections);
   1271 
   1272  // Removes any RefreshDriver observers we might have registered.
   1273  void RemoveObservers();
   1274 
   1275 private:
   1276  class AsyncScroll;
   1277  class AsyncSmoothMSDScroll;
   1278  class AutoMinimumScaleSizeChangeDetector;
   1279 
   1280  enum class AnonymousContentType {
   1281    VerticalScrollbar,
   1282    HorizontalScrollbar,
   1283    Resizer,
   1284  };
   1285  EnumSet<AnonymousContentType> GetNeededAnonymousContent() const;
   1286  EnumSet<AnonymousContentType> GetCurrentAnonymousContent() const;
   1287 
   1288  // If a child frame was added or removed on the scrollframe,
   1289  // reload our child frame list.
   1290  // We need this if a scrollbar frame is recreated.
   1291  void ReloadChildFrames();
   1292 
   1293  // NOTE: Use GetScrollStyles() if you want `overflow` property info.
   1294  nsIFrame* GetFrameForStyle() const;
   1295 
   1296  // Compute all scroll snap related information and store eash snap target
   1297  // element in |mSnapTargets|.
   1298  ScrollSnapInfo ComputeScrollSnapInfo();
   1299 
   1300  bool NeedsScrollSnap() const;
   1301 
   1302  // Returns the snapport size of this scroll container.
   1303  // https://drafts.csswg.org/css-scroll-snap/#scroll-snapport
   1304  nsSize GetSnapportSize() const;
   1305 
   1306  // Schedule the scroll-driven animations.
   1307  void ScheduleScrollAnimations();
   1308  void TryScheduleScrollAnimations() {
   1309    if (!mMayScheduleScrollAnimations) {
   1310      return;
   1311    }
   1312    ScheduleScrollAnimations();
   1313    mMayScheduleScrollAnimations = false;
   1314  }
   1315 
   1316  static void RemoveDisplayPortCallback(nsITimer* aTimer, void* aClosure);
   1317 
   1318  // owning references to the nsIAnonymousContentCreator-built content
   1319  nsCOMPtr<Element> mHScrollbarContent;
   1320  nsCOMPtr<Element> mVScrollbarContent;
   1321  nsCOMPtr<Element> mScrollCornerContent;
   1322  nsCOMPtr<Element> mResizerContent;
   1323 
   1324  class ScrollEvent;
   1325  class ScrollEndEvent;
   1326  class AsyncScrollPortEvent;
   1327  class ScrolledAreaEvent;
   1328 
   1329  RefPtr<ScrollEvent> mScrollEvent;
   1330  RefPtr<ScrollEndEvent> mScrollEndEvent;
   1331  nsRevocableEventPtr<AsyncScrollPortEvent> mAsyncScrollPortEvent;
   1332  nsRevocableEventPtr<ScrolledAreaEvent> mScrolledAreaEvent;
   1333  nsScrollbarFrame* mHScrollbarBox;
   1334  nsScrollbarFrame* mVScrollbarBox;
   1335  nsIFrame* mScrolledFrame;
   1336  nsIFrame* mScrollCornerBox;
   1337  nsIFrame* mResizerBox;
   1338  const nsIFrame* mReferenceFrameDuringPainting;
   1339  RefPtr<AsyncScroll> mAsyncScroll;
   1340  RefPtr<AsyncSmoothMSDScroll> mAsyncSmoothMSDScroll;
   1341  RefPtr<layout::ScrollbarActivity> mScrollbarActivity;
   1342  ScrollOrigin mLastScrollOrigin;
   1343  Maybe<nsPoint> mApzSmoothScrollDestination;
   1344  MainThreadScrollGeneration mScrollGeneration;
   1345  APZScrollGeneration mScrollGenerationOnApz;
   1346 
   1347  nsTArray<ScrollPositionUpdate> mScrollUpdates;
   1348 
   1349  // The minimum-scale size, this is specific to mobile environments where the
   1350  // initial-scale can be less than 1.0.
   1351  // See
   1352  // https://github.com/bokand/bokand.github.io/blob/master/web_viewports_explainer.md#minimum-scale
   1353  // for details.
   1354  nsSize mMinimumScaleSize;
   1355 
   1356  // Stores the ICB size for the root document if this frame is using the
   1357  // minimum scale size for |mScrollPort|.
   1358  nsSize mICBSize;
   1359 
   1360  // Where we're currently scrolling to, if we're scrolling asynchronously.
   1361  // If we're not in the middle of an asynchronous scroll then this is
   1362  // just the current scroll position. ScrollBy will choose its
   1363  // destination based on this value.
   1364  nsPoint mDestination;
   1365 
   1366  // A goal position to try to scroll to as content loads. As long as mLastPos
   1367  // matches the current logical scroll position, we try to scroll to
   1368  // mRestorePos after every reflow --- because after each time content is
   1369  // loaded/added to the scrollable element, there will be a reflow.
   1370  // Note that for frames where layout and visual viewport aren't one and the
   1371  // same thing, this scroll position will be the logical scroll position of
   1372  // the *visual* viewport, as its position will be more relevant to the user.
   1373  nsPoint mRestorePos;
   1374  // The last logical position we scrolled to while trying to restore
   1375  // mRestorePos, or 0,0 when this is a new frame. Set to -1,-1 once we've
   1376  // scrolled for any reason other than trying to restore mRestorePos.
   1377  // Just as with mRestorePos, this position will be the logical position of
   1378  // the *visual* viewport where available.
   1379  nsPoint mLastPos;
   1380 
   1381  // The latest scroll position we've sent or received from APZ. This
   1382  // represents the main thread's best knowledge of the APZ scroll position,
   1383  // and is used to calculate relative scroll offset updates.
   1384  nsPoint mApzScrollPos;
   1385 
   1386  nsExpirationState mActivityExpirationState;
   1387 
   1388  nsCOMPtr<nsITimer> mScrollActivityTimer;
   1389 
   1390  // The scroll position where we last updated frame visibility.
   1391  nsPoint mLastUpdateFramesPos;
   1392  nsRect mDisplayPortAtLastFrameUpdate;
   1393 
   1394  nsRect mPrevScrolledRect;
   1395 
   1396  layers::ScrollableLayerGuid::ViewID mScrollParentID;
   1397 
   1398  // Timer to remove the displayport some time after scrolling has stopped
   1399  nsCOMPtr<nsITimer> mDisplayPortExpiryTimer;
   1400 
   1401  ScrollAnchorContainer mAnchor;
   1402 
   1403  // We keep holding a strong reference for each snap target element until the
   1404  // next snapping happens so that it avoids using the same nsIContent* pointer
   1405  // for newly created contents in this scroll container. Otherwise we will try
   1406  // to match different nsIContent(s) generated at the same address during
   1407  // re-snapping.
   1408  SnapTargetSet mSnapTargets;
   1409 
   1410  // Representing there's an APZ animation is in progress and what caused the
   1411  // animation. Note that this is only set when repainted via APZ, which means
   1412  // that there may be a request for an APZ animation in flight for example,
   1413  // while this is still `No`. In order to answer "is an APZ animation in the
   1414  // process of starting or in progress" you need to check mScrollUpdates,
   1415  // mApzAnimationRequested, and this type.
   1416  APZScrollAnimationType mCurrentAPZScrollAnimationType;
   1417 
   1418  // The paint sequence number if the scroll frame is the first scrollable frame
   1419  // encountered.
   1420  Maybe<uint32_t> mIsFirstScrollableFrameSequenceNumber;
   1421 
   1422  // Representing whether the APZC corresponding to this frame is now in the
   1423  // middle of handling a gesture (e.g. a pan gesture).
   1424  InScrollingGesture mInScrollingGesture : 1;
   1425 
   1426  bool mAllowScrollOriginDowngrade : 1;
   1427  bool mHadDisplayPortAtLastFrameUpdate : 1;
   1428 
   1429  // True if the most recent reflow of the scroll container frame has
   1430  // the vertical scrollbar shown.
   1431  bool mHasVerticalScrollbar : 1;
   1432  // True if the most recent reflow of the scroll container frame has the
   1433  // horizontal scrollbar shown.
   1434  bool mHasHorizontalScrollbar : 1;
   1435 
   1436  // If mHas(Vertical|Horizontal)Scrollbar is true then
   1437  // mOnlyNeed(V|H)ScrollbarToScrollVVInsideLV indicates if the only reason we
   1438  // need that scrollbar is to scroll the visual viewport inside the layout
   1439  // viewport. These scrollbars are special in that even if they are layout
   1440  // scrollbars they do not take up any layout space.
   1441  bool mOnlyNeedVScrollbarToScrollVVInsideLV : 1;
   1442  bool mOnlyNeedHScrollbarToScrollVVInsideLV : 1;
   1443  bool mFrameIsUpdatingScrollbar : 1;
   1444  bool mDidHistoryRestore : 1;
   1445  // Is this the scrollframe for the document's viewport?
   1446  bool mIsRoot : 1;
   1447  // If true, we skipped a scrollbar layout due to mSuppressScrollbarUpdate
   1448  // being set at some point.  That means we should lay out scrollbars even if
   1449  // it might not strictly be needed next time mSuppressScrollbarUpdate is
   1450  // false.
   1451  bool mSkippedScrollbarLayout : 1;
   1452 
   1453  bool mHadNonInitialReflow : 1;
   1454  // Initially true; first call to ReflowFinished() sets it to false.
   1455  bool mFirstReflow : 1;
   1456  // State used only by PostScrollEvents so we know
   1457  // which overflow states have changed.
   1458  bool mHorizontalOverflow : 1;
   1459  bool mVerticalOverflow : 1;
   1460  bool mPostedReflowCallback : 1;
   1461  bool mMayHaveDirtyFixedChildren : 1;
   1462  // If true, need to actually update our scrollbar attributes in the
   1463  // reflow callback.
   1464  bool mUpdateScrollbarAttributes : 1;
   1465  // If true, we should be prepared to scroll using this scrollframe
   1466  // by placing descendant content into its own layer(s)
   1467  bool mHasBeenScrolledRecently : 1;
   1468 
   1469  // If true, the scroll frame should always be active because we always build
   1470  // a scrollable layer. Used for asynchronous scrolling.
   1471  bool mWillBuildScrollableLayer : 1;
   1472 
   1473  // If true, the scroll frame is an ancestor of other "active" scrolling
   1474  // frames, where "active" means has a non-minimal display port if
   1475  // ShouldActivateAllScrollFrames is true, or has a display port if
   1476  // ShouldActivateAllScrollFrames is false. And this means that we shouldn't
   1477  // expire the display port (if ShouldActivateAllScrollFrames is true then
   1478  // expiring a display port means making it minimal, otherwise it means
   1479  // removing the display port). If those descendant scrollframes have their
   1480  // display ports removed or made minimal, then we expire our display port.
   1481  bool mIsParentToActiveScrollFrames : 1;
   1482 
   1483  // True if this frame has been scrolled at least once
   1484  bool mHasBeenScrolled : 1;
   1485 
   1486  // True if the events synthesized by OSX to produce momentum scrolling should
   1487  // be ignored.  Reset when the next real, non-synthesized scroll event occurs.
   1488  bool mIgnoreMomentumScroll : 1;
   1489 
   1490  // True if the APZ is in the process of async-transforming this scrollframe,
   1491  // (as best as we can tell on the main thread, anyway).
   1492  bool mTransformingByAPZ : 1;
   1493 
   1494  // True if APZ can scroll this frame asynchronously (i.e. it has an APZC
   1495  // set up for this frame and it's not a scrollinfo layer).
   1496  bool mScrollableByAPZ : 1;
   1497 
   1498  // True if the APZ is allowed to zoom this scrollframe.
   1499  bool mZoomableByAPZ : 1;
   1500 
   1501  // True if the scroll frame contains out-of-flow content and is inside
   1502  // a CSS filter.
   1503  bool mHasOutOfFlowContentInsideFilter : 1;
   1504 
   1505  // True if we don't want the scrollbar to repaint itself right now.
   1506  bool mSuppressScrollbarRepaints : 1;
   1507 
   1508  // True if we are using the minimum scale size instead of ICB for scroll port.
   1509  bool mIsUsingMinimumScaleSize : 1;
   1510 
   1511  // True if the minimum scale size has been changed since the last reflow.
   1512  bool mMinimumScaleSizeChanged : 1;
   1513 
   1514  // True if we're processing an scroll event.
   1515  bool mProcessingScrollEvent : 1;
   1516 
   1517  // This is true from the time a scroll animation is requested of APZ to the
   1518  // time that APZ responds with an up-to-date repaint request. More precisely,
   1519  // this is flipped to true if a repaint request is dispatched to APZ where
   1520  // the most recent scroll request is a smooth scroll, and it is cleared when
   1521  // mApzAnimationInProgress is updated.
   1522  bool mApzAnimationRequested : 1;
   1523 
   1524  // Similar to above mApzAnimationRequested but the request came from script,
   1525  // e.g., scrollBy().
   1526  bool mApzAnimationTriggeredByScriptRequested : 1;
   1527 
   1528  // Whether we need to reclamp the visual viewport offset in ReflowFinished.
   1529  bool mReclampVVOffsetInReflowFinished : 1;
   1530 
   1531  // Whether we need to schedule the scroll-driven animations.
   1532  bool mMayScheduleScrollAnimations : 1;
   1533 
   1534 #ifdef MOZ_WIDGET_ANDROID
   1535  // True if this scrollable frame was vertically overflowed on the last reflow.
   1536  bool mHasVerticalOverflowForDynamicToolbar : 1;
   1537 #endif
   1538 
   1539  layout::ScrollVelocityQueue mVelocityQueue;
   1540 
   1541  // NOTE: On mobile this value might be factoring into overflow:hidden region
   1542  // in the case of the top level document.
   1543  nsRect mScrollPort;
   1544  UniquePtr<ScrollSnapTargetIds> mLastSnapTargetIds;
   1545  // Lazily created on demand, see StickyScrollContainer::GetOrCreateForFrame.
   1546  UniquePtr<StickyScrollContainer> mStickyContainer;
   1547 };
   1548 
   1549 }  // namespace mozilla
   1550 
   1551 #endif /* mozilla_ScrollContainerFrame_h_ */