Bug 1369072 - part1: PresShell should climb up scrollable frames when there is no selection, no focused content and root scrollable frame isn't scrollable r=smaug
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 05 Sep 2017 17:17:21 +0900
changeset 379691 19f8a5d3da39cc4f2313f2dac2c4dbb04a6329e8
parent 379690 2e507cfef60d45641908a36a977d2497d77e4c84
child 379692 1c3ac6cb53ea9c76c89d8e5d1cb1ee19703e1180
push id32461
push userkwierso@gmail.com
push dateFri, 08 Sep 2017 20:15:32 +0000
treeherdermozilla-central@dd3736e98e4e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssmaug
bugs1369072
milestone57.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 1369072 - part1: PresShell should climb up scrollable frames when there is no selection, no focused content and root scrollable frame isn't scrollable r=smaug When there is no selection and no focused content, aContent of nsIPresShell::GetScrollableFrameToScrollForContent() is nullptr. Then, it'll use root scrollable frame to scroll. However, the root scrollable frame may be not scrollable. In such case, ancestor document's scrollable frame should be scrolled instead. MozReview-Commit-ID: 1kOPtDX6G5L
layout/base/PresShell.cpp
layout/base/nsIPresShell.h
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -2866,41 +2866,52 @@ nsIPresShell::GetSelectedContentForScrol
       domSelection->GetFocusNode(getter_AddRefs(focusedNode));
       selectedContent = do_QueryInterface(focusedNode);
     }
   }
   return selectedContent.forget();
 }
 
 nsIScrollableFrame*
+nsIPresShell::GetNearestScrollableFrame(
+                nsIFrame* aFrame,
+                nsIPresShell::ScrollDirection aDirection)
+{
+  if (aDirection == nsIPresShell::eEither) {
+    return nsLayoutUtils::GetNearestScrollableFrame(aFrame);
+  }
+
+  return nsLayoutUtils::GetNearestScrollableFrameForDirection(aFrame,
+           aDirection == eVertical ? nsLayoutUtils::eVertical :
+                                     nsLayoutUtils::eHorizontal);
+}
+
+nsIScrollableFrame*
 nsIPresShell::GetScrollableFrameToScrollForContent(
                 nsIContent* aContent,
                 nsIPresShell::ScrollDirection aDirection)
 {
   nsIScrollableFrame* scrollFrame = nullptr;
   if (aContent) {
     nsIFrame* startFrame = aContent->GetPrimaryFrame();
     if (startFrame) {
       scrollFrame = startFrame->GetScrollTargetFrame();
       if (scrollFrame) {
         startFrame = scrollFrame->GetScrolledFrame();
       }
-      if (aDirection == nsIPresShell::eEither) {
-        scrollFrame =
-          nsLayoutUtils::GetNearestScrollableFrame(startFrame);
-      } else {
-        scrollFrame =
-          nsLayoutUtils::GetNearestScrollableFrameForDirection(startFrame,
-            aDirection == eVertical ? nsLayoutUtils::eVertical :
-                                      nsLayoutUtils::eHorizontal);
-      }
+      scrollFrame = GetNearestScrollableFrame(startFrame, aDirection);
     }
   }
   if (!scrollFrame) {
     scrollFrame = GetRootScrollFrameAsScrollable();
+    if (!scrollFrame || !scrollFrame->GetScrolledFrame()) {
+      return nullptr;
+    }
+    scrollFrame = GetNearestScrollableFrame(scrollFrame->GetScrolledFrame(),
+                                            aDirection);
   }
   return scrollFrame;
 }
 
 nsIScrollableFrame*
 nsIPresShell::GetScrollableFrameToScroll(nsIPresShell::ScrollDirection aDirection)
 {
   nsCOMPtr<nsIContent> content = GetContentForScrolling();
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -444,16 +444,25 @@ public:
    * selection if there is no focused content. The frame is scrollable with
    * overflow:scroll or overflow:auto in some direction when aDirection is
    * eEither.  Otherwise, this returns a nearest frame that is scrollable in
    * the specified direction.
    */
   nsIScrollableFrame* GetScrollableFrameToScroll(ScrollDirection aDirection);
 
   /**
+   * Gets nearest ancestor scrollable frame from aFrame.  The frame is
+   * scrollable with overflow:scroll or overflow:auto in some direction when
+   * aDirection is eEither.  Otherwise, this returns a nearest frame that is
+   * scrollable in the specified direction.
+   */
+  nsIScrollableFrame* GetNearestScrollableFrame(nsIFrame* aFrame,
+                                                ScrollDirection aDirection);
+
+  /**
    * Returns the page sequence frame associated with the frame hierarchy.
    * Returns nullptr if not a paginated view.
    */
   virtual nsIPageSequenceFrame* GetPageSequenceFrame() const = 0;
 
   /**
   * Returns the canvas frame associated with the frame hierarchy.
   * Returns nullptr if is XUL document.