Bug 1465616 - Use the larger viewport to layout and size fixed position elements. r=mstange draft
authorKashav Madan <kshvmdn@gmail.com>
Wed, 04 Jul 2018 16:10:04 -0400
changeset 829034 2a2ec4983e2ec7f69a3c18389661e00e47ac5277
parent 829033 48a45df79f328c88f0ffe0d2aeeb7d78c007d86b
child 829035 f603a690566bfe607cfc2c36bb5c9853a8e85bab
child 829041 ba75dd9d47998a01759b3c73a9f5666582e82ff3
child 829378 0d3d11b395c1924b26bb597cf74e9fc7345dbf44
child 830108 96b62222a107300fb80e435e813b8c72f8c0ad07
push id118741
push userbmo:kshvmdn@gmail.com
push dateTue, 14 Aug 2018 18:31:47 +0000
reviewersmstange
bugs1465616
milestone63.0a1
Bug 1465616 - Use the larger viewport to layout and size fixed position elements. r=mstange Since fixed position elements are now scrollable, we need to ensure that they're drawn into the viewport that they're attached to. MozReview-Commit-ID: ADQXkLjwIzR
layout/generic/ViewportFrame.cpp
layout/painting/nsDisplayList.h
--- a/layout/generic/ViewportFrame.cpp
+++ b/layout/generic/ViewportFrame.cpp
@@ -276,24 +276,24 @@ ViewportFrame::AdjustReflowInputAsContai
 #endif
     AdjustReflowInputForScrollbars(aReflowInput);
 
   NS_ASSERTION(GetAbsoluteContainingBlock()->GetChildList().IsEmpty() ||
                (offset.x == 0 && offset.y == 0),
                "We don't handle correct positioning of fixed frames with "
                "scrollbars in odd positions");
 
-  // If a scroll position clamping viewport size has been set, layout
-  // fixed position elements to this size instead of the computed size.
+  // Layout fixed position elements to the visual viewport size if and only if
+  // it has been set and it is larger than the computed size, otherwise use the
+  // computed size.
   nsRect rect(0, 0, aReflowInput->ComputedWidth(), aReflowInput->ComputedHeight());
   nsIPresShell* ps = PresShell();
-  if (ps->IsVisualViewportSizeSet()) {
+  if (ps->IsVisualViewportSizeSet() && rect.Size() < ps->GetVisualViewportSize()) {
     rect.SizeTo(ps->GetVisualViewportSize());
   }
-
   return rect;
 }
 
 void
 ViewportFrame::Reflow(nsPresContext*           aPresContext,
                       ReflowOutput&     aDesiredSize,
                       const ReflowInput& aReflowInput,
                       nsReflowStatus&          aStatus)
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -1469,33 +1469,35 @@ public:
     static nsRect ComputeVisibleRectForFrame(nsDisplayListBuilder* aBuilder,
                                              nsIFrame* aFrame,
                                              const nsRect& aVisibleRect,
                                              const nsRect& aDirtyRect,
                                              nsRect* aOutDirtyRect) {
       nsRect visible = aVisibleRect;
       nsRect dirtyRectRelativeToDirtyFrame = aDirtyRect;
 
-      if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
-          aBuilder->IsPaintingToWindow()) {
-        // position: fixed items are reflowed into and only drawn inside the
-        // viewport, or the visual viewport size, if one is set.
-        nsIPresShell* ps = aFrame->PresShell();
-        if (ps->IsVisualViewportSizeSet()) {
-          dirtyRectRelativeToDirtyFrame =
-            nsRect(nsPoint(0, 0), ps->GetVisualViewportSize());
-          visible = dirtyRectRelativeToDirtyFrame;
 #ifdef MOZ_WIDGET_ANDROID
-        } else {
-          dirtyRectRelativeToDirtyFrame =
-            nsRect(nsPoint(0, 0), aFrame->GetParent()->GetSize());
-          visible = dirtyRectRelativeToDirtyFrame;
+        if (nsLayoutUtils::IsFixedPosFrameInDisplayPort(aFrame) &&
+            aBuilder->IsPaintingToWindow()) {
+            // We want to ensure that fixed position elements are visible when
+            // being async scrolled, so we paint them at the size of the larger
+            // viewport.
+            dirtyRectRelativeToDirtyFrame =
+              nsRect(nsPoint(0, 0), aFrame->GetParent()->GetSize());
+
+            nsIPresShell* ps = aFrame->PresShell();
+            if (ps->IsVisualViewportSizeSet() &&
+                dirtyRectRelativeToDirtyFrame.Size() < ps->GetVisualViewportSize()) {
+                dirtyRectRelativeToDirtyFrame.SizeTo(ps->GetVisualViewportSize());
+            }
+
+            visible = dirtyRectRelativeToDirtyFrame;
+        }
 #endif
-        }
-      }
+
       *aOutDirtyRect = dirtyRectRelativeToDirtyFrame - aFrame->GetPosition();
       visible -= aFrame->GetPosition();
 
       nsRect overflowRect = aFrame->GetVisualOverflowRect();
 
       if (aFrame->IsTransformed() &&
           mozilla::EffectCompositor::HasAnimationsForCompositor(aFrame,
                                                                 eCSSProperty_transform)) {