Bug 791616. Part 1: Add nsIScrollableFrame::GetPerceivedScrollingDirections to consolidate logic for whether UI actions should be allowed to scroll in a given direction. r=mats
authorRobert O'Callahan <robert@ocallahan.org>
Mon, 24 Sep 2012 16:30:33 +1200
changeset 108001 50d89c05af5ba7d5d40c7277e61c882fbc80cb7e
parent 108000 3425c7e124b045813eb2108dc6eaacef0ecdd11f
child 108002 6211dca38071c978f2160a5d581d9de2fa0932b9
push id82
push usershu@rfrn.org
push dateFri, 05 Oct 2012 13:20:22 +0000
reviewersmats
bugs791616
milestone18.0a1
Bug 791616. Part 1: Add nsIScrollableFrame::GetPerceivedScrollingDirections to consolidate logic for whether UI actions should be allowed to scroll in a given direction. r=mats
content/events/src/nsEventStateManager.cpp
layout/base/nsLayoutUtils.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsIScrollableFrame.h
--- a/content/events/src/nsEventStateManager.cpp
+++ b/content/events/src/nsEventStateManager.cpp
@@ -378,22 +378,21 @@ static bool
 CanScrollOn(nsIScrollableFrame* aScrollFrame, double aDeltaX, double aDeltaY)
 {
   MOZ_ASSERT(aScrollFrame);
   NS_ASSERTION(aDeltaX || aDeltaY,
                "One of the delta values must be non-zero at least");
 
   nsPoint scrollPt = aScrollFrame->GetScrollPosition();
   nsRect scrollRange = aScrollFrame->GetScrollRange();
-  nscoord oneDevPixel =
-    aScrollFrame->GetScrolledFrame()->PresContext()->AppUnitsPerDevPixel();
-
-  return (aDeltaX && scrollRange.width >= oneDevPixel &&
+  uint32_t directions = aScrollFrame->GetPerceivedScrollingDirections();
+
+  return (aDeltaX && (directions & nsIScrollableFrame::HORIZONTAL) &&
           CanScrollInRange(scrollRange.x, scrollPt.x, scrollRange.XMost(), aDeltaX)) ||
-         (aDeltaY && scrollRange.height >= oneDevPixel &&
+         (aDeltaY && (directions & nsIScrollableFrame::VERTICAL) &&
           CanScrollInRange(scrollRange.y, scrollPt.y, scrollRange.YMost(), aDeltaY));
 }
 
 void
 nsMouseWheelTransaction::BeginTransaction(nsIFrame* aTargetFrame,
                                           widget::WheelEvent* aEvent)
 {
   NS_ASSERTION(!sTargetFrame, "previous transaction is not finished!");
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -938,28 +938,22 @@ nsIScrollableFrame*
 nsLayoutUtils::GetNearestScrollableFrameForDirection(nsIFrame* aFrame,
                                                      Direction aDirection)
 {
   NS_ASSERTION(aFrame, "GetNearestScrollableFrameForDirection expects a non-null frame");
   for (nsIFrame* f = aFrame; f; f = nsLayoutUtils::GetCrossDocParentFrame(f)) {
     nsIScrollableFrame* scrollableFrame = do_QueryFrame(f);
     if (scrollableFrame) {
       nsPresContext::ScrollbarStyles ss = scrollableFrame->GetScrollbarStyles();
-      uint32_t scrollbarVisibility = scrollableFrame->GetScrollbarVisibility();
-      nsRect scrollRange = scrollableFrame->GetScrollRange();
-      // Require visible scrollbars or something to scroll to in
-      // the given direction.
-      nscoord oneDevPixel = f->PresContext()->DevPixelsToAppUnits(1);
+      uint32_t directions = scrollableFrame->GetPerceivedScrollingDirections();
       if (aDirection == eVertical ?
           (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN &&
-           ((scrollbarVisibility & nsIScrollableFrame::VERTICAL) ||
-            scrollRange.height >= oneDevPixel)) :
+           (directions & nsIScrollableFrame::VERTICAL)) :
           (ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN &&
-           ((scrollbarVisibility & nsIScrollableFrame::HORIZONTAL) ||
-            scrollRange.width >= oneDevPixel)))
+           (directions & nsIScrollableFrame::HORIZONTAL)))
         return scrollableFrame;
     }
   }
   return nullptr;
 }
 
 // static
 nsIScrollableFrame*
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -4165,8 +4165,23 @@ nsGfxScrollFrameInner::FireScrolledAreaE
 
   event.mArea = mScrolledFrame->GetScrollableOverflowRectRelativeToParent();
 
   nsIDocument *doc = content->GetCurrentDoc();
   if (doc) {
     nsEventDispatcher::Dispatch(doc, prescontext, &event, nullptr);
   }
 }
+
+uint32_t
+nsIScrollableFrame::GetPerceivedScrollingDirections() const
+{
+  nscoord oneDevPixel = GetScrolledFrame()->PresContext()->AppUnitsPerDevPixel();
+  uint32_t directions = GetScrollbarVisibility();
+  nsRect scrollRange = GetScrollRange();
+  if (scrollRange.width >= oneDevPixel) {
+    directions |= HORIZONTAL;
+  }
+  if (scrollRange.height >= oneDevPixel) {
+    directions |= VERTICAL;
+  }
+  return directions;
+}
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -47,16 +47,22 @@ public:
   enum { HORIZONTAL = 0x01, VERTICAL = 0x02 };
   /**
    * Return the scrollbars which are visible. It's OK to call this during reflow
    * of the scrolled contents, in which case it will reflect the current
    * assumptions about scrollbar visibility.
    */
   virtual uint32_t GetScrollbarVisibility() const = 0;
   /**
+   * Returns the directions in which scrolling is perceived to be allowed.
+   * A direction is perceived to be allowed if there is a visible scrollbar
+   * for that direction or if the scroll range is at least one device pixel.
+   */
+  uint32_t GetPerceivedScrollingDirections() const;
+  /**
    * 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