Bug 1601185. Add a function that returns if a user can scroll on a given scroll frame in either direction and use it in EventStateManager::ComputeScrollTargetAndMayAdjustWheelEvent. r=botond
authorTimothy Nikkel <tnikkel@gmail.com>
Sat, 07 Dec 2019 22:56:00 +0000
changeset 568130 329340b1608d79266217ae37b098fa270f444c89
parent 568129 053b0bb00fedc42ea54e7a6b8e32843d7d6b7849
child 568131 09770afb0f03b135298f892bb664ddaaf76b1cee
push id12493
push userffxbld-merge
push dateMon, 06 Jan 2020 15:38:57 +0000
treeherdermozilla-beta@63ae456b848d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1601185
milestone73.0a1
first release with
nightly linux32
329340b1608d / 73.0a1 / 20191208213628 / files
nightly linux64
329340b1608d / 73.0a1 / 20191208213628 / files
nightly mac
329340b1608d / 73.0a1 / 20191208213628 / files
nightly win32
329340b1608d / 73.0a1 / 20191208213628 / files
nightly win64
329340b1608d / 73.0a1 / 20191208213628 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1601185. Add a function that returns if a user can scroll on a given scroll frame in either direction and use it in EventStateManager::ComputeScrollTargetAndMayAdjustWheelEvent. r=botond Previously we were just checking overflow hidden here, which is not enough because we can scroll overflow hidden if we are zoomed in. Differential Revision: https://phabricator.services.mozilla.com/D55918
dom/events/EventStateManager.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIScrollableFrame.h
--- a/dom/events/EventStateManager.cpp
+++ b/dom/events/EventStateManager.cpp
@@ -2633,22 +2633,24 @@ nsIFrame* EventStateManager::ComputeScro
         case layers::ScrollDirection::eVertical:
           if (checkIfScrollableY) {
             continue;
           }
           break;
       }
     }
 
-    ScrollStyles ss = scrollableFrame->GetScrollStyles();
-    bool hiddenForV = (StyleOverflow::Hidden == ss.mVertical);
-    bool hiddenForH = (StyleOverflow::Hidden == ss.mHorizontal);
-    if ((hiddenForV && hiddenForH) ||
-        (checkIfScrollableY && !checkIfScrollableX && hiddenForV) ||
-        (checkIfScrollableX && !checkIfScrollableY && hiddenForH)) {
+    uint32_t directions =
+        scrollableFrame->GetAvailableScrollingDirectionsForUserInputEvents();
+    if ((!(directions & nsIScrollableFrame::VERTICAL) &&
+         !(directions & nsIScrollableFrame::HORIZONTAL)) ||
+        (checkIfScrollableY && !checkIfScrollableX &&
+         !(directions & nsIScrollableFrame::VERTICAL)) ||
+        (checkIfScrollableX && !checkIfScrollableY &&
+         !(directions & nsIScrollableFrame::HORIZONTAL))) {
       continue;
     }
 
     // Computes whether the currently checked frame is scrollable by this wheel
     // event.
     bool canScroll = false;
     if (isAutoDir) {
       ESMAutoDirWheelDeltaAdjuster adjuster(*aEvent, *scrollFrame, honoursRoot);
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -6661,16 +6661,52 @@ uint32_t nsIScrollableFrame::GetAvailabl
     directions |= HORIZONTAL;
   }
   if (scrollRange.height >= oneDevPixel) {
     directions |= VERTICAL;
   }
   return directions;
 }
 
+uint32_t ScrollFrameHelper::GetAvailableScrollingDirectionsForUserInputEvents()
+    const {
+  // This function basically computes a scroll range based on a scrolled rect
+  // and scroll port defined as follows:
+  //   scrollable rect = overflow:hidden ? layout viewport : scrollable rect
+  //   scroll port = have visual viewport ? visual viewport : layout viewport
+  // The results in the same notion of scroll range that APZ uses (the combined
+  // effect of FrameMetrics::CalculateScrollRange() and
+  // nsLayoutUtils::CalculateScrollableRectForFrame).
+
+  ScrollStyles ss = GetScrollStylesFromFrame();
+
+  nsRect scrolledRect = GetScrolledRect();
+  if (StyleOverflow::Hidden == ss.mHorizontal) {
+    scrolledRect.width = mScrollPort.width;
+  }
+  if (StyleOverflow::Hidden == ss.mVertical) {
+    scrolledRect.height = mScrollPort.height;
+  }
+
+  nsSize scrollPort = GetVisualViewportSize();
+
+  nsSize scrollRange;
+  scrollRange.width = std::max(scrolledRect.width - scrollPort.width, 0);
+  scrollRange.height = std::max(scrolledRect.height - scrollPort.height, 0);
+
+  uint32_t directions = 0;
+  if (scrollRange.width > 0) {
+    directions |= nsIScrollableFrame::HORIZONTAL;
+  }
+  if (scrollRange.height > 0) {
+    directions |= nsIScrollableFrame::VERTICAL;
+  }
+  return directions;
+}
+
 static nsRect InflateByScrollMargin(const nsRect& aTargetRect,
                                     const nsMargin& aScrollMargin,
                                     const nsRect& aScrolledRect) {
   // Inflate the rect by scroll-margin.
   nsRect result = aTargetRect;
   result.Inflate(aScrollMargin);
 
   // But don't be beyond the limit boundary.
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -327,16 +327,18 @@ class ScrollFrameHelper : public nsIRefl
    * Currently it allows scrolling down and to the right for
    * nsHTMLScrollFrames with LTR directionality and for all
    * nsXULScrollFrames, and allows scrolling down and to the left for
    * nsHTMLScrollFrames with RTL directionality.
    */
   nsRect GetUnsnappedScrolledRectInternal(const nsRect& aScrolledOverflowArea,
                                           const nsSize& aScrollPortSize) const;
 
+  uint32_t GetAvailableScrollingDirectionsForUserInputEvents() const;
+
   uint32_t GetScrollbarVisibility() const {
     return (mHasVerticalScrollbar ? nsIScrollableFrame::VERTICAL : 0) |
            (mHasHorizontalScrollbar ? nsIScrollableFrame::HORIZONTAL : 0);
   }
   nsMargin GetActualScrollbarSizes() const;
   nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
   nscoord GetNondisappearingScrollbarWidth(nsBoxLayoutState* aState,
                                            mozilla::WritingMode aVerticalWM);
@@ -857,16 +859,19 @@ class nsHTMLScrollFrame : public nsConta
   }
   mozilla::ScrollStyles GetScrollStyles() const override {
     return mHelper.GetScrollStylesFromFrame();
   }
   mozilla::layers::OverscrollBehaviorInfo GetOverscrollBehaviorInfo()
       const final {
     return mHelper.GetOverscrollBehaviorInfo();
   }
+  uint32_t GetAvailableScrollingDirectionsForUserInputEvents() const final {
+    return mHelper.GetAvailableScrollingDirectionsForUserInputEvents();
+  }
   uint32_t GetScrollbarVisibility() const final {
     return mHelper.GetScrollbarVisibility();
   }
   nsMargin GetActualScrollbarSizes() const final {
     return mHelper.GetActualScrollbarSizes();
   }
   nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) final {
     return mHelper.GetDesiredScrollbarSizes(aState);
@@ -1319,16 +1324,19 @@ class nsXULScrollFrame final : public ns
   }
   mozilla::ScrollStyles GetScrollStyles() const final {
     return mHelper.GetScrollStylesFromFrame();
   }
   mozilla::layers::OverscrollBehaviorInfo GetOverscrollBehaviorInfo()
       const final {
     return mHelper.GetOverscrollBehaviorInfo();
   }
+  uint32_t GetAvailableScrollingDirectionsForUserInputEvents() const final {
+    return mHelper.GetAvailableScrollingDirectionsForUserInputEvents();
+  }
   uint32_t GetScrollbarVisibility() const final {
     return mHelper.GetScrollbarVisibility();
   }
   nsMargin GetActualScrollbarSizes() const final {
     return mHelper.GetActualScrollbarSizes();
   }
   nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState) final {
     return mHelper.GetDesiredScrollbarSizes(aState);
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -96,16 +96,23 @@ class nsIScrollableFrame : public nsIScr
   uint32_t GetAvailableScrollingDirections() const;
   /**
    * Returns the directions in which scrolling is allowed (if the scroll range
    * is at least one device pixel in that direction) when taking into account
    * the visual viewport size.
    */
   uint32_t GetAvailableVisualScrollingDirections() const;
   /**
+   * Returns the directions in which scrolling is allowed when taking into
+   * account the visual viewport size and overflow hidden. (An (apz) zoomed in
+   * overflow hidden scrollframe is actually user scrollable.)
+   */
+  virtual uint32_t GetAvailableScrollingDirectionsForUserInputEvents()
+      const = 0;
+  /**
    * Return the actual sizes of all possible scrollbars. Returns 0 for scrollbar
    * positions that don't have a scrollbar or where the scrollbar is not
    * visible. Do not call this while this frame's descendants are being
    * reflowed, it won't be accurate.
    */
   virtual nsMargin GetActualScrollbarSizes() const = 0;
   /**
    * Return the sizes of all scrollbars assuming that any scrollbars that could