Bug 1310509 - Call NotifyAsyncPanZoomStarted/Stopped on document containing current scrolling content. draft
authorTing-Yu Lin <tlin@mozilla.com>
Fri, 04 Nov 2016 15:29:04 +0800
changeset 433813 8bac93ae7df7ff984477409c37154248770d0b78
parent 433311 3b80868f7a8fe0361918a814fbbbfb9308ae0c0a
child 535964 41a9d1ed4b2b5eb4ad16ab81305aada5357af4b8
push id34659
push userbmo:tlin@mozilla.com
push dateFri, 04 Nov 2016 10:09:37 +0000
bugs1310509, 1088559, 1142926
milestone52.0a1
Bug 1310509 - Call NotifyAsyncPanZoomStarted/Stopped on document containing current scrolling content. We now call NotifyAsyncPanZoomStarted/Stopped precisely on the document which is being transformed, so we no longer need to notify the child docshells which was added in Bug 1088559. Remove the |nsIDocument| argument for ProcessAPZStateChange(), which is not used anymore. mActiveAPZTransforms added in bug 1142926 is removed because AccessibleCaret is the only consumer for AsyncPanZoomStarted/Stopped, and it now defaults to always show while scrolling, i.e. "layout.accessiblecaret.always_show_when_scrolling" defaults to true. And I cannot reproduce the bug even if I turn off the preference. MozReview-Commit-ID: DiEk2gCIHn2
docshell/base/nsDocShell.cpp
dom/ipc/TabChild.cpp
gfx/layers/apz/util/APZEventState.cpp
gfx/layers/apz/util/APZEventState.h
gfx/layers/apz/util/ChromeProcessController.cpp
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -3075,49 +3075,31 @@ nsDocShell::NotifyAsyncPanZoomStarted()
     nsWeakPtr ref = iter.GetNext();
     nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
     if (obs) {
       obs->AsyncPanZoomStarted();
     } else {
       mScrollObservers.RemoveElement(ref);
     }
   }
-
-  // Also notify child docshell
-  for (uint32_t i = 0; i < mChildList.Length(); ++i) {
-    nsCOMPtr<nsIDocShell> kid = do_QueryInterface(ChildAt(i));
-    if (kid) {
-      nsDocShell* docShell = static_cast<nsDocShell*>(kid.get());
-      docShell->NotifyAsyncPanZoomStarted();
-    }
-  }
 }
 
 void
 nsDocShell::NotifyAsyncPanZoomStopped()
 {
   nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
   while (iter.HasMore()) {
     nsWeakPtr ref = iter.GetNext();
     nsCOMPtr<nsIScrollObserver> obs = do_QueryReferent(ref);
     if (obs) {
       obs->AsyncPanZoomStopped();
     } else {
       mScrollObservers.RemoveElement(ref);
     }
   }
-
-  // Also notify child docshell
-  for (uint32_t i = 0; i < mChildList.Length(); ++i) {
-    nsCOMPtr<nsIDocShell> kid = do_QueryInterface(ChildAt(i));
-    if (kid) {
-      nsDocShell* docShell = static_cast<nsDocShell*>(kid.get());
-      docShell->NotifyAsyncPanZoomStopped();
-    }
-  }
 }
 
 NS_IMETHODIMP
 nsDocShell::NotifyScrollObservers()
 {
   nsTObserverArray<nsWeakPtr>::ForwardIterator iter(mScrollObservers);
   while (iter.HasMore()) {
     nsWeakPtr ref = iter.GetNext();
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -1518,17 +1518,17 @@ TabChild::RecvHandleTap(const GeckoConte
   return true;
 }
 
 bool
 TabChild::NotifyAPZStateChange(const ViewID& aViewId,
                                const layers::GeckoContentController::APZStateChange& aChange,
                                const int& aArg)
 {
-  mAPZEventState->ProcessAPZStateChange(GetDocument(), aViewId, aChange, aArg);
+  mAPZEventState->ProcessAPZStateChange(aViewId, aChange, aArg);
   if (aChange == layers::GeckoContentController::APZStateChange::eTransformEnd) {
     // This is used by tests to determine when the APZ is done doing whatever
     // it's doing. XXX generify this as needed when writing additional tests.
     nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
     observerService->NotifyObservers(nullptr, "APZ:TransformEnd", nullptr);
   }
   return true;
 }
--- a/gfx/layers/apz/util/APZEventState.cpp
+++ b/gfx/layers/apz/util/APZEventState.cpp
@@ -97,17 +97,16 @@ APZEventState::APZEventState(nsIWidget* 
                              ContentReceivedInputBlockCallback&& aCallback)
   : mWidget(nullptr)  // initialized in constructor body
   , mActiveElementManager(new ActiveElementManager())
   , mContentReceivedInputBlockCallback(Move(aCallback))
   , mPendingTouchPreventedResponse(false)
   , mPendingTouchPreventedBlockId(0)
   , mEndTouchIsClick(false)
   , mTouchEndCancelled(false)
-  , mActiveAPZTransforms(0)
   , mLastTouchIdentifier(0)
 {
   nsresult rv;
   mWidget = do_GetWeakReference(aWidget, &rv);
   MOZ_ASSERT(NS_SUCCEEDED(rv), "APZEventState constructed with a widget that"
       " does not support weak references. APZ will NOT work!");
 
   if (!sActiveDurationMsSet) {
@@ -401,62 +400,59 @@ APZEventState::ProcessMouseEvent(const W
   // ignore this drag block. We can send defaultPrevented as either true or
   // false, it doesn't matter, because APZ won't have the scrollbar metrics
   // anyway, and will know to drop the block.
   bool defaultPrevented = false;
   mContentReceivedInputBlockCallback(aGuid, aInputBlockId, defaultPrevented);
 }
 
 void
-APZEventState::ProcessAPZStateChange(const nsCOMPtr<nsIDocument>& aDocument,
-                                     ViewID aViewId,
+APZEventState::ProcessAPZStateChange(ViewID aViewId,
                                      APZStateChange aChange,
                                      int aArg)
 {
   switch (aChange)
   {
   case APZStateChange::eTransformBegin:
   {
     nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
     if (sf) {
       sf->SetTransformingByAPZ(true);
     }
     nsIScrollbarMediator* scrollbarMediator = do_QueryFrame(sf);
     if (scrollbarMediator) {
       scrollbarMediator->ScrollbarActivityStarted();
     }
 
-    if (aDocument && mActiveAPZTransforms == 0) {
-      nsCOMPtr<nsIDocShell> docshell(aDocument->GetDocShell());
-      if (docshell && sf) {
-        nsDocShell* nsdocshell = static_cast<nsDocShell*>(docshell.get());
-        nsdocshell->NotifyAsyncPanZoomStarted();
-      }
+    nsIContent* content = nsLayoutUtils::FindContentFor(aViewId);
+    nsIDocument* doc = content ? content->GetComposedDoc() : nullptr;
+    nsCOMPtr<nsIDocShell> docshell(doc ? doc->GetDocShell() : nullptr);
+    if (docshell && sf) {
+      nsDocShell* nsdocshell = static_cast<nsDocShell*>(docshell.get());
+      nsdocshell->NotifyAsyncPanZoomStarted();
     }
-    mActiveAPZTransforms++;
     break;
   }
   case APZStateChange::eTransformEnd:
   {
-    mActiveAPZTransforms--;
     nsIScrollableFrame* sf = nsLayoutUtils::FindScrollableFrameFor(aViewId);
     if (sf) {
       sf->SetTransformingByAPZ(false);
     }
     nsIScrollbarMediator* scrollbarMediator = do_QueryFrame(sf);
     if (scrollbarMediator) {
       scrollbarMediator->ScrollbarActivityStopped();
     }
 
-    if (aDocument && mActiveAPZTransforms == 0) {
-      nsCOMPtr<nsIDocShell> docshell(aDocument->GetDocShell());
-      if (docshell && sf) {
-        nsDocShell* nsdocshell = static_cast<nsDocShell*>(docshell.get());
-        nsdocshell->NotifyAsyncPanZoomStopped();
-      }
+    nsIContent* content = nsLayoutUtils::FindContentFor(aViewId);
+    nsIDocument* doc = content ? content->GetComposedDoc() : nullptr;
+    nsCOMPtr<nsIDocShell> docshell(doc ? doc->GetDocShell() : nullptr);
+    if (docshell && sf) {
+      nsDocShell* nsdocshell = static_cast<nsDocShell*>(docshell.get());
+      nsdocshell->NotifyAsyncPanZoomStopped();
     }
     break;
   }
   case APZStateChange::eStartTouch:
   {
     mActiveElementManager->HandleTouchStart(aArg);
     break;
   }
--- a/gfx/layers/apz/util/APZEventState.h
+++ b/gfx/layers/apz/util/APZEventState.h
@@ -67,18 +67,17 @@ public:
                          nsEventStatus aApzResponse,
                          nsEventStatus aContentResponse);
   void ProcessWheelEvent(const WidgetWheelEvent& aEvent,
                          const ScrollableLayerGuid& aGuid,
                          uint64_t aInputBlockId);
   void ProcessMouseEvent(const WidgetMouseEvent& aEvent,
                          const ScrollableLayerGuid& aGuid,
                          uint64_t aInputBlockId);
-  void ProcessAPZStateChange(const nsCOMPtr<nsIDocument>& aDocument,
-                             ViewID aViewId,
+  void ProcessAPZStateChange(ViewID aViewId,
                              APZStateChange aChange,
                              int aArg);
   void ProcessClusterHit();
 private:
   ~APZEventState();
   bool SendPendingTouchPreventedResponse(bool aPreventDefault);
   bool FireContextmenuEvents(const nsCOMPtr<nsIPresShell>& aPresShell,
                              const CSSPoint& aPoint,
@@ -90,16 +89,15 @@ private:
   nsWeakPtr mWidget;
   RefPtr<ActiveElementManager> mActiveElementManager;
   ContentReceivedInputBlockCallback mContentReceivedInputBlockCallback;
   bool mPendingTouchPreventedResponse;
   ScrollableLayerGuid mPendingTouchPreventedGuid;
   uint64_t mPendingTouchPreventedBlockId;
   bool mEndTouchIsClick;
   bool mTouchEndCancelled;
-  int mActiveAPZTransforms;
   int32_t mLastTouchIdentifier;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif /* mozilla_layers_APZEventState_h */
--- a/gfx/layers/apz/util/ChromeProcessController.cpp
+++ b/gfx/layers/apz/util/ChromeProcessController.cpp
@@ -245,17 +245,17 @@ ChromeProcessController::NotifyAPZStateC
                             aGuid, aChange, aArg));
     return;
   }
 
   if (!mAPZEventState) {
     return;
   }
 
-  mAPZEventState->ProcessAPZStateChange(GetRootDocument(), aGuid.mScrollId, aChange, aArg);
+  mAPZEventState->ProcessAPZStateChange(aGuid.mScrollId, aChange, aArg);
 }
 
 void
 ChromeProcessController::NotifyMozMouseScrollEvent(const FrameMetrics::ViewID& aScrollId, const nsString& aEvent)
 {
   if (MessageLoop::current() != mUILoop) {
     mUILoop->PostTask(NewRunnableMethod
                       <FrameMetrics::ViewID,