Bug 1525075 - Use the ICB size for Element.{clientWidth, clientHeight} instead of expanded the layout viewport size. r=botond
authorHiroyuki Ikezoe <hikezoe@mozilla.com>
Wed, 13 Feb 2019 23:47:32 +0000
changeset 459072 2ae0011bb82c
parent 459071 43baecd33ce6
child 459073 c6829642e2d0
push id111913
push usershindli@mozilla.com
push dateThu, 14 Feb 2019 05:01:59 +0000
treeherdermozilla-inbound@a0752d7e8073 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbotond
bugs1525075, 1515043
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 1525075 - Use the ICB size for Element.{clientWidth, clientHeight} instead of expanded the layout viewport size. r=botond This is what Chrome does. documentElement-clientWidth-on-minimum-scale-size.tentative.html was the test case for this but unfortunately it was disabled in bug 1515043. And it seems that the test case failed on Android in the first place. Differential Revision: https://phabricator.services.mozilla.com/D19461
dom/base/Element.cpp
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
layout/generic/nsIScrollableFrame.h
testing/web-platform/meta/css/css-device-adapt/documentElement-clientWidth-on-minimum-scale-size.tentative.html.ini
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -972,17 +972,21 @@ int32_t Element::ScrollWidth() {
   return nsPresContext::AppUnitsToIntCSSPixels(width);
 }
 
 nsRect Element::GetClientAreaRect() {
   nsIFrame* frame;
   nsIScrollableFrame* sf = GetScrollFrame(&frame);
 
   if (sf) {
-    return sf->GetScrollPortRect();
+    nsRect scrollPort = sf->GetScrollPortRect();
+    // The scroll port value might be expanded to the minimum scale size, we
+    // should limit the size to the ICB in such cases.
+    scrollPort.SizeTo(sf->GetLayoutSize());
+    return scrollPort;
   }
 
   if (frame &&
       // The display check is OK even though we're not looking at the style
       // frame, because the style frame only differs from "frame" for tables,
       // and table wrappers have the same display as the table itself.
       (frame->StyleDisplay()->mDisplay != StyleDisplay::Inline ||
        frame->IsFrameOfType(nsIFrame::eReplaced))) {
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -375,19 +375,24 @@ bool nsHTMLScrollFrame::TryLayout(Scroll
       std::max(aKidMetrics->Height(), vScrollbarMinHeight);
   aState->mInsideBorderSize =
       ComputeInsideBorderSize(aState, desiredInsideBorderSize);
 
   nsSize layoutSize = mHelper.mIsUsingMinimumScaleSize
                           ? mHelper.mMinimumScaleSize
                           : aState->mInsideBorderSize;
 
-  nsSize scrollPortSize =
+  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));
+  }
 
   nsSize visualViewportSize = scrollPortSize;
   nsIPresShell* presShell = PresShell();
   if (mHelper.mIsRoot && presShell->IsVisualViewportSizeSet()) {
     nsSize compositionSize =
         nsLayoutUtils::CalculateCompositionSizeForFrame(this, false);
     float resolution = presShell->GetResolution();
     compositionSize.width /= resolution;
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -190,16 +190,22 @@ class ScrollFrameHelper : public nsIRefl
                             nscoord* aRangeLength);
 
   /**
    * @note This method might destroy the frame, pres shell and other objects.
    * Update scrollbar curpos attributes to reflect current scroll position
    */
   void UpdateScrollbarPosition();
 
+  nsSize GetLayoutSize() const {
+    if (mIsUsingMinimumScaleSize) {
+      return mICBSize;
+    }
+    return mScrollPort.Size();
+  }
   nsRect GetScrollPortRect() const { return mScrollPort; }
   nsPoint GetScrollPosition() const {
     return mScrollPort.TopLeft() - mScrolledFrame->GetPosition();
   }
   /**
    * For LTR frames, the logical scroll position is the offset of the top left
    * corner of the frame from the top left corner of the scroll port (same as
    * GetScrollPosition).
@@ -558,16 +564,20 @@ class ScrollFrameHelper : public nsIRefl
   nsAtom* mLastSmoothScrollOrigin;
   Maybe<nsPoint> mApzSmoothScrollDestination;
   uint32_t mScrollGeneration;
   // NOTE: On mobile this value might be factoring into overflow:hidden region
   // in the case of the top level document.
   nsRect mScrollPort;
   nsSize mMinimumScaleSize;
 
+  // Stores the ICB size for the root document if this frame is using the
+  // minimum scale size for |mScrollPort|.
+  nsSize mICBSize;
+
   // Where we're currently scrolling to, if we're scrolling asynchronously.
   // If we're not in the middle of an asynchronous scroll then this is
   // just the current scroll position. ScrollBy will choose its
   // destination based on this value.
   nsPoint mDestination;
 
   // A goal position to try to scroll to as content loads. As long as mLastPos
   // matches the current logical scroll position, we try to scroll to
@@ -883,16 +893,19 @@ class nsHTMLScrollFrame : public nsConta
     return GetDesiredScrollbarSizes(&bls);
   }
   virtual nscoord GetNondisappearingScrollbarWidth(
       nsPresContext* aPresContext, gfxContext* aRC,
       mozilla::WritingMode aWM) override {
     nsBoxLayoutState bls(aPresContext, aRC, 0);
     return mHelper.GetNondisappearingScrollbarWidth(&bls, aWM);
   }
+  virtual nsSize GetLayoutSize() const override {
+    return mHelper.GetLayoutSize();
+  }
   virtual nsRect GetScrolledRect() const override {
     return mHelper.GetScrolledRect();
   }
   virtual nsRect GetScrollPortRect() const override {
     return mHelper.GetScrollPortRect();
   }
   virtual nsPoint GetScrollPosition() const override {
     return mHelper.GetScrollPosition();
@@ -1357,16 +1370,19 @@ class nsXULScrollFrame final : public ns
     return GetDesiredScrollbarSizes(&bls);
   }
   virtual nscoord GetNondisappearingScrollbarWidth(
       nsPresContext* aPresContext, gfxContext* aRC,
       mozilla::WritingMode aWM) override {
     nsBoxLayoutState bls(aPresContext, aRC, 0);
     return mHelper.GetNondisappearingScrollbarWidth(&bls, aWM);
   }
+  virtual nsSize GetLayoutSize() const override {
+    return mHelper.GetLayoutSize();
+  }
   virtual nsRect GetScrolledRect() const override {
     return mHelper.GetScrolledRect();
   }
   virtual nsRect GetScrollPortRect() const override {
     return mHelper.GetScrollPortRect();
   }
   virtual nsPoint GetScrollPosition() const override {
     return mHelper.GetScrollPosition();
--- a/layout/generic/nsIScrollableFrame.h
+++ b/layout/generic/nsIScrollableFrame.h
@@ -106,16 +106,25 @@ class nsIScrollableFrame : public nsIScr
                                             gfxContext* aRC) = 0;
   /**
    * Return the width for non-disappearing scrollbars.
    */
   virtual nscoord GetNondisappearingScrollbarWidth(
       nsPresContext* aPresContext, gfxContext* aRC,
       mozilla::WritingMode aWM) = 0;
   /**
+   * Get the layout size of this frame.
+   * Note that this is a value which is not expanded by the minimum scale size.
+   * For scroll frames other than the root content document's scroll frame, this
+   * value will be the same as GetScrollPortRect().Size().
+   *
+   * This value is used for Element.clientWidth and clientHeight.
+   */
+  virtual nsSize GetLayoutSize() const = 0;
+  /**
    * GetScrolledRect is designed to encapsulate deciding which
    * directions of overflow should be reachable by scrolling and which
    * should not.  Callers should NOT depend on it having any particular
    * behavior (although nsXULScrollFrame currently does).
    *
    * This should only be called when the scrolled frame has been
    * reflowed with the scroll port size given in mScrollPort.
    *
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-device-adapt/documentElement-clientWidth-on-minimum-scale-size.tentative.html.ini
+++ /dev/null
@@ -1,5 +0,0 @@
-[documentElement-clientWidth-on-minimum-scale-size.tentative.html]
-  [documentElement clientWidth should be equal to device-width even if overflow:hidden region is visible]
-    expected:
-      if (os == "android"): FAIL
-