fune/gfx/layers/FrameMetrics.cpp
Tanushree Podder a468f78119 Bug 1473699 - Async-scroll the layout viewport even if it's smaller than the visual viewport. r=botond
When the layout viewport is smaller than the visual viewport and the user
scrolls a web page, the layout viewport remains fixed to its position before
the scroll event took place. However, the visual viewport moves according to
the new scroll position. This patch addresses this issue by moving the layout
viewport along with the visual viewport.

MozReview-Commit-ID: 3Mk1o6AF2wr

--HG--
extra : rebase_source : 8c6068059593038dc443cb9c96242483de97e9d9
2018-07-22 01:59:37 -04:00

107 lines
3.8 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FrameMetrics.h"
#include "gfxPrefs.h"
#include "nsStyleConsts.h"
namespace mozilla {
namespace layers {
const FrameMetrics::ViewID FrameMetrics::NULL_SCROLL_ID = 0;
void
FrameMetrics::RecalculateViewportOffset()
{
if (!mIsRootContent) {
return;
}
CSSRect visualViewport = GetVisualViewport();
// If the visual viewport is contained within the layout viewport, we don't
// need to make any adjustments, so we can exit early.
//
// Additionally, if the composition bounds changes (due to an orientation
// change, window resize, etc.), it may take a few frames for mViewport to
// update and during that time, the visual viewport may be larger than the
// layout viewport. In such situations, we take an early exit if the visual
// viewport contains the layout viewport.
if (mViewport.Contains(visualViewport) || visualViewport.Contains(mViewport)) {
return;
}
// If visual viewport size is greater than the layout viewport, move the layout
// viewport such that it remains inside the visual viewport. Otherwise,
// move the layout viewport such that the visual viewport is contained
// inside the layout viewport.
if ((mViewport.Width() < visualViewport.Width() &&
!FuzzyEqualsMultiplicative(mViewport.Width(), visualViewport.Width())) ||
(mViewport.Height() < visualViewport.Height() &&
!FuzzyEqualsMultiplicative(mViewport.Height(), visualViewport.Height()))) {
if (mViewport.X() < visualViewport.X()) {
// layout viewport moves right
mViewport.MoveToX(visualViewport.X());
} else if (visualViewport.XMost() < mViewport.XMost()) {
// layout viewport moves left
mViewport.MoveByX(visualViewport.XMost() - mViewport.XMost());
}
if (mViewport.Y() < visualViewport.Y()) {
// layout viewport moves down
mViewport.MoveToY(visualViewport.Y());
} else if (visualViewport.YMost() < mViewport.YMost()) {
// layout viewport moves up
mViewport.MoveByY(visualViewport.YMost() - mViewport.YMost());
}
} else {
if (visualViewport.X() < mViewport.X()) {
mViewport.MoveToX(visualViewport.X());
} else if (mViewport.XMost() < visualViewport.XMost()) {
mViewport.MoveByX(visualViewport.XMost() - mViewport.XMost());
}
if (visualViewport.Y() < mViewport.Y()) {
mViewport.MoveToY(visualViewport.Y());
} else if (mViewport.YMost() < visualViewport.YMost()) {
mViewport.MoveByY(visualViewport.YMost() - mViewport.YMost());
}
}
}
void
ScrollMetadata::SetUsesContainerScrolling(bool aValue) {
MOZ_ASSERT_IF(aValue, gfxPrefs::LayoutUseContainersForRootFrames());
mUsesContainerScrolling = aValue;
}
static OverscrollBehavior
ToOverscrollBehavior(StyleOverscrollBehavior aBehavior)
{
switch (aBehavior) {
case StyleOverscrollBehavior::Auto:
return OverscrollBehavior::Auto;
case StyleOverscrollBehavior::Contain:
return OverscrollBehavior::Contain;
case StyleOverscrollBehavior::None:
return OverscrollBehavior::None;
}
MOZ_ASSERT_UNREACHABLE("Invalid overscroll behavior");
return OverscrollBehavior::Auto;
}
OverscrollBehaviorInfo
OverscrollBehaviorInfo::FromStyleConstants(StyleOverscrollBehavior aBehaviorX,
StyleOverscrollBehavior aBehaviorY)
{
OverscrollBehaviorInfo result;
result.mBehaviorX = ToOverscrollBehavior(aBehaviorX);
result.mBehaviorY = ToOverscrollBehavior(aBehaviorY);
return result;
}
StaticAutoPtr<const ScrollMetadata> ScrollMetadata::sNullMetadata;
}
}