Bug 1290420 Part 4: Make the PresShell create a MobileViewportManager on demand. r=botond,smaug
authorBrad Werth <bwerth@mozilla.com>
Thu, 04 Oct 2018 03:28:40 +0000
changeset 495379 e6cfd555f0d1d013d3c9c5f519f96889c2994609
parent 495378 c23a9b7119c4fa8a66a09aa56579db8369244ad2
child 495380 3acd60dbb363995157c4825cd2896158028008e6
push id9984
push userffxbld-merge
push dateMon, 15 Oct 2018 21:07:35 +0000
treeherdermozilla-beta@183d27ea8570 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond, smaug
bugs1290420
milestone64.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 1290420 Part 4: Make the PresShell create a MobileViewportManager on demand. r=botond,smaug Depends on D3376 Differential Revision: https://phabricator.services.mozilla.com/D3377
docshell/base/nsDocShell.cpp
layout/base/MobileViewportManager.h
layout/base/PresShell.cpp
layout/base/PresShell.h
layout/base/nsIPresShell.h
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -2664,16 +2664,23 @@ nsDocShell::SetMetaViewportOverride(uint
   if (!(aMetaViewportOverride == nsIDocShell::META_VIEWPORT_OVERRIDE_NONE ||
         aMetaViewportOverride == nsIDocShell::META_VIEWPORT_OVERRIDE_ENABLED ||
         aMetaViewportOverride == nsIDocShell::META_VIEWPORT_OVERRIDE_DISABLED)) {
     return NS_ERROR_INVALID_ARG;
   }
 
   mMetaViewportOverride = aMetaViewportOverride;
 
+  // Inform our presShell that it needs to re-check its need for a viewport
+  // override.
+  nsCOMPtr<nsIPresShell> presShell = GetPresShell();
+  if (presShell) {
+    presShell->UpdateViewportOverridden(true);
+  }
+
   return NS_OK;
 }
 
 /* virtual */ int32_t
 nsDocShell::ItemType()
 {
   return mItemType;
 }
--- a/layout/base/MobileViewportManager.h
+++ b/layout/base/MobileViewportManager.h
@@ -51,22 +51,23 @@ public:
   /* Notify the MobileViewportManager that a reflow was requested in the
    * presShell.*/
   void RequestReflow();
 
   /* Notify the MobileViewportManager that the resolution on the presShell was
    * updated, and the visual viewport size needs to be updated. */
   void ResolutionUpdated();
 
-private:
-  ~MobileViewportManager();
+  /* Called to compute the initial viewport on page load or before-first-paint,
+   * whichever happens first. Also called directly if we are created after the
+   * presShell is initialized. */
+  void SetInitialViewport();
 
-  /* Called to compute the initial viewport on page load or before-first-paint,
-   * whichever happens first. */
-  void SetInitialViewport();
+  private:
+  ~MobileViewportManager();
 
   /* Main helper method to update the CSS viewport and any other properties that
    * need updating. */
   void RefreshViewportSize(bool aForceAdjustResolution);
 
   /* Secondary main helper method to update just the visual viewport size. */
   void RefreshVisualViewportSize();
 
--- a/layout/base/PresShell.cpp
+++ b/layout/base/PresShell.cpp
@@ -1040,19 +1040,19 @@ PresShell::Init(nsIDocument* aDocument,
   // We'll compute the font size inflation state in Initialize(), when we know
   // the document type.
 
   mTouchManager.Init(this, mDocument);
 
   if (mPresContext->IsRootContentDocument()) {
     mZoomConstraintsClient = new ZoomConstraintsClient();
     mZoomConstraintsClient->Init(this, mDocument);
-    if (nsLayoutUtils::ShouldHandleMetaViewport(mDocument) || gfxPrefs::APZAllowZooming()) {
-      mMobileViewportManager = new MobileViewportManager(this, mDocument);
-    }
+
+    // We call this to create mMobileViewportManager, if it is needed.
+    UpdateViewportOverridden(false);
   }
 }
 
 enum TextPerfLogType {
   eLog_reflow,
   eLog_loaddone,
   eLog_totals
 };
@@ -10500,16 +10500,59 @@ PresShell::SetIsActive(bool aIsActive)
     if (accService) {
       accService->PresShellActivated(this);
     }
   }
 #endif
   return rv;
 }
 
+void
+PresShell::UpdateViewportOverridden(bool aAfterInitialization)
+{
+  // Determine if we require a MobileViewportManager.
+  bool needMVM = nsLayoutUtils::ShouldHandleMetaViewport(mDocument) ||
+                 gfxPrefs::APZAllowZooming();
+
+  if (needMVM == !!mMobileViewportManager) {
+    // Either we've need one and we've already got it, or we don't need one
+    // and don't have it. Either way, we're done.
+    return;
+  }
+
+  if (needMVM) {
+    if (mPresContext->IsRootContentDocument()) {
+      mMobileViewportManager = new MobileViewportManager(this, mDocument);
+
+      if (aAfterInitialization) {
+        // Setting the initial viewport will trigger a reflow.
+        mMobileViewportManager->SetInitialViewport();
+      }
+    }
+    return;
+  }
+
+  MOZ_ASSERT(mMobileViewportManager, "Shouldn't reach this without a "
+                                     "MobileViewportManager.");
+  mMobileViewportManager->Destroy();
+  mMobileViewportManager = nullptr;
+
+  if (aAfterInitialization) {
+    // Force a reflow to our correct size by going back to the docShell
+    // and asking it to reassert its size. This is necessary because
+    // everything underneath the docShell, like the ViewManager, has been
+    // altered by the MobileViewportManager in an irreversible way.
+    nsDocShell* docShell =
+      static_cast<nsDocShell*>(GetPresContext()->GetDocShell());
+    int32_t width, height;
+    docShell->GetSize(&width, &height);
+    docShell->SetSize(width, height, false);
+  }
+}
+
 /*
  * Determines the current image locking state. Called when one of the
  * dependent factors changes.
  */
 nsresult
 PresShell::UpdateImageLockingState()
 {
   // We're locked if we're both thawed and active.
--- a/layout/base/PresShell.h
+++ b/layout/base/PresShell.h
@@ -340,16 +340,18 @@ public:
   nscolor ComputeBackstopColor(nsView* aDisplayRoot) override;
 
   nsresult SetIsActive(bool aIsActive) override;
 
   bool GetIsViewportOverridden() override {
     return (mMobileViewportManager != nullptr);
   }
 
+  void UpdateViewportOverridden(bool aAfterInitialization) override;
+
   bool IsLayoutFlushObserver() override
   {
     return GetPresContext()->RefreshDriver()->
       IsLayoutFlushObserver(this);
   }
 
   void LoadComplete() override;
 
--- a/layout/base/nsIPresShell.h
+++ b/layout/base/nsIPresShell.h
@@ -361,21 +361,27 @@ public:
    */
   virtual nsresult ResizeReflowIgnoreOverride(
                      nscoord aWidth, nscoord aHeight,
                      nscoord aOldWidth, nscoord aOldHeight,
                      ResizeReflowOptions aOptions =
                        ResizeReflowOptions::eBSizeExact) = 0;
 
   /**
-   * Returns true if ResizeReflowOverride has been called.
+   * Returns true if the platform/pref or docshell require a meta viewport.
    */
   virtual bool GetIsViewportOverridden() = 0;
 
   /**
+   * Note that the assumptions that determine the need for a meta viewport
+   * may have changed.
+   */
+  virtual void UpdateViewportOverridden(bool aAfterInitialization) = 0;
+
+  /**
    * Return true if the presshell expects layout flush.
    */
   virtual bool IsLayoutFlushObserver() = 0;
 
   /**
    * Called when document load completes.
    */
   virtual void LoadComplete() = 0;