Bug 1005815 - Extract TabChild::FireSingleTapEvent and its helpers into APZCCallbackHelper. r=kats,smaug
authorBotond Ballo <botond@mozilla.com>
Wed, 21 Jan 2015 19:46:27 -0500
changeset 226946 7ee5dfb97ff602d09c5e72fd605a907684fddd5b
parent 226945 4b3d6f5a3f1b2ab405b9c5df3e09b7e04acc2a75
child 226947 0038cfaf847a5625e0b0309e1b3374e2a71fda4c
push id28212
push userphilringnalda@gmail.com
push dateSun, 01 Feb 2015 17:17:22 +0000
treeherdermozilla-central@2ed663b8bc05 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskats, smaug
bugs1005815
milestone38.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 1005815 - Extract TabChild::FireSingleTapEvent and its helpers into APZCCallbackHelper. r=kats,smaug
dom/ipc/TabChild.cpp
dom/ipc/TabChild.h
gfx/layers/apz/util/APZCCallbackHelper.cpp
gfx/layers/apz/util/APZCCallbackHelper.h
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -119,46 +119,46 @@ static bool sActiveDurationMsSet = false
 typedef nsDataHashtable<nsUint64HashKey, TabChild*> TabChildMap;
 static TabChildMap* sTabChildren;
 
 class TabChild::DelayedFireSingleTapEvent MOZ_FINAL : public nsITimerCallback
 {
 public:
   NS_DECL_ISUPPORTS
 
-  DelayedFireSingleTapEvent(TabChild* aTabChild,
+  DelayedFireSingleTapEvent(nsIWidget* aWidget,
                             LayoutDevicePoint& aPoint,
                             nsITimer* aTimer)
-    : mTabChild(do_GetWeakReference(static_cast<nsITabChild*>(aTabChild)))
+    : mWidget(do_GetWeakReference(aWidget))
     , mPoint(aPoint)
     // Hold the reference count until we are called back.
     , mTimer(aTimer)
   {
   }
 
   NS_IMETHODIMP Notify(nsITimer*) MOZ_OVERRIDE
   {
-    nsCOMPtr<nsITabChild> tabChild = do_QueryReferent(mTabChild);
-    if (tabChild) {
-      static_cast<TabChild*>(tabChild.get())->FireSingleTapEvent(mPoint);
+    nsCOMPtr<nsIWidget> widget = do_QueryReferent(mWidget);
+    if (widget) {
+      APZCCallbackHelper::FireSingleTapEvent(mPoint, widget);
     }
     mTimer = nullptr;
     return NS_OK;
   }
 
   void ClearTimer() {
     mTimer = nullptr;
   }
 
 private:
   ~DelayedFireSingleTapEvent()
   {
   }
 
-  nsWeakPtr mTabChild;
+  nsWeakPtr mWidget;
   LayoutDevicePoint mPoint;
   nsCOMPtr<nsITimer> mTimer;
 };
 
 NS_IMPL_ISUPPORTS(TabChild::DelayedFireSingleTapEvent,
                   nsITimerCallback)
 
 class TabChild::DelayedFireContextMenuEvent MOZ_FINAL : public nsITimerCallback
@@ -597,56 +597,16 @@ TabChildBase::ProcessUpdateFrame(const F
         data.AppendFloat(cssCompositedSize.height);
         data.AppendLiteral(" }");
     data.AppendLiteral(" }");
 
     DispatchMessageManagerMessage(NS_LITERAL_STRING("Viewport:Change"), data);
     return newMetrics;
 }
 
-nsEventStatus
-TabChildBase::DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
-                                            const LayoutDevicePoint& aRefPoint,
-                                            nsIWidget* aWidget)
-{
-  MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN ||
-             aMsg == NS_MOUSE_BUTTON_UP || aMsg == NS_MOUSE_MOZLONGTAP);
-
-  WidgetMouseEvent event(true, aMsg, nullptr,
-                         WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
-  event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
-  event.time = aTime;
-  event.button = WidgetMouseEvent::eLeftButton;
-  event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
-  event.ignoreRootScrollFrame = true;
-  if (aMsg != NS_MOUSE_MOVE) {
-    event.clickCount = 1;
-  }
-  event.widget = aWidget;
-
-  return DispatchWidgetEvent(event);
-}
-
-nsEventStatus
-TabChildBase::DispatchWidgetEvent(WidgetGUIEvent& event)
-{
-  if (!event.widget)
-    return nsEventStatus_eConsumeNoDefault;
-
-  if (TabParent* capturer = TabParent::GetEventCapturer()) {
-    if (capturer->TryCapture(event)) {
-      return nsEventStatus_eConsumeNoDefault;
-    }
-  }
-  nsEventStatus status;
-  NS_ENSURE_SUCCESS(event.widget->DispatchEvent(&event, status),
-                    nsEventStatus_eConsumeNoDefault);
-  return status;
-}
-
 bool
 TabChildBase::IsAsyncPanZoomEnabled()
 {
     return mScrolling == ASYNC_PAN_ZOOM;
 }
 
 NS_IMETHODIMP
 ContentListener::HandleEvent(nsIDOMEvent* aEvent)
@@ -2150,49 +2110,35 @@ TabChild::RecvHandleSingleTap(const CSSP
 
   LayoutDevicePoint currentPoint =
       APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid, GetPresShellResolution())
     * mWidget->GetDefaultScale();;
   if (!mActiveElementManager->ActiveElementUsesStyle()) {
     // If the active element isn't visually affected by the :active style, we
     // have no need to wait the extra sActiveDurationMs to make the activation
     // visually obvious to the user.
-    FireSingleTapEvent(currentPoint);
+    APZCCallbackHelper::FireSingleTapEvent(currentPoint, mWidget);
     return true;
   }
 
   TABC_LOG("Active element uses style, scheduling timer for click event\n");
   nsCOMPtr<nsITimer> timer = do_CreateInstance(NS_TIMER_CONTRACTID);
   nsRefPtr<DelayedFireSingleTapEvent> callback =
-    new DelayedFireSingleTapEvent(this, currentPoint, timer);
+    new DelayedFireSingleTapEvent(mWidget, currentPoint, timer);
   nsresult rv = timer->InitWithCallback(callback,
                                         sActiveDurationMs,
                                         nsITimer::TYPE_ONE_SHOT);
   if (NS_FAILED(rv)) {
     // Make |callback| not hold the timer, so they will both be destructed when
     // we leave the scope of this function.
     callback->ClearTimer();
   }
   return true;
 }
 
-void
-TabChild::FireSingleTapEvent(LayoutDevicePoint aPoint)
-{
-  if (mDestroyed) {
-    return;
-  }
-  TABC_LOG("Dispatching single-tap component events to %s\n",
-    Stringify(aPoint).c_str());
-  int time = 0;
-  DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, mWidget);
-  DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, mWidget);
-  DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, aPoint, mWidget);
-}
-
 bool
 TabChild::RecvHandleLongTap(const CSSPoint& aPoint, const ScrollableLayerGuid& aGuid, const uint64_t& aInputBlockId)
 {
   TABC_LOG("Handling long tap at %s with %p %p\n",
     Stringify(aPoint).c_str(), mGlobal.get(), mTabChildGlobal.get());
 
   if (!mGlobal || !mTabChildGlobal) {
     return true;
@@ -2210,17 +2156,17 @@ TabChild::RecvHandleLongTap(const CSSPoi
 
   // If no one handle context menu, fire MOZLONGTAP event
   if (!eventHandled) {
     LayoutDevicePoint currentPoint =
         APZCCallbackHelper::ApplyCallbackTransform(aPoint, aGuid, GetPresShellResolution())
       * mWidget->GetDefaultScale();
     int time = 0;
     nsEventStatus status =
-      DispatchSynthesizedMouseEvent(NS_MOUSE_MOZLONGTAP, time, currentPoint, mWidget);
+        APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_MOZLONGTAP, time, currentPoint, mWidget);
     eventHandled = (status == nsEventStatus_eConsumeNoDefault);
     TABC_LOG("MOZLONGTAP event handled: %d\n", eventHandled);
   }
 
   SendContentReceivedInputBlock(aGuid, aInputBlockId, eventHandled);
 
   return true;
 }
@@ -2337,17 +2283,17 @@ TabChild::RecvMouseEvent(const nsString&
   return true;
 }
 
 bool
 TabChild::RecvRealMouseEvent(const WidgetMouseEvent& event)
 {
   WidgetMouseEvent localEvent(event);
   localEvent.widget = mWidget;
-  DispatchWidgetEvent(localEvent);
+  APZCCallbackHelper::DispatchWidgetEvent(localEvent);
   return true;
 }
 
 bool
 TabChild::RecvMouseWheelEvent(const WidgetWheelEvent& aEvent,
                               const ScrollableLayerGuid& aGuid,
                               const uint64_t& aInputBlockId)
 {
@@ -2362,17 +2308,17 @@ TabChild::RecvMouseWheelEvent(const Widg
 
         SendSetTargetAPZCNotification(shell, aInputBlockId, targets, waitForRefresh);
       }
     }
   }
 
   WidgetWheelEvent event(aEvent);
   event.widget = mWidget;
-  DispatchWidgetEvent(event);
+  APZCCallbackHelper::DispatchWidgetEvent(event);
 
   if (IsAsyncPanZoomEnabled()) {
     SendContentReceivedInputBlock(aGuid, aInputBlockId, event.mFlags.mDefaultPrevented);
   }
   return true;
 }
 
 static Touch*
@@ -2456,19 +2402,19 @@ TabChild::UpdateTapState(const WidgetTou
     if (std::abs(currentPoint.x - mGestureDownPoint.x) > sDragThreshold.width ||
         std::abs(currentPoint.y - mGestureDownPoint.y) > sDragThreshold.height) {
       CancelTapTracking();
     }
     return;
 
   case NS_TOUCH_END:
     if (!nsIPresShell::gPreventMouseEvents) {
-      DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, currentPoint, mWidget);
-      DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, currentPoint, mWidget);
-      DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, currentPoint, mWidget);
+      APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, currentPoint, mWidget);
+      APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, currentPoint, mWidget);
+      APZCCallbackHelper::DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, currentPoint, mWidget);
     }
     // fall through
   case NS_TOUCH_CANCEL:
     CancelTapTracking();
     return;
 
   default:
     NS_WARNING("Unknown touch event type");
@@ -2697,17 +2643,17 @@ TabChild::RecvRealTouchEvent(const Widge
 
   if (aEvent.message == NS_TOUCH_START && IsAsyncPanZoomEnabled()) {
     SendSetTargetAPZCNotification(aEvent, aGuid, aInputBlockId);
   }
 
   WidgetTouchEvent localEvent(aEvent);
   localEvent.widget = mWidget;
   // Dispatch event to content (potentially a long-running operation)
-  nsEventStatus status = DispatchWidgetEvent(localEvent);
+  nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
 
   if (!IsAsyncPanZoomEnabled()) {
     UpdateTapState(localEvent, status);
     return true;
   }
 
   if (aEvent.message == NS_TOUCH_START && localEvent.touches.Length() > 0) {
     mActiveElementManager->SetTargetElement(localEvent.touches[0]->GetTarget());
@@ -2802,17 +2748,17 @@ TabChild::RecvRealKeyEvent(const WidgetK
   // If content code called preventDefault() on a keydown event, then we don't
   // want to process any following keypress events.
   if (event.message == NS_KEY_PRESS && mIgnoreKeyPressEvent) {
     return true;
   }
 
   WidgetKeyboardEvent localEvent(event);
   localEvent.widget = mWidget;
-  nsEventStatus status = DispatchWidgetEvent(localEvent);
+  nsEventStatus status = APZCCallbackHelper::DispatchWidgetEvent(localEvent);
 
   if (event.message == NS_KEY_DOWN) {
     mIgnoreKeyPressEvent = status == nsEventStatus_eConsumeNoDefault;
   }
 
   if (localEvent.mFlags.mWantReplyFromContentProcess) {
     SendReplyKeyEvent(localEvent);
   }
@@ -2839,26 +2785,26 @@ TabChild::RecvKeyEvent(const nsString& a
   return true;
 }
 
 bool
 TabChild::RecvCompositionEvent(const WidgetCompositionEvent& event)
 {
   WidgetCompositionEvent localEvent(event);
   localEvent.widget = mWidget;
-  DispatchWidgetEvent(localEvent);
+  APZCCallbackHelper::DispatchWidgetEvent(localEvent);
   return true;
 }
 
 bool
 TabChild::RecvSelectionEvent(const WidgetSelectionEvent& event)
 {
   WidgetSelectionEvent localEvent(event);
   localEvent.widget = mWidget;
-  DispatchWidgetEvent(localEvent);
+  APZCCallbackHelper::DispatchWidgetEvent(localEvent);
   return true;
 }
 
 PDocumentRendererChild*
 TabChild::AllocPDocumentRendererChild(const nsRect& documentRect,
                                       const mozilla::gfx::Matrix& transform,
                                       const nsString& bgcolor,
                                       const uint32_t& renderFlags,
--- a/dom/ipc/TabChild.h
+++ b/dom/ipc/TabChild.h
@@ -191,20 +191,16 @@ public:
     // change, this function doesn't do anything.  However, it should
     // not be called all the time as it is fairly expensive.
     bool HandlePossibleViewportChange(const ScreenIntSize& aOldScreenSize);
     virtual bool DoUpdateZoomConstraints(const uint32_t& aPresShellId,
                                          const mozilla::layers::FrameMetrics::ViewID& aViewId,
                                          const bool& aIsRoot,
                                          const mozilla::layers::ZoomConstraints& aConstraints) = 0;
 
-    nsEventStatus DispatchSynthesizedMouseEvent(uint32_t aMsg, uint64_t aTime,
-                                                const LayoutDevicePoint& aRefPoint,
-                                                nsIWidget* aWidget);
-
 protected:
     virtual ~TabChildBase();
     CSSSize GetPageSize(nsCOMPtr<nsIDocument> aDocument, const CSSSize& aViewport);
 
     // Get the DOMWindowUtils for the top-level window in this tab.
     already_AddRefed<nsIDOMWindowUtils> GetDOMWindowUtils();
     // Get the Document for the top-level window in this tab.
     already_AddRefed<nsIDocument> GetDocument() const;
@@ -216,18 +212,16 @@ protected:
     // Wraps up a JSON object as a structured clone and sends it to the browser
     // chrome script.
     //
     // XXX/bug 780335: Do the work the browser chrome script does in C++ instead
     // so we don't need things like this.
     void DispatchMessageManagerMessage(const nsAString& aMessageName,
                                        const nsAString& aJSONData);
 
-    nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& event);
-
     void InitializeRootMetrics();
 
     mozilla::layers::FrameMetrics ProcessUpdateFrame(const mozilla::layers::FrameMetrics& aFrameMetrics);
 
     bool UpdateFrameHandler(const mozilla::layers::FrameMetrics& aFrameMetrics);
 
 protected:
     CSSSize mOldViewportSize;
@@ -654,17 +648,16 @@ private:
     bool mDidFakeShow;
     bool mNotified;
     bool mTriedBrowserInit;
     ScreenOrientation mOrientation;
     bool mUpdateHitRegion;
     bool mPendingTouchPreventedResponse;
     ScrollableLayerGuid mPendingTouchPreventedGuid;
     uint64_t mPendingTouchPreventedBlockId;
-    void FireSingleTapEvent(LayoutDevicePoint aPoint);
 
     bool mTouchEndCancelled;
     bool mEndTouchIsClick;
 
     bool mIgnoreKeyPressEvent;
     nsRefPtr<ActiveElementManager> mActiveElementManager;
     bool mHasValidInnerSize;
     bool mDestroyed;
--- a/gfx/layers/apz/util/APZCCallbackHelper.cpp
+++ b/gfx/layers/apz/util/APZCCallbackHelper.cpp
@@ -1,26 +1,33 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "APZCCallbackHelper.h"
+
 #include "gfxPlatform.h" // For gfxPlatform::UseTiling
+#include "mozilla/dom/TabParent.h"
 #include "nsIScrollableFrame.h"
 #include "nsLayoutUtils.h"
 #include "nsIDOMElement.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIContent.h"
 #include "nsIDocument.h"
 #include "nsIDOMWindow.h"
 
+#define APZCCH_LOG(...)
+// #define APZCCH_LOG(...) printf_stderr("APZCCH: " __VA_ARGS__)
+
 namespace mozilla {
 namespace layers {
 
+using dom::TabParent;
+
 bool
 APZCCallbackHelper::HasValidPresShellId(nsIDOMWindowUtils* aUtils,
                                         const FrameMetrics& aMetrics)
 {
     MOZ_ASSERT(aUtils);
 
     uint32_t presShellId;
     nsresult rv = aUtils->GetPresShellId(&presShellId);
@@ -355,10 +362,72 @@ APZCCallbackHelper::ApplyCallbackTransfo
                                            float aPresShellResolution)
 {
     LayoutDevicePoint point = LayoutDevicePoint(aPoint.x, aPoint.y);
     point = ApplyCallbackTransform(point / aScale, aGuid, aPresShellResolution) * aScale;
     LayoutDeviceIntPoint ret = gfx::RoundedToInt(point);
     return nsIntPoint(ret.x, ret.y);
 }
 
+nsEventStatus
+APZCCallbackHelper::DispatchWidgetEvent(WidgetGUIEvent& aEvent)
+{
+  if (!aEvent.widget)
+    return nsEventStatus_eConsumeNoDefault;
+
+  // A nested process may be capturing events.
+  if (TabParent* capturer = TabParent::GetEventCapturer()) {
+    if (capturer->TryCapture(aEvent)) {
+      // Only touch events should be captured, and touch events from a parent
+      // process should not make it here. Capture for those is done elsewhere
+      // (for gonk, in nsWindow::DispatchTouchInputViaAPZ).
+      MOZ_ASSERT(!XRE_IsParentProcess());
+
+      return nsEventStatus_eConsumeNoDefault;
+    }
+  }
+  nsEventStatus status;
+  NS_ENSURE_SUCCESS(aEvent.widget->DispatchEvent(&aEvent, status),
+                    nsEventStatus_eConsumeNoDefault);
+  return status;
+}
+
+nsEventStatus
+APZCCallbackHelper::DispatchSynthesizedMouseEvent(uint32_t aMsg,
+                                                  uint64_t aTime,
+                                                  const LayoutDevicePoint& aRefPoint,
+                                                  nsIWidget* aWidget)
+{
+  MOZ_ASSERT(aMsg == NS_MOUSE_MOVE || aMsg == NS_MOUSE_BUTTON_DOWN ||
+             aMsg == NS_MOUSE_BUTTON_UP || aMsg == NS_MOUSE_MOZLONGTAP);
+
+  WidgetMouseEvent event(true, aMsg, nullptr,
+                         WidgetMouseEvent::eReal, WidgetMouseEvent::eNormal);
+  event.refPoint = LayoutDeviceIntPoint(aRefPoint.x, aRefPoint.y);
+  event.time = aTime;
+  event.button = WidgetMouseEvent::eLeftButton;
+  event.inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
+  event.ignoreRootScrollFrame = true;
+  if (aMsg != NS_MOUSE_MOVE) {
+    event.clickCount = 1;
+  }
+  event.widget = aWidget;
+
+  return DispatchWidgetEvent(event);
+}
+
+void
+APZCCallbackHelper::FireSingleTapEvent(const LayoutDevicePoint& aPoint,
+                                       nsIWidget* aWidget)
+{
+  if (aWidget->Destroyed()) {
+    return;
+  }
+  APZCCH_LOG("Dispatching single-tap component events to %s\n",
+    Stringify(aPoint).c_str());
+  int time = 0;
+  DispatchSynthesizedMouseEvent(NS_MOUSE_MOVE, time, aPoint, aWidget);
+  DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_DOWN, time, aPoint, aWidget);
+  DispatchSynthesizedMouseEvent(NS_MOUSE_BUTTON_UP, time, aPoint, aWidget);
+}
+
 }
 }
--- a/gfx/layers/apz/util/APZCCallbackHelper.h
+++ b/gfx/layers/apz/util/APZCCallbackHelper.h
@@ -2,20 +2,22 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_layers_APZCCallbackHelper_h
 #define mozilla_layers_APZCCallbackHelper_h
 
 #include "FrameMetrics.h"
+#include "mozilla/EventForwards.h"
 #include "nsIDOMWindowUtils.h"
 
 class nsIContent;
 class nsIDocument;
+class nsIWidget;
 template<class T> struct already_AddRefed;
 
 namespace mozilla {
 namespace layers {
 
 /* This class contains some helper methods that facilitate implementing the
    GeckoContentController callback interface required by the AsyncPanZoomController.
    Since different platforms need to implement this interface in similar-but-
@@ -99,14 +101,31 @@ public:
 
     /* Same as above, but operates on nsIntPoint that are assumed to be in LayoutDevice
        pixel space. Requires an additonal |aScale| parameter to convert between CSS and
        LayoutDevice space. */
     static nsIntPoint ApplyCallbackTransform(const nsIntPoint& aPoint,
                                              const ScrollableLayerGuid& aGuid,
                                              const CSSToLayoutDeviceScale& aScale,
                                              float aPresShellResolution);
+
+    /* Dispatch a widget event via the widget stored in the event, if any.
+     * In a child process, allows the TabParent event-capture mechanism to
+     * intercept the event. */
+    static nsEventStatus DispatchWidgetEvent(WidgetGUIEvent& aEvent);
+
+    /* Synthesize a mouse event with the given parameters, and dispatch it
+     * via the given widget. */
+    static nsEventStatus DispatchSynthesizedMouseEvent(uint32_t aMsg,
+                                                       uint64_t aTime,
+                                                       const LayoutDevicePoint& aRefPoint,
+                                                       nsIWidget* aWidget);
+
+    /* Fire a single-tap event at the given point. The event is dispatched
+     * via the given widget. */
+    static void FireSingleTapEvent(const LayoutDevicePoint& aPoint,
+                                   nsIWidget* aWidget);
 };
 
 }
 }
 
 #endif /* mozilla_layers_APZCCallbackHelper_h */