Bug 1509575 - Extend the internal visual scroll API to allow specifying "restore" vs. regular priority. r=kats

The distinction is not exposed at the JS level which currently always uses
"restore", but it could be if necessary.

Differential Revision: https://phabricator.services.mozilla.com/D16346

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Botond Ballo 2019-01-15 01:30:43 +00:00
Родитель d5f06efae5
Коммит e99815f1f0
4 изменённых файлов: 55 добавлений и 29 удалений

Просмотреть файл

@ -1406,8 +1406,12 @@ nsDOMWindowUtils::ScrollToVisual(float aOffsetX, float aOffsetY) {
// This should only be called on the root content document.
NS_ENSURE_TRUE(presContext->IsRootContentDocument(), NS_ERROR_INVALID_ARG);
presContext->PresShell()->SetPendingVisualViewportOffset(
Some(CSSPoint::ToAppUnits(CSSPoint(aOffsetX, aOffsetY))));
// Use |eRestore| as the priority for now, as it's the conservative choice.
// If a JS call site needs higher priority, we can expose the update type
// as a parameter.
presContext->PresShell()->SetPendingVisualScrollUpdate(
CSSPoint::ToAppUnits(CSSPoint(aOffsetX, aOffsetY)),
FrameMetrics::eRestore);
return NS_OK;
}

Просмотреть файл

@ -4262,8 +4262,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(
(aLayerMetrics.GetScrollGeneration() != Metrics().GetScrollGeneration());
if (scrollOffsetUpdated && userScrolled &&
aLayerMetrics.GetScrollUpdateType() ==
FrameMetrics::ScrollOffsetUpdateType::eRestore) {
aLayerMetrics.GetScrollUpdateType() == FrameMetrics::eRestore) {
APZC_LOG(
"%p dropping scroll update of type eRestore because of user scroll\n",
this);
@ -4274,6 +4273,23 @@ void AsyncPanZoomController::NotifyLayersUpdated(
aLayerMetrics.GetDoSmoothScroll() &&
(aLayerMetrics.GetScrollGeneration() != Metrics().GetScrollGeneration());
// The main thread may also ask us to scroll the visual viewport to a
// particular location. This is different from a layout viewport offset update
// in that the layout viewport offset is limited to the layout scroll range
// (this will be enforced by the main thread once bug 1516056 is fixed),
// while the visual viewport offset is not.
// The update type indicates the priority; an eMainThread layout update (or
// a smooth scroll request which is similar) takes precedence over an eRestore
// visual update, but we allow the possibility for the main thread to ask us
// to scroll both the layout and visual viewports to distinct (but compatible)
// locations (via e.g. both updates being eRestore).
bool visualScrollOffsetUpdated =
aLayerMetrics.GetVisualScrollUpdateType() != FrameMetrics::eNone;
if (aLayerMetrics.GetScrollUpdateType() == FrameMetrics::eMainThread ||
smoothScrollRequested) {
visualScrollOffsetUpdated = false;
}
// TODO if we're in a drag and scrollOffsetUpdated is set then we want to
// ignore it
@ -4500,18 +4516,7 @@ void AsyncPanZoomController::NotifyLayersUpdated(
SmoothScrollTo(Metrics().GetSmoothScrollOffset());
}
// If the main thread asked us to scroll the visual viewport to a particular
// location, do so. This is different from a layout viewport offset update
// in that the layout viewport offset is limited to the layout scroll range
// (this will be enforced by the main thread once bug 1516056 is fixed),
// while the visual viewport offset is not. The main thread can also ask
// us to scroll both the layout and visual viewports to distinct (but
// compatible) locations.
FrameMetrics::ScrollOffsetUpdateType visualUpdateType =
aLayerMetrics.GetVisualScrollUpdateType();
MOZ_ASSERT(visualUpdateType == FrameMetrics::eNone ||
visualUpdateType == FrameMetrics::eMainThread);
if (visualUpdateType == FrameMetrics::eMainThread) {
if (visualScrollOffsetUpdated) {
Metrics().ClampAndSetScrollOffset(aLayerMetrics.GetVisualViewportOffset());
// The rest of this branch largely follows the code in the

Просмотреть файл

@ -18,6 +18,7 @@
#include "mozilla/StyleSheet.h"
#include "mozilla/UniquePtr.h"
#include "mozilla/WeakPtr.h"
#include "FrameMetrics.h"
#include "GeckoProfiler.h"
#include "gfxPoint.h"
#include "nsTHashtable.h"
@ -176,6 +177,7 @@ class nsIPresShell : public nsStubDocumentObserver {
protected:
typedef mozilla::dom::Document Document;
typedef mozilla::layers::FrameMetrics FrameMetrics;
typedef mozilla::layers::LayerManager LayerManager;
typedef mozilla::gfx::SourceSurface SourceSurface;
@ -1660,18 +1662,32 @@ class nsIPresShell : public nsStubDocumentObserver {
nsPoint GetVisualViewportOffsetRelativeToLayoutViewport() const;
// Ask APZ in the next transaction to scroll to the given visual viewport
// Represents an update to the visual scroll offset that will be sent to APZ.
// The update type is used to determine priority compared to other scroll
// updates.
struct VisualScrollUpdate {
nsPoint mVisualScrollOffset;
FrameMetrics::ScrollOffsetUpdateType mUpdateType;
};
// Ask APZ in the next transaction to scroll to the given visual viewport
// offset (relative to the document).
// Use this sparingly, as it will clobber JS-driven scrolling that happens
// in the same frame. This is mostly intended to be used in special
// situations like "first paint" or session restore.
// Please request APZ review if adding a new call site.
void SetPendingVisualViewportOffset(
const mozilla::Maybe<nsPoint>& aPendingVisualViewportOffset) {
mPendingVisualViewportOffset = aPendingVisualViewportOffset;
void SetPendingVisualScrollUpdate(
const nsPoint& aVisualViewportOffset,
FrameMetrics::ScrollOffsetUpdateType aUpdateType) {
mPendingVisualScrollUpdate =
mozilla::Some(VisualScrollUpdate{aVisualViewportOffset, aUpdateType});
}
const mozilla::Maybe<nsPoint>& GetPendingVisualViewportOffset() const {
return mPendingVisualViewportOffset;
void ClearPendingVisualScrollUpdate() {
mPendingVisualScrollUpdate = mozilla::Nothing();
}
const mozilla::Maybe<VisualScrollUpdate>& GetPendingVisualScrollUpdate()
const {
return mPendingVisualScrollUpdate;
}
nsPoint GetLayoutViewportOffset() const;
@ -1755,10 +1771,10 @@ class nsIPresShell : public nsStubDocumentObserver {
nsPoint mVisualViewportOffset;
// A pending visual viewport offset that we will ask APZ to scroll to
// A pending visual scroll offset that we will ask APZ to scroll to
// during the next transaction. Cleared when we send the transaction.
// Only applicable to the RCD pres shell.
mozilla::Maybe<nsPoint> mPendingVisualViewportOffset;
mozilla::Maybe<VisualScrollUpdate> mPendingVisualScrollUpdate;
// A list of stack weak frames. This is a pointer to the last item in the
// list.

Просмотреть файл

@ -8708,11 +8708,12 @@ static void MaybeReflowForInflationScreenSizeChange(
metrics.SetBaseScrollOffset(apzScrollPosition);
if (aIsRootContent) {
if (const Maybe<nsPoint>& visualOffset =
presShell->GetPendingVisualViewportOffset()) {
metrics.SetVisualViewportOffset(CSSPoint::FromAppUnits(*visualOffset));
metrics.SetVisualScrollUpdateType(FrameMetrics::eMainThread);
presShell->SetPendingVisualViewportOffset(Nothing());
if (const Maybe<nsIPresShell::VisualScrollUpdate>& visualUpdate =
presShell->GetPendingVisualScrollUpdate()) {
metrics.SetVisualViewportOffset(
CSSPoint::FromAppUnits(visualUpdate->mVisualScrollOffset));
metrics.SetVisualScrollUpdateType(visualUpdate->mUpdateType);
presShell->ClearPendingVisualScrollUpdate();
}
}