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 draft
authorMasayuki Nakano <masayuki@d-toybox.com>
Tue, 05 Sep 2017 17:17:21 +0900
changeset 661241 f913f68f2af214e9c40fed5dee35cab9398449eb
parent 661240 dd62c7f6fd9e236b45389e017b50240b61ee1723
child 661242 c8a85f8076e25ee0dfaa794251532e105f8dd83f
push id78698
push usermasayuki@d-toybox.com
push dateFri, 08 Sep 2017 07:58:14 +0000
reviewerssmaug
bugs1369072
milestone57.0a1
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.