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
--- 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.