author | Doug Sherk <dsherk2@mozilla.com> |
Wed, 08 Aug 2012 13:38:06 -0700 | |
changeset 107894 | 282bfd3e56e029cc430ac372a7cdcaa660586e1f |
parent 107893 | 986a9cafa237ab8b46ea3cc6e5bff270f4ff64fa |
child 107895 | 174a57bbcb225b08864d9284a0ffe86d54a25346 |
push id | 214 |
push user | akeybl@mozilla.com |
push date | Wed, 14 Nov 2012 20:38:59 +0000 |
treeherder | mozilla-release@c8b08ec8e1aa [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | cjones |
bugs | 775448 |
milestone | 17.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
|
--- a/dom/browser-element/BrowserElementScrolling.js +++ b/dom/browser-element/BrowserElementScrolling.js @@ -38,16 +38,26 @@ const ContentPanning = { onTouchStart: function cp_onTouchStart(evt) { this.dragging = true; this.panning = false; let oldTarget = this.target; [this.target, this.scrollCallback] = this.getPannable(evt.target); + // If we found a target, that means we have found a scrollable subframe. In + // this case, and if we are using async panning and zooming on the parent + // frame, inform the pan/zoom controller that it should not attempt to + // handle any touch events it gets until the next batch (meaning the next + // time we get a touch end). + if (this.target != null && ContentPanning._asyncPanZoomForViewportFrame) { + var os = Cc["@mozilla.org/observer-service;1"].getService(Ci.nsIObserverService); + os.notifyObservers(docShell, 'cancel-default-pan-zoom', null); + } + // If there is a pan animation running (from a previous pan gesture) and // the user touch back the screen, stop this animation immediatly and // prevent the possible click action if the touch happens on the same // target. this.preventNextClick = false; if (KineticPanning.active) { KineticPanning.stop();
--- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -115,16 +115,22 @@ TabChild::Observe(nsISupports *aSubject, if (!strcmp(aTopic, "dom-touch-listener-added")) { nsCOMPtr<nsIDOMWindow> subject(do_QueryInterface(aSubject)); nsCOMPtr<nsIDOMWindow> win(do_GetInterface(mWebNav)); nsCOMPtr<nsIDOMWindow> topSubject; subject->GetTop(getter_AddRefs(topSubject)); if (win == topSubject) { SendNotifyDOMTouchListenerAdded(); } + } else if (!strcmp(aTopic, "cancel-default-pan-zoom")) { + nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aSubject)); + nsCOMPtr<nsITabChild> tabChild(GetTabChildFrom(docShell)); + if (tabChild == this) { + mRemoteFrame->CancelDefaultPanZoom(); + } } return NS_OK; } nsresult TabChild::Init() { @@ -143,16 +149,19 @@ TabChild::Init() nsCOMPtr<nsIObserverService> observerService = do_GetService(NS_OBSERVERSERVICE_CONTRACTID); if (observerService) { observerService->AddObserver(this, "dom-touch-listener-added", false); + observerService->AddObserver(this, + "cancel-default-pan-zoom", + false); } return NS_OK; } NS_INTERFACE_MAP_BEGIN(TabChild) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIWebBrowserChrome) NS_INTERFACE_MAP_ENTRY(nsIWebBrowserChrome)
--- a/gfx/layers/ipc/AsyncPanZoomController.cpp +++ b/gfx/layers/ipc/AsyncPanZoomController.cpp @@ -49,17 +49,18 @@ AsyncPanZoomController::AsyncPanZoomCont : mGeckoContentController(aGeckoContentController), mX(this), mY(this), mMonitor("AsyncPanZoomController"), mLastSampleTime(TimeStamp::Now()), mState(NOTHING), mDPI(72), mContentPainterStatus(CONTENT_IDLE), - mMayHaveTouchListeners(false) + mMayHaveTouchListeners(false), + mDisableNextTouchBatch(false) { if (aGestures == USE_GESTURE_DETECTOR) { mGestureEventListener = new GestureEventListener(this); } SetDPI(mDPI); } @@ -218,16 +219,20 @@ nsEventStatus AsyncPanZoomController::On NS_WARNING("Unhandled case in OnTouchStart"); break; } return nsEventStatus_eConsumeNoDefault; } nsEventStatus AsyncPanZoomController::OnTouchMove(const MultiTouchInput& aEvent) { + if (mDisableNextTouchBatch) { + return nsEventStatus_eIgnore; + } + switch (mState) { case FLING: case NOTHING: // May happen if the user double-taps and drags without lifting after the // second tap. Ignore the move if this happens. return nsEventStatus_eIgnore; case TOUCHING: { @@ -249,16 +254,21 @@ nsEventStatus AsyncPanZoomController::On NS_WARNING("Gesture listener should have handled pinching in OnTouchMove."); return nsEventStatus_eIgnore; } return nsEventStatus_eConsumeNoDefault; } nsEventStatus AsyncPanZoomController::OnTouchEnd(const MultiTouchInput& aEvent) { + if (mDisableNextTouchBatch) { + mDisableNextTouchBatch = false; + return nsEventStatus_eIgnore; + } + switch (mState) { case FLING: // Should never happen. NS_WARNING("Received impossible touch end in OnTouchEnd."); // Fall through. case NOTHING: // May happen if the user double-taps and drags without lifting after the // second tap. Ignore if this happens. @@ -806,10 +816,14 @@ void AsyncPanZoomController::UpdateViewp metrics.mViewport = nsIntRect(0, 0, aWidth, aHeight); mFrameMetrics = metrics; } void AsyncPanZoomController::NotifyDOMTouchListenerAdded() { mMayHaveTouchListeners = true; } +void AsyncPanZoomController::CancelDefaultPanZoom() { + mDisableNextTouchBatch = true; +} + } }
--- a/gfx/layers/ipc/AsyncPanZoomController.h +++ b/gfx/layers/ipc/AsyncPanZoomController.h @@ -104,16 +104,26 @@ public: * 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(); + /** + * We have found a scrollable subframe, so disable our machinery until we hit + * a touch end or a new touch start. This prevents us from accidentally + * panning both the subframe and the parent frame. + * + * XXX/bug 775452: We should eventually be supporting async scrollable + * subframes. + */ + void CancelDefaultPanZoom(); + // -------------------------------------------------------------------------- // These methods must only be called on the compositor thread. // /** * The compositor calls this when it's about to draw pannable/zoomable content * and is setting up transforms for compositing the layer tree. This is not * idempotent. For example, a fling transform can be applied each time this is @@ -403,15 +413,19 @@ private: // this status will not be updated. It is only changed when this class // 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; + // Flag used to determine whether or not we should disable handling of the + // next batch of touch events. This is used for sync scrolling of subframes. + bool mDisableNextTouchBatch; + friend class Axis; }; } } #endif // mozilla_layers_PanZoomController_h
--- a/layout/ipc/PRenderFrame.ipdl +++ b/layout/ipc/PRenderFrame.ipdl @@ -36,16 +36,18 @@ parent: * * |id| is set to 0 in the "direct" case, and to a whole number * in the "indirect" case. */ async PLayers(); async NotifyCompositorTransaction(); + async CancelDefaultPanZoom(); + async __delete__(); state EMPTY_OR_DIRECT_COMPOSITOR: recv PLayers goto HAVE_CONTENT; recv NotifyCompositorTransaction goto EMPTY_OR_DIRECT_COMPOSITOR; recv __delete__; state HAVE_CONTENT:
--- a/layout/ipc/RenderFrameChild.cpp +++ b/layout/ipc/RenderFrameChild.cpp @@ -27,16 +27,22 @@ RenderFrameChild::Destroy() layers->Destroy(); // |layers| was just deleted, take care } Send__delete__(this); // WARNING: |this| is dead, hands off } +void +RenderFrameChild::CancelDefaultPanZoom() +{ + SendCancelDefaultPanZoom(); +} + PLayersChild* RenderFrameChild::AllocPLayers() { return new ShadowLayersChild(); } bool RenderFrameChild::DeallocPLayers(PLayersChild* aLayers)
--- a/layout/ipc/RenderFrameChild.h +++ b/layout/ipc/RenderFrameChild.h @@ -14,16 +14,18 @@ namespace mozilla { namespace layout { class RenderFrameChild : public PRenderFrameChild { public: RenderFrameChild() {} virtual ~RenderFrameChild() {} + void CancelDefaultPanZoom(); + void Destroy(); protected: virtual PLayersChild* AllocPLayers() MOZ_OVERRIDE; virtual bool DeallocPLayers(PLayersChild* aLayers) MOZ_OVERRIDE; }; } // namespace layout
--- a/layout/ipc/RenderFrameParent.cpp +++ b/layout/ipc/RenderFrameParent.cpp @@ -715,16 +715,25 @@ RenderFrameParent::ActorDestroy(ActorDes bool RenderFrameParent::RecvNotifyCompositorTransaction() { TriggerRepaint(); return true; } +bool +RenderFrameParent::RecvCancelDefaultPanZoom() +{ + if (mPanZoomController) { + mPanZoomController->CancelDefaultPanZoom(); + } + return true; +} + PLayersParent* RenderFrameParent::AllocPLayers() { if (!mFrameLoader || mFrameLoaderDestroyed) { return nullptr; } nsRefPtr<LayerManager> lm = GetFrom(mFrameLoader); return new ShadowLayersParent(lm->AsShadowManager(), this, 0);
--- a/layout/ipc/RenderFrameParent.h +++ b/layout/ipc/RenderFrameParent.h @@ -95,16 +95,18 @@ public: void NotifyDOMTouchListenerAdded(); protected: void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE; virtual bool RecvNotifyCompositorTransaction() MOZ_OVERRIDE; + virtual bool RecvCancelDefaultPanZoom() MOZ_OVERRIDE; + virtual PLayersParent* AllocPLayers() MOZ_OVERRIDE; virtual bool DeallocPLayers(PLayersParent* aLayers) MOZ_OVERRIDE; private: void BuildViewMap(); void TriggerRepaint(); void DispatchEventForPanZoomController(const InputEvent& aEvent);