Bug 1560237 - Introduce nsIScrollableFrame::IsSmoothScroll. r=botond
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Wed, 26 Jun 2019 20:59:01 +0000
changeset 543077 065a45b8659dc25fb91738a7625dab916b76d0b6
parent 543076 2b77a507ec0561dac16dcaef8b3a89a2d0b3f28f
child 543078 a269192c5d3037c7841d30219516548a6fa8db1a
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1560237
milestone69.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1560237 - Introduce nsIScrollableFrame::IsSmoothScroll. r=botond This is pretty much the same as ScrollStyles::IsSmoothScroll right now, but in the next commit, we will no longer propagate scroll-behavior on <body> to the root element so that nsIScrollableFrame::IsSmoothScroll will be changed to reflect it. Differential Revision: https://phabricator.services.mozilla.com/D35737
docshell/base/nsDocShell.cpp
dom/base/Element.cpp
dom/base/nsGlobalWindowInner.cpp
layout/base/PresShell.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIScrollableFrame.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -5713,21 +5713,18 @@ nsPoint nsDocShell::GetCurScrollPos() {
   return scrollPos;
 }
 
 nsresult nsDocShell::SetCurScrollPosEx(int32_t aCurHorizontalPos,
                                        int32_t aCurVerticalPos) {
   nsIScrollableFrame* sf = GetRootScrollFrame();
   NS_ENSURE_TRUE(sf, NS_ERROR_FAILURE);
 
-  ScrollMode scrollMode = ScrollMode::Instant;
-  if (sf->GetScrollStyles().mScrollBehavior ==
-      NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
-    scrollMode = ScrollMode::SmoothMsd;
-  }
+  ScrollMode scrollMode =
+      sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
 
   nsPoint targetPos(aCurHorizontalPos, aCurVerticalPos);
   sf->ScrollTo(targetPos, scrollMode);
 
   // Set the visual viewport offset as well.
 
   RefPtr<PresShell> presShell = GetPresShell();
   NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -781,25 +781,19 @@ void Element::ScrollIntoView(const Scrol
       this, ScrollAxis(whereToScrollVertically, WhenToScroll::Always),
       ScrollAxis(whereToScrollHorizontally, WhenToScroll::Always), scrollFlags);
 }
 
 void Element::Scroll(const CSSIntPoint& aScroll,
                      const ScrollOptions& aOptions) {
   nsIScrollableFrame* sf = GetScrollFrame();
   if (sf) {
-    ScrollMode scrollMode = ScrollMode::Instant;
-    if (aOptions.mBehavior == ScrollBehavior::Smooth) {
-      scrollMode = ScrollMode::SmoothMsd;
-    } else if (aOptions.mBehavior == ScrollBehavior::Auto) {
-      ScrollStyles styles = sf->GetScrollStyles();
-      if (styles.mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
-        scrollMode = ScrollMode::SmoothMsd;
-      }
-    }
+    ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
+                                ? ScrollMode::SmoothMsd
+                                : ScrollMode::Instant;
 
     sf->ScrollToCSSPixels(aScroll, scrollMode);
   }
 }
 
 void Element::Scroll(double aXScroll, double aYScroll) {
   // Convert -Inf, Inf, and NaN to 0; otherwise, convert by C-style cast.
   auto scrollPos = CSSIntPoint::Truncate(mozilla::ToZeroIfNonfinite(aXScroll),
@@ -844,25 +838,19 @@ void Element::ScrollBy(const ScrollToOpt
     CSSIntPoint scrollDelta;
     if (aOptions.mLeft.WasPassed()) {
       scrollDelta.x = mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
     }
     if (aOptions.mTop.WasPassed()) {
       scrollDelta.y = mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
     }
 
-    ScrollMode scrollMode = ScrollMode::Instant;
-    if (aOptions.mBehavior == ScrollBehavior::Smooth) {
-      scrollMode = ScrollMode::SmoothMsd;
-    } else if (aOptions.mBehavior == ScrollBehavior::Auto) {
-      ScrollStyles styles = sf->GetScrollStyles();
-      if (styles.mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
-        scrollMode = ScrollMode::SmoothMsd;
-      }
-    }
+    ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
+                                ? ScrollMode::SmoothMsd
+                                : ScrollMode::Instant;
 
     sf->ScrollByCSSPixels(scrollDelta, scrollMode, nsGkAtoms::relative);
   }
 }
 
 int32_t Element::ScrollTop() {
   nsIScrollableFrame* sf = GetScrollFrame();
   return sf ? sf->GetScrollPositionCSSPixels().y : 0;
@@ -874,21 +862,19 @@ void Element::SetScrollTop(int32_t aScro
   // need to flush frames so we ensure we find the right scrollable frame if
   // there is one.
   //
   // If aScrollTop is nonzero, we need to flush layout because we need to figure
   // out what our real scrollTopMax is.
   FlushType flushType = aScrollTop == 0 ? FlushType::Frames : FlushType::Layout;
   nsIScrollableFrame* sf = GetScrollFrame(nullptr, flushType);
   if (sf) {
-    ScrollMode scrollMode = ScrollMode::Instant;
-    if (sf->GetScrollStyles().mScrollBehavior ==
-        NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
-      scrollMode = ScrollMode::SmoothMsd;
-    }
+    ScrollMode scrollMode =
+        sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
+
     sf->ScrollToCSSPixels(
         CSSIntPoint(sf->GetScrollPositionCSSPixels().x, aScrollTop),
         scrollMode);
   }
 }
 
 int32_t Element::ScrollLeft() {
   nsIScrollableFrame* sf = GetScrollFrame();
@@ -896,21 +882,18 @@ int32_t Element::ScrollLeft() {
 }
 
 void Element::SetScrollLeft(int32_t aScrollLeft) {
   // We can't assume things here based on the value of aScrollLeft, because
   // depending on our direction and layout 0 may or may not be in our scroll
   // range.  So we need to flush layout no matter what.
   nsIScrollableFrame* sf = GetScrollFrame();
   if (sf) {
-    ScrollMode scrollMode = ScrollMode::Instant;
-    if (sf->GetScrollStyles().mScrollBehavior ==
-        NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
-      scrollMode = ScrollMode::SmoothMsd;
-    }
+    ScrollMode scrollMode =
+        sf->IsSmoothScroll() ? ScrollMode::SmoothMsd : ScrollMode::Instant;
 
     sf->ScrollToCSSPixels(
         CSSIntPoint(aScrollLeft, sf->GetScrollPositionCSSPixels().y),
         scrollMode);
   }
 }
 
 void Element::MozScrollSnap() {
--- a/dom/base/nsGlobalWindowInner.cpp
+++ b/dom/base/nsGlobalWindowInner.cpp
@@ -3646,21 +3646,21 @@ void nsGlobalWindowInner::ScrollTo(const
     if (scroll.x > maxpx) {
       scroll.x = maxpx;
     }
 
     if (scroll.y > maxpx) {
       scroll.y = maxpx;
     }
 
-    bool smoothScroll =
-        sf->GetScrollStyles().IsSmoothScroll(aOptions.mBehavior);
-
-    sf->ScrollToCSSPixels(
-        scroll, smoothScroll ? ScrollMode::SmoothMsd : ScrollMode::Instant);
+    ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
+                                ? ScrollMode::SmoothMsd
+                                : ScrollMode::Instant;
+
+    sf->ScrollToCSSPixels(scroll, scrollMode);
   }
 }
 
 void nsGlobalWindowInner::ScrollBy(double aXScrollDif, double aYScrollDif) {
   FlushPendingNotifications(FlushType::Layout);
   nsIScrollableFrame* sf = GetScrollFrame();
 
   if (sf) {
@@ -3682,59 +3682,55 @@ void nsGlobalWindowInner::ScrollBy(const
     CSSIntPoint scrollDelta;
     if (aOptions.mLeft.WasPassed()) {
       scrollDelta.x = mozilla::ToZeroIfNonfinite(aOptions.mLeft.Value());
     }
     if (aOptions.mTop.WasPassed()) {
       scrollDelta.y = mozilla::ToZeroIfNonfinite(aOptions.mTop.Value());
     }
 
-    ScrollMode scrollMode = ScrollMode::Instant;
-    if (aOptions.mBehavior == ScrollBehavior::Smooth) {
-      scrollMode = ScrollMode::SmoothMsd;
-    } else if (aOptions.mBehavior == ScrollBehavior::Auto) {
-      ScrollStyles styles = sf->GetScrollStyles();
-      if (styles.mScrollBehavior == NS_STYLE_SCROLL_BEHAVIOR_SMOOTH) {
-        scrollMode = ScrollMode::SmoothMsd;
-      }
-    }
+    ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
+                                ? ScrollMode::SmoothMsd
+                                : ScrollMode::Instant;
 
     sf->ScrollByCSSPixels(scrollDelta, scrollMode, nsGkAtoms::relative);
   }
 }
 
 void nsGlobalWindowInner::ScrollByLines(int32_t numLines,
                                         const ScrollOptions& aOptions) {
   FlushPendingNotifications(FlushType::Layout);
   nsIScrollableFrame* sf = GetScrollFrame();
   if (sf) {
     // It seems like it would make more sense for ScrollByLines to use
     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
     // Perhaps Web content does too.
-    bool smoothScroll =
-        sf->GetScrollStyles().IsSmoothScroll(aOptions.mBehavior);
+    ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
+                                ? ScrollMode::SmoothMsd
+                                : ScrollMode::Instant;
 
     sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES,
-                 smoothScroll ? ScrollMode::SmoothMsd : ScrollMode::Instant);
+                 scrollMode);
   }
 }
 
 void nsGlobalWindowInner::ScrollByPages(int32_t numPages,
                                         const ScrollOptions& aOptions) {
   FlushPendingNotifications(FlushType::Layout);
   nsIScrollableFrame* sf = GetScrollFrame();
   if (sf) {
     // It seems like it would make more sense for ScrollByPages to use
     // SMOOTH mode, but tests seem to depend on the synchronous behaviour.
     // Perhaps Web content does too.
-    bool smoothScroll =
-        sf->GetScrollStyles().IsSmoothScroll(aOptions.mBehavior);
+    ScrollMode scrollMode = sf->IsSmoothScroll(aOptions.mBehavior)
+                                ? ScrollMode::SmoothMsd
+                                : ScrollMode::Instant;
 
     sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES,
-                 smoothScroll ? ScrollMode::SmoothMsd : ScrollMode::Instant);
+                 scrollMode);
   }
 }
 
 void nsGlobalWindowInner::MozScrollSnap() {
   FlushPendingNotifications(FlushType::Layout);
   nsIScrollableFrame* sf = GetScrollFrame();
   if (sf) {
     sf->ScrollSnap();
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -3385,19 +3385,17 @@ static void ScrollToShowRect(PresShell* 
       needToScroll = true;
     }
   }
 
   // If we don't need to scroll, then don't try since it might cancel
   // a current smooth scroll operation.
   if (needToScroll) {
     ScrollMode scrollMode = ScrollMode::Instant;
-    bool autoBehaviorIsSmooth =
-        (aFrameAsScrollable->GetScrollStyles().mScrollBehavior ==
-         NS_STYLE_SCROLL_BEHAVIOR_SMOOTH);
+    bool autoBehaviorIsSmooth = aFrameAsScrollable->IsSmoothScroll();
     bool smoothScroll = (aScrollFlags & ScrollFlags::ScrollSmooth) ||
                         ((aScrollFlags & ScrollFlags::ScrollSmoothAuto) &&
                          autoBehaviorIsSmooth);
     if (StaticPrefs::ScrollBehaviorEnabled() && smoothScroll) {
       scrollMode = ScrollMode::SmoothMsd;
     }
     nsIFrame* frame = do_QueryFrame(aFrameAsScrollable);
     AutoWeakFrame weakFrame(frame);
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -7123,8 +7123,15 @@ bool ScrollFrameHelper::SmoothScrollVisu
   mDestination = GetVisualScrollRange().ClampPoint(aVisualViewportOffset);
 
   // Perform the scroll.
   ApzSmoothScrollTo(mDestination, aUpdateType == FrameMetrics::eRestore
                                       ? nsGkAtoms::restore
                                       : nsGkAtoms::other);
   return true;
 }
+
+bool ScrollFrameHelper::IsSmoothScroll(dom::ScrollBehavior aBehavior) const {
+  return aBehavior == dom::ScrollBehavior::Smooth ||
+         (aBehavior == dom::ScrollBehavior::Auto &&
+          GetScrollStylesFromFrame().mScrollBehavior ==
+              NS_STYLE_SCROLL_BEHAVIOR_SMOOTH);
+}
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -497,16 +497,18 @@ class ScrollFrameHelper : public nsIRefl
   void AsyncScrollbarDragRejected();
 
   bool IsRootScrollFrameOfDocument() const { return mIsRoot; }
 
   bool SmoothScrollVisual(
       const nsPoint& aVisualViewportOffset,
       mozilla::layers::FrameMetrics::ScrollOffsetUpdateType aUpdateType);
 
+  bool IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior) const;
+
   // Update minimum-scale size.  The minimum-scale size will be set/used only
   // if there is overflow-x:hidden region.
   void UpdateMinimumScaleSize(const nsRect& aScrollableOverflow,
                               const nsSize& aICBSize);
 
   // Return the scroll frame's "true outer size".
   // This is mOuter->GetSize(), except when mOuter has been sized to reflect
   // a virtual (layout) viewport in which case this returns the outer size
@@ -1181,16 +1183,20 @@ class nsHTMLScrollFrame : public nsConta
   }
 
   bool SmoothScrollVisual(const nsPoint& aVisualViewportOffset,
                           mozilla::layers::FrameMetrics::ScrollOffsetUpdateType
                               aUpdateType) override {
     return mHelper.SmoothScrollVisual(aVisualViewportOffset, aUpdateType);
   }
 
+  bool IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior) const override {
+    return mHelper.IsSmoothScroll(aBehavior);
+  }
+
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
 #ifdef ACCESSIBILITY
   virtual mozilla::a11y::AccType AccessibleType() override;
 #endif
 
@@ -1670,16 +1676,20 @@ class nsXULScrollFrame final : public ns
   }
 
   bool SmoothScrollVisual(const nsPoint& aVisualViewportOffset,
                           mozilla::layers::FrameMetrics::ScrollOffsetUpdateType
                               aUpdateType) override {
     return mHelper.SmoothScrollVisual(aVisualViewportOffset, aUpdateType);
   }
 
+  bool IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior) const override {
+    return mHelper.IsSmoothScroll(aBehavior);
+  }
+
 #ifdef DEBUG_FRAME_DUMP
   virtual nsresult GetFrameName(nsAString& aResult) const override;
 #endif
 
  protected:
   nsXULScrollFrame(ComputedStyle*, nsPresContext*, bool aIsRoot,
                    bool aClipAllDescendants);
 
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -559,11 +559,18 @@ class nsIScrollableFrame : public nsIScr
    * never null.
    */
   virtual const ScrollAnchorContainer* Anchor() const = 0;
   virtual ScrollAnchorContainer* Anchor() = 0;
 
   virtual bool SmoothScrollVisual(
       const nsPoint& aVisualViewportOffset,
       mozilla::layers::FrameMetrics::ScrollOffsetUpdateType aUpdateType) = 0;
+
+  /**
+   * Returns true if this scroll frame should perform smooth scroll with the
+   * given |aBehavior|.
+   */
+  virtual bool IsSmoothScroll(mozilla::dom::ScrollBehavior aBehavior =
+                                  mozilla::dom::ScrollBehavior::Auto) const = 0;
 };
 
 #endif