From f9723b32cf4e2db9c03dd6410e1c04e52ec9b851 Mon Sep 17 00:00:00 2001 From: Ethan Lin Date: Sun, 8 Feb 2015 18:57:00 +0100 Subject: [PATCH] Bug 1125750 - Check the overflow region direction to avoid unnecesary reflow for scrollable frame. r=dbaron --HG-- extra : rebase_source : f95ce49ad13e9c26ad225d5135d9dd545485b6e8 --- layout/generic/nsGfxScrollFrame.cpp | 49 +++++++++++++++++++++++++++-- layout/generic/nsGfxScrollFrame.h | 4 +++ 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/layout/generic/nsGfxScrollFrame.cpp b/layout/generic/nsGfxScrollFrame.cpp index 592eef5aa4c5..8981856701ef 100644 --- a/layout/generic/nsGfxScrollFrame.cpp +++ b/layout/generic/nsGfxScrollFrame.cpp @@ -80,6 +80,21 @@ BuildScrollContainerLayers() return !sContainerlessScrollingEnabled; } +static uint32_t +GetOverflowChange(const nsRect& aCurScrolledRect, const nsRect& aPrevScrolledRect) +{ + uint32_t result = 0; + if (aPrevScrolledRect.x != aCurScrolledRect.x || + aPrevScrolledRect.width != aCurScrolledRect.width) { + result |= nsIScrollableFrame::HORIZONTAL; + } + if (aPrevScrolledRect.y != aCurScrolledRect.y || + aPrevScrolledRect.height != aCurScrolledRect.height) { + result |= nsIScrollableFrame::VERTICAL; + } + return result; +} + //---------------------------------------------------------------------- //----------nsHTMLScrollFrame------------------------------------------- @@ -914,6 +929,8 @@ nsHTMLScrollFrame::Reflow(nsPresContext* aPresContext, mHelper.PostScrolledAreaEvent(); } + mHelper.UpdatePrevScrolledRect(); + aStatus = NS_FRAME_COMPLETE; NS_FRAME_SET_TRUNCATION(aStatus, aReflowState, aDesiredSize); mHelper.PostOverflowEvent(); @@ -4525,6 +4542,8 @@ nsXULScrollFrame::Layout(nsBoxLayoutState& aState) f->SetRect(clippedRect); } + mHelper.UpdatePrevScrolledRect(); + mHelper.PostOverflowEvent(); return NS_OK; } @@ -4668,9 +4687,27 @@ ScrollFrameHelper::UpdateOverflow() nsIScrollableFrame* sf = do_QueryFrame(mOuter); ScrollbarStyles ss = sf->GetScrollbarStyles(); - if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN || - ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN || - GetScrollPosition() != nsPoint()) { + // Reflow when the change in overflow leads to one of our scrollbars + // changing or might require repositioning the scrolled content due to + // reduced extents. + nsRect scrolledRect = GetScrolledRect(); + uint32_t overflowChange = GetOverflowChange(scrolledRect, mPrevScrolledRect); + mPrevScrolledRect = scrolledRect; + + bool needReflow = false; + nsPoint scrollPosition = GetScrollPosition(); + if (overflowChange & nsIScrollableFrame::HORIZONTAL) { + if (ss.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN || scrollPosition.x) { + needReflow = true; + } + } + if (overflowChange & nsIScrollableFrame::VERTICAL) { + if (ss.mVertical != NS_STYLE_OVERFLOW_HIDDEN || scrollPosition.y) { + needReflow = true; + } + } + + if (needReflow) { // If there are scrollbars, or we're not at the beginning of the pane, // the scroll position may change. In this case, mark the frame as // needing reflow. Don't use NS_FRAME_IS_DIRTY as dirty as that means @@ -4699,6 +4736,12 @@ ScrollFrameHelper::UpdateSticky() } } +void +ScrollFrameHelper::UpdatePrevScrolledRect() +{ + mPrevScrolledRect = GetScrolledRect(); +} + void ScrollFrameHelper::AdjustScrollbarRectForResizer( nsIFrame* aFrame, nsPresContext* aPresContext, diff --git a/layout/generic/nsGfxScrollFrame.h b/layout/generic/nsGfxScrollFrame.h index d94c14a5f991..fd4877b80d30 100644 --- a/layout/generic/nsGfxScrollFrame.h +++ b/layout/generic/nsGfxScrollFrame.h @@ -300,6 +300,8 @@ public: void UpdateSticky(); + void UpdatePrevScrolledRect(); + bool IsRectNearlyVisible(const nsRect& aRect) const; nsRect ExpandRectToNearlyVisible(const nsRect& aRect) const; @@ -422,6 +424,8 @@ public: // The scroll position where we last updated image visibility. nsPoint mLastUpdateImagesPos; + nsRect mPrevScrolledRect; + FrameMetrics::ViewID mScrollParentID; bool mNeverHasVerticalScrollbar:1;