Bug 1250550 - Ensure a scroll event posted during a refresh driver tick fires during that same tick. r=mats
☠☠ backed out by ae4f419ba470 ☠ ☠
authorBotond Ballo <botond@mozilla.com>
Wed, 24 Feb 2016 18:20:40 -0500
changeset 322615 447498cdecee1d06cce578767ab64874628cf32c
parent 322614 ad0a07c60528ac9a2be4fdd164f5dde99dd66170
child 322616 651ae113dc0d9eef77b0f253c7ee122cf952ddce
push id5913
push userjlund@mozilla.com
push dateMon, 25 Apr 2016 16:57:49 +0000
treeherdermozilla-beta@dcaf0a6fa115 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmats
bugs1250550
milestone47.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 1250550 - Ensure a scroll event posted during a refresh driver tick fires during that same tick. r=mats MozReview-Commit-ID: 1ZvYjA6a5ay
layout/generic/nsGfxScrollFrame.cpp
layout/generic/nsGfxScrollFrame.h
--- a/layout/generic/nsGfxScrollFrame.cpp
+++ b/layout/generic/nsGfxScrollFrame.cpp
@@ -4382,31 +4382,31 @@ void ScrollFrameHelper::CurPosAttributeC
 }
 
 /* ============= Scroll events ========== */
 
 ScrollFrameHelper::ScrollEvent::ScrollEvent(ScrollFrameHelper* aHelper)
   : mHelper(aHelper)
 {
   mDriver = mHelper->mOuter->PresContext()->RefreshDriver();
-  mDriver->AddRefreshObserver(this, Flush_Style);
+  mDriver->AddRefreshObserver(this, Flush_Layout);
 }
 
 ScrollFrameHelper::ScrollEvent::~ScrollEvent()
 {
   if (mDriver) {
     mDriver->RemoveRefreshObserver(this, Flush_Style);
     mDriver = nullptr;
   }
 }
 
 void
 ScrollFrameHelper::ScrollEvent::WillRefresh(mozilla::TimeStamp aTime)
 {
-  mDriver->RemoveRefreshObserver(this, Flush_Style);
+  mDriver->RemoveRefreshObserver(this, Flush_Layout);
   mDriver = nullptr;
   mHelper->FireScrollEvent();
 }
 
 void
 ScrollFrameHelper::FireScrollEvent()
 {
   MOZ_ASSERT(mScrollEvent);
--- a/layout/generic/nsGfxScrollFrame.h
+++ b/layout/generic/nsGfxScrollFrame.h
@@ -96,16 +96,39 @@ public:
 
   void PostScrollEvent();
   void FireScrollEvent();
   void PostScrolledAreaEvent();
   void FireScrolledAreaEvent();
 
   bool IsSmoothScrollingEnabled();
 
+  /**
+   * This class handles the dispatching of scroll events to content.
+   *
+   * nsRefreshDriver maintains three lists of refresh observers, one for each
+   * flush type: Flush_Style, Flush_Layout, and Flush_Display.
+   *
+   * During a tick, it runs through each list of observers, in order, and runs
+   * them. To iterate over each list, it uses an EndLimitedIterator, which is
+   * designed to iterate only over elements present when the iterator was
+   * created, not elements added afterwards. This means that, for a given flush
+   * type, a refresh observer added during the execution of another refresh
+   * observer of that flush type, will not run until the next tick.
+   *
+   * During main-thread animation-driven scrolling, ScrollEvents are *posted*
+   * by AsyncScroll::WillRefresh(). AsyncScroll registers itself as a Flush_Style
+   * refresh observer.
+   *
+   * Posting a scroll event, as of bug 1250550, registers a Flush_Layout
+   * refresh observer, which *fires* the event when run. This allows the event
+   * to be fired to content in the same refresh driver tick as it is posted.
+   * This is an important invariant to maintain to reduce scroll event latency
+   * for main-thread scrolling.
+   */
   class ScrollEvent : public nsARefreshObserver {
   public:
     NS_INLINE_DECL_REFCOUNTING(ScrollEvent, override)
     explicit ScrollEvent(ScrollFrameHelper *helper);
     void WillRefresh(mozilla::TimeStamp aTime) override;
   protected:
     virtual ~ScrollEvent();
   private: