diff --git a/content/base/src/Element.cpp b/content/base/src/Element.cpp index e578f43e0b44..1926820eaa84 100644 --- a/content/base/src/Element.cpp +++ b/content/base/src/Element.cpp @@ -608,12 +608,17 @@ Element::ScrollIntoView(bool aTop, const ScrollOptions &aOptions) int16_t vpercent = aTop ? nsIPresShell::SCROLL_TOP : nsIPresShell::SCROLL_BOTTOM; + uint32_t flags = nsIPresShell::SCROLL_OVERFLOW_HIDDEN; + if (aOptions.mBehavior == ScrollBehavior::Smooth) { + flags |= nsIPresShell::SCROLL_SMOOTH; + } + presShell->ScrollContentIntoView(this, nsIPresShell::ScrollAxis( vpercent, nsIPresShell::SCROLL_ALWAYS), nsIPresShell::ScrollAxis(), - nsIPresShell::SCROLL_OVERFLOW_HIDDEN); + flags); } bool diff --git a/dom/base/nsGlobalWindow.cpp b/dom/base/nsGlobalWindow.cpp index d41c2d6f16bf..e0e8aaa3959c 100644 --- a/dom/base/nsGlobalWindow.cpp +++ b/dom/base/nsGlobalWindow.cpp @@ -7225,32 +7225,33 @@ void nsGlobalWindow::Scroll(int32_t aXScroll, int32_t aYScroll, const ScrollOptions& aOptions) { - ScrollTo(CSSIntPoint(aXScroll, aYScroll)); + ScrollTo(CSSIntPoint(aXScroll, aYScroll), aOptions); } void nsGlobalWindow::ScrollTo(int32_t aXScroll, int32_t aYScroll, const ScrollOptions& aOptions) { - ScrollTo(CSSIntPoint(aXScroll, aYScroll)); + ScrollTo(CSSIntPoint(aXScroll, aYScroll), aOptions); } NS_IMETHODIMP nsGlobalWindow::Scroll(int32_t aXScroll, int32_t aYScroll) { - ScrollTo(CSSIntPoint(aXScroll, aYScroll)); + ScrollTo(CSSIntPoint(aXScroll, aYScroll), ScrollOptions()); return NS_OK; } NS_IMETHODIMP nsGlobalWindow::ScrollTo(int32_t aXScroll, int32_t aYScroll) { - ScrollTo(CSSIntPoint(aXScroll, aYScroll)); + ScrollTo(CSSIntPoint(aXScroll, aYScroll), ScrollOptions()); return NS_OK; } void -nsGlobalWindow::ScrollTo(const CSSIntPoint& aScroll) +nsGlobalWindow::ScrollTo(const CSSIntPoint& aScroll, + const ScrollOptions& aOptions) { FlushPendingNotifications(Flush_Layout); nsIScrollableFrame *sf = GetScrollFrame(); @@ -7271,7 +7272,86 @@ nsGlobalWindow::ScrollTo(const CSSIntPoint& aScroll) if (scroll.y > maxpx) { scroll.y = maxpx; } - sf->ScrollToCSSPixels(scroll); + + sf->ScrollToCSSPixels(scroll, + aOptions.mBehavior == ScrollBehavior::Smooth + ? nsIScrollableFrame::SMOOTH_MSD + : nsIScrollableFrame::INSTANT); + } +} + +NS_IMETHODIMP +nsGlobalWindow::ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif) +{ + ScrollBy(aXScrollDif, aYScrollDif, ScrollOptions()); + + return NS_OK; +} + +void +nsGlobalWindow::ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif, + const ScrollOptions& aOptions) +{ + FlushPendingNotifications(Flush_Layout); + nsIScrollableFrame *sf = GetScrollFrame(); + + if (sf) { + CSSIntPoint scrollPos = + sf->GetScrollPositionCSSPixels() + CSSIntPoint(aXScrollDif, aYScrollDif); + // It seems like it would make more sense for ScrollBy to use + // SMOOTH mode, but tests seem to depend on the synchronous behaviour. + // Perhaps Web content does too. + ScrollTo(scrollPos, aOptions); + } +} + +NS_IMETHODIMP +nsGlobalWindow::ScrollByLines(int32_t numLines) +{ + ScrollByLines(numLines, ScrollOptions()); + + return NS_OK; +} + +void +nsGlobalWindow::ScrollByLines(int32_t numLines, + const ScrollOptions& aOptions) +{ + FlushPendingNotifications(Flush_Layout); + nsIScrollableFrame *sf = GetScrollFrame(); + if (sf) { + // It seems like it would make more sense for ScrollByLines to use + // SMOOTH mode, but tests seem to depend on the synchronous behaviour. + // Perhaps Web content does too. + sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES, + aOptions.mBehavior == ScrollBehavior::Smooth + ? nsIScrollableFrame::SMOOTH_MSD + : nsIScrollableFrame::INSTANT); + } +} + +NS_IMETHODIMP +nsGlobalWindow::ScrollByPages(int32_t numPages) +{ + ScrollByPages(numPages, ScrollOptions()); + + return NS_OK; +} + +void +nsGlobalWindow::ScrollByPages(int32_t numPages, + const ScrollOptions& aOptions) +{ + FlushPendingNotifications(Flush_Layout); + nsIScrollableFrame *sf = GetScrollFrame(); + if (sf) { + // It seems like it would make more sense for ScrollByPages to use + // SMOOTH mode, but tests seem to depend on the synchronous behaviour. + // Perhaps Web content does too. + sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES, + aOptions.mBehavior == ScrollBehavior::Smooth + ? nsIScrollableFrame::SMOOTH_MSD + : nsIScrollableFrame::INSTANT); } } @@ -7291,77 +7371,6 @@ nsGlobalWindow::MozRequestOverfill(OverfillCallback& aCallback, aError.Throw(NS_ERROR_NOT_AVAILABLE); } -void -nsGlobalWindow::ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif, - const ScrollOptions& aOptions) -{ - ScrollBy(aXScrollDif, aYScrollDif); -} - -void -nsGlobalWindow::ScrollByLines(int32_t numLines, - const ScrollOptions& aOptions) -{ - ScrollByLines(numLines); -} - -void -nsGlobalWindow::ScrollByPages(int32_t numPages, - const ScrollOptions& aOptions) -{ - ScrollByPages(numPages); -} - -NS_IMETHODIMP -nsGlobalWindow::ScrollBy(int32_t aXScrollDif, int32_t aYScrollDif) -{ - FlushPendingNotifications(Flush_Layout); - nsIScrollableFrame *sf = GetScrollFrame(); - - if (sf) { - CSSIntPoint scrollPos = - sf->GetScrollPositionCSSPixels() + CSSIntPoint(aXScrollDif, aYScrollDif); - // It seems like it would make more sense for ScrollBy to use - // SMOOTH mode, but tests seem to depend on the synchronous behaviour. - // Perhaps Web content does too. - ScrollTo(scrollPos); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsGlobalWindow::ScrollByLines(int32_t numLines) -{ - FlushPendingNotifications(Flush_Layout); - nsIScrollableFrame *sf = GetScrollFrame(); - if (sf) { - // It seems like it would make more sense for ScrollByLines to use - // SMOOTH mode, but tests seem to depend on the synchronous behaviour. - // Perhaps Web content does too. - sf->ScrollBy(nsIntPoint(0, numLines), nsIScrollableFrame::LINES, - nsIScrollableFrame::INSTANT); - } - - return NS_OK; -} - -NS_IMETHODIMP -nsGlobalWindow::ScrollByPages(int32_t numPages) -{ - FlushPendingNotifications(Flush_Layout); - nsIScrollableFrame *sf = GetScrollFrame(); - if (sf) { - // It seems like it would make more sense for ScrollByPages to use - // SMOOTH mode, but tests seem to depend on the synchronous behaviour. - // Perhaps Web content does too. - sf->ScrollBy(nsIntPoint(0, numPages), nsIScrollableFrame::PAGES, - nsIScrollableFrame::INSTANT); - } - - return NS_OK; -} - void nsGlobalWindow::ClearTimeout(int32_t aHandle, ErrorResult& aError) { diff --git a/dom/base/nsGlobalWindow.h b/dom/base/nsGlobalWindow.h index 96f60ac4762e..569a6ef16f84 100644 --- a/dom/base/nsGlobalWindow.h +++ b/dom/base/nsGlobalWindow.h @@ -1322,7 +1322,8 @@ public: mozilla::ErrorResult& aError); nsRect GetInnerScreenRect(); - void ScrollTo(const mozilla::CSSIntPoint& aScroll); + void ScrollTo(const mozilla::CSSIntPoint& aScroll, + const mozilla::dom::ScrollOptions& aOptions); bool IsFrame() { diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 10df929885f3..046260a359b6 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -681,6 +681,10 @@ public: * If SCROLL_NO_PARENT_FRAMES is set then we only scroll * nodes in this document, not in any parent documents which * contain this document in a iframe or the like. + * If SCROLL_SMOOTH is set and CSSOM-VIEW scroll-behavior + * is enabled, we will scroll smoothly using + * nsIScrollableFrame::ScrollMode::SMOOTH_MSD; otherwise, + * nsIScrollableFrame::ScrollMode::INSTANT will be used. */ virtual nsresult ScrollContentIntoView(nsIContent* aContent, ScrollAxis aVertical, @@ -690,7 +694,8 @@ public: enum { SCROLL_FIRST_ANCESTOR_ONLY = 0x01, SCROLL_OVERFLOW_HIDDEN = 0x02, - SCROLL_NO_PARENT_FRAMES = 0x04 + SCROLL_NO_PARENT_FRAMES = 0x04, + SCROLL_SMOOTH = 0x08 }; /** * Scrolls the view of the document so that the given area of a frame diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 03610aad425f..161ddcbce01c 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -3519,7 +3519,11 @@ static void ScrollToShowRect(nsIFrame* aFrame, // If we don't need to scroll, then don't try since it might cancel // a current smooth scroll operation. if (needToScroll) { - aFrameAsScrollable->ScrollTo(scrollPt, nsIScrollableFrame::INSTANT, &allowedRange); + nsIScrollableFrame::ScrollMode scrollMode = nsIScrollableFrame::INSTANT; + if (gfxPrefs::ScrollBehaviorEnabled() && aFlags & nsIPresShell::SCROLL_SMOOTH) { + scrollMode = nsIScrollableFrame::SMOOTH_MSD; + } + aFrameAsScrollable->ScrollTo(scrollPt, scrollMode, &allowedRange); } }