Bug 1502566 - When entering fullscreen mode, use the intrinsic resolution rather than a resolution of 1. r=kats a=jcristau
authorBotond Ballo <botond@mozilla.com>
Fri, 02 Nov 2018 21:18:42 +0000
changeset 501058 8219b9f7f288522a3833ee9db4fa40d114833e20
parent 501057 8439e60af323d186aed2a360fa9b27453955fd0d
child 501059 0af5b6b540febc8c5b4cd07904fbf0a2b80f15ea
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, jcristau
bugs1502566
milestone64.0
Bug 1502566 - When entering fullscreen mode, use the intrinsic resolution rather than a resolution of 1. r=kats a=jcristau Differential Revision: https://phabricator.services.mozilla.com/D10754
dom/base/nsDocument.cpp
layout/base/MobileViewportManager.cpp
layout/base/MobileViewportManager.h
layout/base/PresShell.h
layout/base/nsIPresShell.h
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -11168,20 +11168,18 @@ nsIDocument::CleanupFullscreenState()
       ClearFullscreenStateOnElement(element);
     }
   }
   mFullscreenStack.Clear();
   mFullscreenRoot = nullptr;
 
   // Restore the zoom level that was in place prior to entering fullscreen.
   if (nsIPresShell* shell = GetShell()) {
-    if (nsPresContext* context = shell->GetPresContext()) {
-      if (context->IsRootContentDocument()) {
-        shell->SetResolutionAndScaleTo(mSavedResolution);
-      }
+    if (shell->GetMobileViewportManager()) {
+      shell->SetResolutionAndScaleTo(mSavedResolution);
     }
   }
 
   UpdateViewportScrollbarOverrideForFullscreen(this);
 }
 
 bool
 nsIDocument::FullscreenStackPush(Element* aElement)
@@ -11579,29 +11577,27 @@ nsIDocument::ApplyFullscreen(UniquePtr<F
   // the element's container in ancestor documents. This also sets the
   // appropriate css styles as well. Note we don't propagate down the
   // document hierarchy, the fullscreen element (or its container) is not
   // visible there. Stop when we reach the root document.
   nsIDocument* child = this;
   while (true) {
     child->SetFullscreenRoot(fullScreenRootDoc);
 
-    // When entering fullscreen, reset the RCD's zoom level to 1,
-    // otherwise the fullscreen content could be sized larger than the
-    // screen (since fullscreen is implemented using position:fixed and
+    // When entering fullscreen, reset the RCD's resolution to the intrinsic
+    // resolution, otherwise the fullscreen content could be sized larger than
+    // the screen (since fullscreen is implemented using position:fixed and
     // fixed elements are sized to the layout viewport).
     // This also ensures that things like video controls aren't zoomed in
     // when in fullscreen mode.
     if (nsIPresShell* shell = child->GetShell()) {
-      if (nsPresContext* context = shell->GetPresContext()) {
-        if (context->IsRootContentDocument()) {
-          // Save the previous resolution so it can be restored.
-          child->mSavedResolution = shell->GetResolution();
-          shell->SetResolutionAndScaleTo(1.0f);
-        }
+      if (RefPtr<MobileViewportManager> manager = shell->GetMobileViewportManager()) {
+        // Save the previous resolution so it can be restored.
+        child->mSavedResolution = shell->GetResolution();
+        shell->SetResolutionAndScaleTo(manager->ComputeIntrinsicResolution());
       }
     }
 
     NS_ASSERTION(child->GetFullscreenRoot() == fullScreenRootDoc,
         "Fullscreen root should be set!");
     if (child == fullScreenRootDoc) {
       break;
     }
--- a/layout/base/MobileViewportManager.cpp
+++ b/layout/base/MobileViewportManager.cpp
@@ -97,16 +97,39 @@ MobileViewportManager::SetRestoreResolut
 }
 
 void
 MobileViewportManager::SetRestoreResolution(float aResolution)
 {
   mRestoreResolution = Some(aResolution);
 }
 
+float
+MobileViewportManager::ComputeIntrinsicResolution() const
+{
+  ScreenIntSize displaySize = ViewAs<ScreenPixel>(mDisplaySize,
+      PixelCastJustification::LayoutDeviceIsScreenForBounds);
+  CSSToScreenScale intrinsicScale =
+      ComputeIntrinsicScale(mDocument->GetViewportInfo(displaySize),
+                            displaySize, mMobileViewportSize);
+  CSSToLayoutDeviceScale cssToDev =
+      mPresShell->GetPresContext()->CSSToDevPixelScale();
+  return (intrinsicScale / cssToDev).scale;
+}
+
+mozilla::CSSToScreenScale
+MobileViewportManager::ComputeIntrinsicScale(const nsViewportInfo& aViewportInfo,
+                                             const mozilla::ScreenIntSize& aDisplaySize,
+                                             const mozilla::CSSSize& aViewportSize) const
+{
+  CSSToScreenScale intrinsicScale = MaxScaleRatio(ScreenSize(aDisplaySize), aViewportSize);
+  MVM_LOG("%p: Intrinsic computed zoom is %f\n", this, intrinsicScale.scale);
+  return ClampZoom(intrinsicScale, aViewportInfo);
+}
+
 void
 MobileViewportManager::RequestReflow()
 {
   MVM_LOG("%p: got a reflow request\n", this);
   RefreshViewportSize(false);
 }
 
 void
@@ -165,17 +188,17 @@ MobileViewportManager::SetInitialViewpor
   MVM_LOG("%p: setting initial viewport\n", this);
   mIsFirstPaint = true;
   mPainted = true;
   RefreshViewportSize(false);
 }
 
 CSSToScreenScale
 MobileViewportManager::ClampZoom(const CSSToScreenScale& aZoom,
-                                 const nsViewportInfo& aViewportInfo)
+                                 const nsViewportInfo& aViewportInfo) const
 {
   CSSToScreenScale zoom = aZoom;
   if (zoom < aViewportInfo.GetMinZoom()) {
     zoom = aViewportInfo.GetMinZoom();
     MVM_LOG("%p: Clamped to %f\n", this, zoom.scale);
   }
   if (zoom > aViewportInfo.GetMaxZoom()) {
     zoom = aViewportInfo.GetMaxZoom();
@@ -226,19 +249,17 @@ MobileViewportManager::UpdateResolution(
       }
       defaultZoom = CSSToScreenScale(restoreResolution.scale * cssToDev.scale);
       MVM_LOG("%p: restored zoom is %f\n", this, defaultZoom.scale);
       defaultZoom = ClampZoom(defaultZoom, aViewportInfo);
     } else {
       defaultZoom = aViewportInfo.GetDefaultZoom();
       MVM_LOG("%p: default zoom from viewport is %f\n", this, defaultZoom.scale);
       if (!aViewportInfo.IsDefaultZoomValid()) {
-        defaultZoom = MaxScaleRatio(ScreenSize(aDisplaySize), aViewport);
-        MVM_LOG("%p: Intrinsic computed zoom is %f\n", this, defaultZoom.scale);
-        defaultZoom = ClampZoom(defaultZoom, aViewportInfo);
+        defaultZoom = ComputeIntrinsicScale(aViewportInfo, aDisplaySize, aViewport);
       }
     }
     MOZ_ASSERT(aViewportInfo.GetMinZoom() <= defaultZoom &&
       defaultZoom <= aViewportInfo.GetMaxZoom());
 
     CSSToParentLayerScale zoom = ViewTargetAs<ParentLayerPixel>(defaultZoom,
       PixelCastJustification::ScreenIsParentLayerForRoot);
 
--- a/layout/base/MobileViewportManager.h
+++ b/layout/base/MobileViewportManager.h
@@ -39,16 +39,27 @@ public:
    * resolution computed from the viewport info metadata. This is in the same
    * "units" as the argument to nsDOMWindowUtils::SetResolutionAndScaleTo.
    * Also takes the previous display dimensions as they were at the time the
    * resolution was stored in order to correctly adjust the resolution if the
    * device was rotated in the meantime. */
   void SetRestoreResolution(float aResolution,
                             mozilla::LayoutDeviceIntSize aDisplaySize);
 
+  /* Compute the "intrinsic resolution", which is the smallest resolution at
+   * which the layout viewport fills the visual viewport. (In typical
+   * scenarios, where the aspect ratios of the two viewports match, it's the
+   * resolution at which they are the same size.)
+   *
+   * The returned resolution is suitable for passing to
+   * nsIPresShell::SetResolutionAndScaleTo(). It's not in typed units for
+   * reasons explained at the declaration of FrameMetrics::mPresShellResolution.
+   */
+  float ComputeIntrinsicResolution() const;
+
 private:
   void SetRestoreResolution(float aResolution);
 
 public:
   /* Notify the MobileViewportManager that a reflow was requested in the
    * presShell.*/
   void RequestReflow();
 
@@ -68,17 +79,17 @@ public:
    * need updating. */
   void RefreshViewportSize(bool aForceAdjustResolution);
 
   /* Secondary main helper method to update just the visual viewport size. */
   void RefreshVisualViewportSize();
 
   /* Helper to clamp the given zoom by the min/max in the viewport info. */
   mozilla::CSSToScreenScale ClampZoom(const mozilla::CSSToScreenScale& aZoom,
-                                      const nsViewportInfo& aViewportInfo);
+                                      const nsViewportInfo& aViewportInfo) const;
 
   /* Helper to update the given resolution according to changed display and viewport widths. */
   mozilla::LayoutDeviceToLayerScale
   ScaleResolutionWithDisplayWidth(const mozilla::LayoutDeviceToLayerScale& aRes,
                                   const float& aDisplayWidthChangeRatio,
                                   const mozilla::CSSSize& aNewViewport,
                                   const mozilla::CSSSize& aOldViewport);
 
@@ -89,16 +100,21 @@ public:
                                              const mozilla::Maybe<float>& aDisplayWidthChangeRatio);
 
   void UpdateVisualViewportSize(const mozilla::ScreenIntSize& aDisplaySize,
                                 const mozilla::CSSToScreenScale& aZoom);
 
   /* Updates the displayport margins for the presShell's root scrollable frame */
   void UpdateDisplayPortMargins();
 
+  /* Helper function for ComputeIntrinsicResolution(). */
+  mozilla::CSSToScreenScale ComputeIntrinsicScale(const nsViewportInfo& aViewportInfo,
+                                                  const mozilla::ScreenIntSize& aDisplaySize,
+                                                  const mozilla::CSSSize& aViewportSize) const;
+
   nsCOMPtr<nsIDocument> mDocument;
   nsIPresShell* MOZ_NON_OWNING_REF mPresShell; // raw ref since the presShell owns this
   nsCOMPtr<mozilla::dom::EventTarget> mEventTarget;
   bool mIsFirstPaint;
   bool mPainted;
   mozilla::LayoutDeviceIntSize mDisplaySize;
   mozilla::CSSSize mMobileViewportSize;
   mozilla::Maybe<float> mRestoreResolution;
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -339,16 +339,20 @@ public:
   nscolor ComputeBackstopColor(nsView* aDisplayRoot) override;
 
   nsresult SetIsActive(bool aIsActive) override;
 
   bool GetIsViewportOverridden() override {
     return (mMobileViewportManager != nullptr);
   }
 
+  RefPtr<MobileViewportManager> GetMobileViewportManager() const override {
+    return mMobileViewportManager;
+  }
+
   void UpdateViewportOverridden(bool aAfterInitialization) override;
 
   bool IsLayoutFlushObserver() override
   {
     return GetPresContext()->RefreshDriver()->
       IsLayoutFlushObserver(this);
   }
 
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -62,16 +62,17 @@ class StyleSheet;
 } // namespace mozilla
 class nsFrameSelection;
 class nsFrameManager;
 class nsILayoutHistoryState;
 class nsIReflowCallback;
 class nsCSSFrameConstructor;
 template<class E> class nsCOMArray;
 class AutoWeakFrame;
+class MobileViewportManager;
 class WeakFrame;
 class nsIScrollableFrame;
 class nsDisplayList;
 class nsDisplayListBuilder;
 class nsPIDOMWindowOuter;
 struct nsPoint;
 class nsINode;
 struct nsRect;
@@ -373,16 +374,23 @@ public:
 
   /**
    * Note that the assumptions that determine the need for a meta viewport
    * may have changed.
    */
   virtual void UpdateViewportOverridden(bool aAfterInitialization) = 0;
 
   /**
+   * Get the MobileViewportManager used to manage the document's mobile
+   * viewport. Will return null in situations where we don't have a mobile
+   * viewport, and for documents that are not the root content document.
+   */
+  virtual RefPtr<MobileViewportManager> GetMobileViewportManager() const = 0;
+
+  /**
    * Return true if the presshell expects layout flush.
    */
   virtual bool IsLayoutFlushObserver() = 0;
 
   /**
    * Called when document load completes.
    */
   virtual void LoadComplete() = 0;