From 6cf8da54f8334fc87041f679d8f292d0b5b0b0af Mon Sep 17 00:00:00 2001 From: Doug Sherk Date: Tue, 7 Aug 2012 18:51:00 -0700 Subject: [PATCH] Bug 775447: Properly count number of touch listeners in AsyncPanZoomController r=cjones --- dom/ipc/PBrowser.ipdl | 4 +++- dom/ipc/TabChild.cpp | 29 +++++++++++++++++++++++ dom/ipc/TabChild.h | 4 +++- dom/ipc/TabParent.cpp | 9 +++++++ dom/ipc/TabParent.h | 1 + gfx/layers/ipc/AsyncPanZoomController.cpp | 11 ++++++++- gfx/layers/ipc/AsyncPanZoomController.h | 14 +++++++++++ layout/ipc/RenderFrameParent.cpp | 8 +++++++ layout/ipc/RenderFrameParent.h | 2 ++ 9 files changed, 79 insertions(+), 3 deletions(-) diff --git a/dom/ipc/PBrowser.ipdl b/dom/ipc/PBrowser.ipdl index d45ff2ff39b4..767ffb655746 100644 --- a/dom/ipc/PBrowser.ipdl +++ b/dom/ipc/PBrowser.ipdl @@ -232,6 +232,8 @@ parent: nsString aName, nsString aFeatures) returns (bool windowOpened); + NotifyDOMTouchListenerAdded(); + __delete__(); child: @@ -342,4 +344,4 @@ state DYING: }; } -} \ No newline at end of file +} diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 8aee4abbf25e..78f606822c4c 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -20,6 +20,7 @@ #include "mozilla/layers/CompositorChild.h" #include "mozilla/layers/PLayersChild.h" #include "mozilla/layout/RenderFrameChild.h" +#include "mozilla/unused.h" #include "nsComponentManagerUtils.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" @@ -106,6 +107,24 @@ TabChild::TabChild(PRUint32 aChromeFlags, bool aIsBrowserElement, printf("creating %d!\n", NS_IsMainThread()); } +nsresult +TabChild::Observe(nsISupports *aSubject, + const char *aTopic, + const PRUnichar *aData) +{ + if (!strcmp(aTopic, "dom-touch-listener-added")) { + nsCOMPtr subject(do_QueryInterface(aSubject)); + nsCOMPtr win(do_GetInterface(mWebNav)); + nsCOMPtr topSubject; + subject->GetTop(getter_AddRefs(topSubject)); + if (win == topSubject) { + SendNotifyDOMTouchListenerAdded(); + } + } + + return NS_OK; +} + nsresult TabChild::Init() { @@ -121,6 +140,16 @@ TabChild::Init() nsCOMPtr docShellItem(do_QueryInterface(mWebNav)); docShellItem->SetItemType(nsIDocShellTreeItem::typeContentWrapper); + + nsCOMPtr observerService = + do_GetService(NS_OBSERVERSERVICE_CONTRACTID); + + if (observerService) { + observerService->AddObserver(this, + "dom-touch-listener-added", + false); + } + return NS_OK; } diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index 67b6c2ade8aa..5afc520a8af2 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -140,7 +140,8 @@ class TabChild : public PBrowserChild, public nsIWindowProvider, public nsSupportsWeakReference, public nsIDialogCreator, - public nsITabChild + public nsITabChild, + public nsIObserver { typedef mozilla::layout::RenderFrameChild RenderFrameChild; typedef mozilla::dom::ClonedMessageData ClonedMessageData; @@ -166,6 +167,7 @@ public: NS_DECL_NSIWINDOWPROVIDER NS_DECL_NSIDIALOGCREATOR NS_DECL_NSITABCHILD + NS_DECL_NSIOBSERVER virtual bool RecvLoadURL(const nsCString& uri); virtual bool RecvShow(const nsIntSize& size); diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 39c34f12d713..5e91c8aa02e8 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -1090,5 +1090,14 @@ TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, return true; } +bool +TabParent::RecvNotifyDOMTouchListenerAdded() +{ + if (RenderFrameParent* rfp = GetRenderFrame()) { + rfp->NotifyDOMTouchListenerAdded(); + } + return true; +} + } // namespace tabs } // namespace mozilla diff --git a/dom/ipc/TabParent.h b/dom/ipc/TabParent.h index b3b80598b577..f7710abfa7e6 100644 --- a/dom/ipc/TabParent.h +++ b/dom/ipc/TabParent.h @@ -101,6 +101,7 @@ public: virtual bool RecvSetBackgroundColor(const nscolor& aValue); virtual bool RecvGetDPI(float* aValue); virtual bool RecvGetWidgetNativeData(WindowsHandle* aValue); + virtual bool RecvNotifyDOMTouchListenerAdded(); virtual PContentDialogParent* AllocPContentDialog(const PRUint32& aType, const nsCString& aName, const nsCString& aFeatures, diff --git a/gfx/layers/ipc/AsyncPanZoomController.cpp b/gfx/layers/ipc/AsyncPanZoomController.cpp index 7972f567bbff..9a4252560d04 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -53,7 +53,8 @@ AsyncPanZoomController::AsyncPanZoomController(GeckoContentController* aGeckoCon mLastSampleTime(TimeStamp::Now()), mState(NOTHING), mDPI(72), - mContentPainterStatus(CONTENT_IDLE) + mContentPainterStatus(CONTENT_IDLE), + mMayHaveTouchListeners(false) { if (aGestures == USE_GESTURE_DETECTOR) { mGestureEventListener = new GestureEventListener(this); @@ -784,6 +785,10 @@ void AsyncPanZoomController::NotifyLayersUpdated(const FrameMetrics& aViewportFr // we get a larger displayport. This is very bad because we're wasting a // paint and not initializating the displayport correctly. RequestContentRepaint(); + + // Assuming a first paint means a new page has been loaded, clear the flag + // indicating that we may have touch listeners. + mMayHaveTouchListeners = false; } else if (!mFrameMetrics.mContentRect.IsEqualEdges(aViewportFrame.mContentRect)) { mFrameMetrics.mCSSContentRect = aViewportFrame.mCSSContentRect; SetPageRect(mFrameMetrics.mCSSContentRect); @@ -802,5 +807,9 @@ void AsyncPanZoomController::UpdateViewportSize(int aWidth, int aHeight) { mFrameMetrics = metrics; } +void AsyncPanZoomController::NotifyDOMTouchListenerAdded() { + mMayHaveTouchListeners = true; +} + } } diff --git a/gfx/layers/ipc/AsyncPanZoomController.h b/gfx/layers/ipc/AsyncPanZoomController.h index 2322b06e5037..82122c54f662 100644 --- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -99,6 +99,16 @@ public: */ void UpdateViewportSize(int aWidth, int aHeight); + /** + * A DOM touch listener has been added. When called, we enable the machinery + * that allows touch listeners to preventDefault any touch inputs. This should + * not be called unless there are actually touch listeners as it introduces + * potentially unbounded lag because it causes a round-trip through content. + * Usually, if content is responding in a timely fashion, this only introduces + * a nearly constant few hundred ms of lag. + */ + void NotifyDOMTouchListenerAdded(); + // -------------------------------------------------------------------------- // These methods must only be called on the compositor thread. // @@ -394,6 +404,10 @@ private: // requests a repaint. ContentPainterStatus mContentPainterStatus; + // Whether or not we might have touch listeners. This is a conservative + // approximation and may not be accurate. + bool mMayHaveTouchListeners; + friend class Axis; }; diff --git a/layout/ipc/RenderFrameParent.cpp b/layout/ipc/RenderFrameParent.cpp index 896b11d9aac3..43ae7717228d 100644 --- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -852,6 +852,14 @@ RenderFrameParent::BuildDisplayList(nsDisplayListBuilder* aBuilder, bounds)); } +void +RenderFrameParent::NotifyDOMTouchListenerAdded() +{ + if (mPanZoomController) { + mPanZoomController->NotifyDOMTouchListenerAdded(); + } +} + } // namespace layout } // namespace mozilla diff --git a/layout/ipc/RenderFrameParent.h b/layout/ipc/RenderFrameParent.h index a7ea91feb97a..aa30f7b59561 100644 --- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -93,6 +93,8 @@ public: void NotifyDimensionsChanged(int width, int height); + void NotifyDOMTouchListenerAdded(); + protected: void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;