Bug 1525948 - Ensure the layout viewport retains the aspect ratio of the visual viewport. r=hiro
authorBotond Ballo <botond@mozilla.com>
Sat, 16 Feb 2019 01:37:47 +0000
changeset 459691 d3ca8862f6ff
parent 459690 cd5ad8016bd5
child 459692 bf8ca7933ead
push id35565
push userncsoregi@mozilla.com
push dateSat, 16 Feb 2019 21:45:13 +0000
treeherdermozilla-central@bf8ca7933ead [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1525948
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1525948 - Ensure the layout viewport retains the aspect ratio of the visual viewport. r=hiro Differential Revision: https://phabricator.services.mozilla.com/D19996
layout/generic/nsGfxScrollFrame.cpp
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -379,19 +379,20 @@ bool nsHTMLScrollFrame::TryLayout(Scroll
   nsSize layoutSize = mHelper.mIsUsingMinimumScaleSize
                           ? mHelper.mMinimumScaleSize
                           : aState->mInsideBorderSize;
 
   const nsSize scrollPortSize =
       nsSize(std::max(0, layoutSize.width - vScrollbarDesiredWidth),
              std::max(0, layoutSize.height - hScrollbarDesiredHeight));
   if (mHelper.mIsUsingMinimumScaleSize) {
-    mHelper.mICBSize =
-        nsSize(std::max(0, aState->mInsideBorderSize.width - vScrollbarDesiredWidth),
-               std::max(0, aState->mInsideBorderSize.height - hScrollbarDesiredHeight));
+    mHelper.mICBSize = nsSize(
+        std::max(0, aState->mInsideBorderSize.width - vScrollbarDesiredWidth),
+        std::max(0,
+                 aState->mInsideBorderSize.height - hScrollbarDesiredHeight));
   }
 
   nsSize visualViewportSize = scrollPortSize;
   nsIPresShell* presShell = PresShell();
   if (mHelper.mIsRoot && presShell->IsVisualViewportSizeSet()) {
     nsSize compositionSize =
         nsLayoutUtils::CalculateCompositionSizeForFrame(this, false);
     float resolution = presShell->GetResolution();
@@ -5568,31 +5569,45 @@ void ScrollFrameHelper::UpdateMinimumSca
   MOZ_ASSERT(doc, "The document should be valid");
   if (doc->GetFullscreenElement()) {
     // Don't use the minimum scale size in the case of fullscreen state.
     // FIXME: 1508177: We will no longer need this.
     return;
   }
 
   nsViewportInfo viewportInfo = doc->GetViewportInfo(displaySize);
-  nsSize maximumPossibleSize =
-      CSSSize::ToAppUnits(ScreenSize(displaySize) / viewportInfo.GetMinZoom());
-
-  mMinimumScaleSize =
-      Min(maximumPossibleSize,
-          nsSize(aScrollableOverflow.XMost(), aScrollableOverflow.YMost()));
-  mMinimumScaleSize = Max(aICBSize, mMinimumScaleSize);
-
-  // Chrome doesn't allow overflow-y:hidden region reachable if there is no
-  // overflow-x:hidden region.
+
+  // The intrinsic minimum scale is the scale that fits the entire content
+  // width into the visual viewport.
+  CSSToScreenScale intrinsicMinScale(
+      displaySize.width / CSSRect::FromAppUnits(aScrollableOverflow).XMost());
+
+  // The scale used to compute the minimum-scale size is the larger of the
+  // intrinsic minimum and the min-scale from the meta viewport tag.
+  CSSToScreenScale minScale =
+      std::max(intrinsicMinScale, viewportInfo.GetMinZoom());
+
+  // The minimum-scale size is the size of the visual viewport when zoomed
+  // to be the minimum scale.
+  mMinimumScaleSize = CSSSize::ToAppUnits(ScreenSize(displaySize) / minScale);
+
+  // Clamp the min-scale size so it's not taller than the content height.
   // TODO: Bug 1508177: We can drop this condition once after we shrink the
   // content even if no content area gets visible.
-  if (mMinimumScaleSize.width != aICBSize.width) {
-    mIsUsingMinimumScaleSize = true;
-  }
+  mMinimumScaleSize =
+      Min(mMinimumScaleSize,
+          nsSize(aScrollableOverflow.XMost(), aScrollableOverflow.YMost()));
+
+  // Ensure the minimum-scale size is never smaller than the ICB size.
+  // That could happen if a page has a meta viewport tag with large explicitly
+  // specified viewport dimensions (making the ICB large) and also a large
+  // minimum scale (making the min-scale size small).
+  mMinimumScaleSize = Max(aICBSize, mMinimumScaleSize);
+
+  mIsUsingMinimumScaleSize = true;
 }
 
 bool ScrollFrameHelper::ReflowFinished() {
   mPostedReflowCallback = false;
 
   bool doScroll = true;
   if (NS_SUBTREE_DIRTY(mOuter)) {
     // We will get another call after the next reflow and scrolling