Set the position of the childRect in nsXULScrollFrame::LayoutScrollArea before calling Layout. Bug 632379, r=dbaron, a=blocker
authorSimon Montagu <smontagu@smontagu.org>
Sun, 13 Feb 2011 08:38:29 +0200
changeset 62492 51702867d932550a0e6a50a07edf94d1ca6c7fd6
parent 62491 d05be9356e44a489c06cbba4d338ac852fd455dd
child 62493 bf5e32270935848f52e03938b68d6642704396e4
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron, blocker
bugs632379
milestone2.0b12pre
first release with
nightly linux32
51702867d932 / 4.0b12pre / 20110213030344 / files
nightly linux64
51702867d932 / 4.0b12pre / 20110213030344 / files
nightly mac
51702867d932 / 4.0b12pre / 20110213030344 / files
nightly win32
51702867d932 / 4.0b12pre / 20110213030344 / files
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
Set the position of the childRect in nsXULScrollFrame::LayoutScrollArea before calling Layout. Bug 632379, r=dbaron, a=blocker
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -2633,69 +2633,49 @@ nsXULScrollFrame::AddRemoveScrollbar(PRB
    return PR_FALSE;
 }
 
 void
 nsXULScrollFrame::LayoutScrollArea(nsBoxLayoutState& aState,
                                    const nsPoint& aScrollPosition)
 {
   PRUint32 oldflags = aState.LayoutFlags();
-  nsRect childRect = nsRect(nsPoint(0, 0),
+  nsRect childRect = nsRect(mInner.mScrollPort.TopLeft() - aScrollPosition,
                             mInner.mScrollPort.Size());
   PRInt32 flags = NS_FRAME_NO_MOVE_VIEW;
 
   nsRect originalRect = mInner.mScrolledFrame->GetRect();
   nsRect originalVisOverflow = mInner.mScrolledFrame->GetVisualOverflowRect();
 
   nsSize minSize = mInner.mScrolledFrame->GetMinSize(aState);
   
   if (minSize.height > childRect.height)
     childRect.height = minSize.height;
   
   if (minSize.width > childRect.width)
     childRect.width = minSize.width;
 
   aState.SetLayoutFlags(flags);
-  mInner.mScrolledFrame->SetBounds(aState, childRect);
+  ClampAndSetBounds(aState, childRect, aScrollPosition);
   mInner.mScrolledFrame->Layout(aState);
 
   childRect = mInner.mScrolledFrame->GetRect();
 
   if (childRect.width < mInner.mScrollPort.width ||
       childRect.height < mInner.mScrollPort.height)
   {
     childRect.width = NS_MAX(childRect.width, mInner.mScrollPort.width);
     childRect.height = NS_MAX(childRect.height, mInner.mScrollPort.height);
 
     // remove overflow areas when we update the bounds,
     // because we've already accounted for it
     // REVIEW: Have we accounted for both?
-    mInner.mScrolledFrame->SetBounds(aState, childRect, PR_TRUE);
+    ClampAndSetBounds(aState, childRect, aScrollPosition, PR_TRUE);
   }
 
-  /*
-   * After layout, restore the original position of the frame relative to the
-   * scroll port.
-   *
-   * In the LTR case, restore the original physical position (top left).
-   *
-   * In the RTL case, restore the original logical position (top right), then
-   * subtract the current width to find the physical position.
-   * This can break the invariant that the scroll position is a multiple of
-   * device pixels, so round off the result to the nearest device pixel.
-   */
-  if (mInner.IsLTR())
-    childRect.x = mInner.mScrollPort.x - aScrollPosition.x;
-  else {
-    childRect.x = PresContext()->RoundAppUnitsToNearestDevPixels(
-             mInner.mScrollPort.XMost() - aScrollPosition.x - childRect.width);
-  }
-  childRect.y = mInner.mScrollPort.y - aScrollPosition.y;
-  mInner.mScrolledFrame->SetBounds(aState, childRect);
-
   nsRect finalRect = mInner.mScrolledFrame->GetRect();
   nsRect finalVisOverflow = mInner.mScrolledFrame->GetVisualOverflowRect();
   // The position of the scrolled frame shouldn't change, but if it does or
   // the position of the overflow rect changes just invalidate both the old
   // and new overflow rect.
   if (originalRect.TopLeft() != finalRect.TopLeft() ||
       originalVisOverflow.TopLeft() != finalVisOverflow.TopLeft())
   {
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -753,14 +753,31 @@ public:
 #ifdef NS_DEBUG
   NS_IMETHOD GetFrameName(nsAString& aResult) const;
 #endif
 
 protected:
   nsXULScrollFrame(nsIPresShell* aShell, nsStyleContext* aContext, PRBool aIsRoot);
   virtual PRIntn GetSkipSides() const;
 
+  void ClampAndSetBounds(nsBoxLayoutState& aState, 
+                         nsRect& aRect,
+                         nsPoint aScrollPosition,
+                         PRBool aRemoveOverflowAreas = PR_FALSE) {
+    /* 
+     * For RTL frames, restore the original scrolled position of the right
+     * edge, then subtract the current width to find the physical position.
+     * This can break the invariant that the scroll position is a multiple of
+     * device pixels, so round off the result to the nearest device pixel.
+     */
+    if (!mInner.IsLTR()) {
+      aRect.x = PresContext()->RoundAppUnitsToNearestDevPixels(
+         mInner.mScrollPort.XMost() - aScrollPosition.x - aRect.width);
+    }
+    mInner.mScrolledFrame->SetBounds(aState, aRect, aRemoveOverflowAreas);
+  }
+
 private:
   friend class nsGfxScrollFrameInner;
   nsGfxScrollFrameInner mInner;
 };
 
 #endif /* nsGfxScrollFrame_h___ */