Bug 811570 - Make the root content scroll frame inactive initially if it is overflow hidden. r=roc
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 13 Nov 2012 22:26:33 -0800
changeset 113200 24c0c55af0edc657b37310a440e23e109f5b1003
parent 113199 1cfa8c4279e51605d041272813886195b0ec6867
child 113201 51fa971d228095bb9d9402477be2966aa1cbc413
push id17997
push usermwoodrow@mozilla.com
push dateWed, 14 Nov 2012 06:26:43 +0000
treeherdermozilla-inbound@24c0c55af0ed [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs811570
milestone19.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 811570 - Make the root content scroll frame inactive initially if it is overflow hidden. r=roc
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -1450,16 +1450,17 @@ nsGfxScrollFrameInner::nsGfxScrollFrameI
   , mHadNonInitialReflow(false)
   , mHorizontalOverflow(false)
   , mVerticalOverflow(false)
   , mPostedReflowCallback(false)
   , mMayHaveDirtyFixedChildren(false)
   , mUpdateScrollbarAttributes(false)
   , mCollapsedResizer(false)
   , mShouldBuildLayer(false)
+  , mHasBeenScrolled(false)
 {
   mScrollingActive = IsAlwaysActive();
 
   if (LookAndFeel::GetInt(LookAndFeel::eIntID_ShowHideScrollbars) != 0) {
     mScrollbarActivity = new ScrollbarActivity(do_QueryFrame(aOuter));
   }
 }
 
@@ -1735,21 +1736,33 @@ bool nsGfxScrollFrameInner::ShouldClampS
     return true;
   nsSubDocumentFrame* subdocFrame = static_cast<nsSubDocumentFrame*>
     (nsLayoutUtils::GetCrossDocParentFrame(mOuter->PresContext()->PresShell()->GetRootFrame()));
   return !subdocFrame || subdocFrame->ShouldClampScrollPosition();
 }
 
 bool nsGfxScrollFrameInner::IsAlwaysActive() const
 {
-  // The root scrollframe for a non-chrome document which is the direct
-  // child of a chrome document is always treated as "active".
-  // XXX maybe we should extend this so that IFRAMEs which are fill the
-  // entire viewport (like GMail!) are always active
-  return mIsRoot && mOuter->PresContext()->IsRootContentDocument();
+  // Unless this is the root scrollframe for a non-chrome document 
+  // which is the direct child of a chrome document, we default to not
+  // being "active".
+  if (!(mIsRoot && mOuter->PresContext()->IsRootContentDocument())) {
+     return false;
+  }
+
+  // If we have scrolled before, then we should stay active.
+  if (mHasBeenScrolled) {
+   return true;
+  }
+ 
+  // If we're overflow:hidden, then start as inactive until
+  // we get scrolled manually.
+  ScrollbarStyles styles = GetScrollbarStylesFromFrame();
+  return (styles.mHorizontal != NS_STYLE_OVERFLOW_HIDDEN &&
+          styles.mVertical != NS_STYLE_OVERFLOW_HIDDEN);
 }
 
 void nsGfxScrollFrameInner::MarkInactive()
 {
   if (IsAlwaysActive() || !mScrollingActive)
     return;
 
   mScrollingActive = false;
@@ -1769,16 +1782,22 @@ void nsGfxScrollFrameInner::MarkActive()
       gScrollFrameActivityTracker = new ScrollFrameActivityTracker();
     }
     gScrollFrameActivityTracker->AddObject(this);
   }
 }
 
 void nsGfxScrollFrameInner::ScrollVisual(nsPoint aOldScrolledFramePos)
 {
+  // Mark this frame as having been scrolled. If this is the root
+  // scroll frame of a content document, then IsAlwaysActive()
+  // will return true from now on and MarkInactive() won't
+  // have any effect.
+  mHasBeenScrolled = true;
+
   AdjustViews(mScrolledFrame);
   // We need to call this after fixing up the view positions
   // to be consistent with the frame hierarchy.
   bool invalidate = false;
   bool canScrollWithBlitting = CanScrollWithBlitting(mOuter);
   mOuter->RemoveStateBits(NS_SCROLLFRAME_INVALIDATE_CONTENTS_ON_SCROLL);
   if (IsScrollingActive()) {
     if (!canScrollWithBlitting) {
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -329,16 +329,19 @@ public:
   bool mScrollingActive:1;
   // If true, the resizer is collapsed and not displayed
   bool mCollapsedResizer:1;
 
   // If true, the layer should always be active because we always build a layer.
   // Used for asynchronous scrolling.
   bool mShouldBuildLayer:1;
 
+  // True if this frame has been scrolled at least once
+  bool mHasBeenScrolled:1;
+
 protected:
   void ScrollToWithOrigin(nsPoint aScrollPosition,
                           nsIScrollableFrame::ScrollMode aMode,
                           nsIAtom *aOrigin, // nullptr indicates "other" origin
                           const nsRect* aRange);
 };
 
 /**