Bug 1119355 - Add a dummy touch listener on nsRangeFrame so the APZ code knows it handles them. r=roc
authorKartikaya Gupta <kgupta@mozilla.com>
Tue, 13 Jan 2015 09:06:37 -0500
changeset 250699 86fa41494e58f9f87535d89f460a368f2185958e
parent 250698 2ecbda2b89b03fd3f3ee748c13bd7d796213c0f7
child 250700 ae23c2a328cbf8dba41e57044ccf841e0e7914fd
push id4610
push userjlund@mozilla.com
push dateMon, 30 Mar 2015 18:32:55 +0000
treeherdermozilla-beta@4df54044d9ef [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs1119355
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 1119355 - Add a dummy touch listener on nsRangeFrame so the APZ code knows it handles them. r=roc
layout/forms/nsRangeFrame.cpp
layout/forms/nsRangeFrame.h
--- a/layout/forms/nsRangeFrame.cpp
+++ b/layout/forms/nsRangeFrame.cpp
@@ -30,16 +30,18 @@
 #include "nsAccessibilityService.h"
 #endif
 
 #define LONG_SIDE_TO_SHORT_SIDE_RATIO 10
 
 using namespace mozilla;
 using namespace mozilla::dom;
 
+NS_IMPL_ISUPPORTS(nsRangeFrame::DummyTouchListener, nsIDOMEventListener)
+
 nsIFrame*
 NS_NewRangeFrame(nsIPresShell* aPresShell, nsStyleContext* aContext)
 {
   return new (aPresShell) nsRangeFrame(aContext);
 }
 
 nsRangeFrame::nsRangeFrame(nsStyleContext* aContext)
   : nsContainerFrame(aContext)
@@ -57,36 +59,27 @@ NS_QUERYFRAME_HEAD(nsRangeFrame)
   NS_QUERYFRAME_ENTRY(nsIAnonymousContentCreator)
 NS_QUERYFRAME_TAIL_INHERITING(nsContainerFrame)
 
 void
 nsRangeFrame::Init(nsIContent*       aContent,
                    nsContainerFrame* aParent,
                    nsIFrame*         aPrevInFlow)
 {
-  // B2G's AsyncPanZoomController::ReceiveInputEvent handles touch events
-  // without checking whether the out-of-process document that it controls
-  // will handle them, unless it has been told that the document might do so.
-  // This is for perf reasons, otherwise it has to wait for the event to be
-  // round-tripped to the other process and back, delaying panning, etc.
-  // We must call SetHasTouchEventListeners() in order to get APZC to wait
-  // until the event has been round-tripped and check whether it has been
-  // handled, otherwise B2G will end up panning the document when the user
-  // tries to drag our thumb.
-  //
-  nsIPresShell* presShell = PresContext()->GetPresShell();
-  if (presShell) {
-    nsIDocument* document = presShell->GetDocument();
-    if (document) {
-      nsPIDOMWindow* innerWin = document->GetInnerWindow();
-      if (innerWin) {
-        innerWin->SetHasTouchEventListeners();
-      }
-    }
+  // With APZ enabled, touch events may be handled directly by the APZC code
+  // if the APZ knows that there is no content interested in the touch event.
+  // The range input element *is* interested in touch events, but doesn't use
+  // the usual mechanism (i.e. registering an event listener) to handle touch
+  // input. Instead, we do it here so that the APZ finds out about it, and
+  // makes sure to wait for content to run handlers before handling the touch
+  // input itself.
+  if (!mDummyTouchListener) {
+    mDummyTouchListener = new DummyTouchListener();
   }
+  aContent->AddEventListener(NS_LITERAL_STRING("touchstart"), mDummyTouchListener, false);
 
   nsStyleSet *styleSet = PresContext()->StyleSet();
 
   mOuterFocusStyle =
     styleSet->ProbePseudoElementStyle(aContent->AsElement(),
                                       nsCSSPseudoElements::ePseudo_mozFocusOuter,
                                       StyleContext());
 
@@ -94,16 +87,19 @@ nsRangeFrame::Init(nsIContent*       aCo
 }
 
 void
 nsRangeFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
   NS_ASSERTION(!GetPrevContinuation() && !GetNextContinuation(),
                "nsRangeFrame should not have continuations; if it does we "
                "need to call RegUnregAccessKey only for the first.");
+
+  mContent->RemoveEventListener(NS_LITERAL_STRING("touchstart"), mDummyTouchListener, false);
+
   nsFormControlFrame::RegUnRegAccessKey(static_cast<nsIFrame*>(this), false);
   nsContentUtils::DestroyAnonymousContent(&mTrackDiv);
   nsContentUtils::DestroyAnonymousContent(&mProgressDiv);
   nsContentUtils::DestroyAnonymousContent(&mThumbDiv);
   nsContainerFrame::DestroyFrom(aDestructRoot);
 }
 
 nsresult
--- a/layout/forms/nsRangeFrame.h
+++ b/layout/forms/nsRangeFrame.h
@@ -6,16 +6,17 @@
 #ifndef nsRangeFrame_h___
 #define nsRangeFrame_h___
 
 #include "mozilla/Attributes.h"
 #include "mozilla/Decimal.h"
 #include "mozilla/EventForwards.h"
 #include "nsContainerFrame.h"
 #include "nsIAnonymousContentCreator.h"
+#include "nsIDOMEventListener.h"
 #include "nsCOMPtr.h"
 
 class nsBaseContentList;
 class nsDisplayRangeFocusRing;
 
 class nsRangeFrame : public nsContainerFrame,
                      public nsIAnonymousContentCreator
 {
@@ -174,11 +175,30 @@ private:
    * @see nsRangeFrame::CreateAnonymousContent
    */
   nsCOMPtr<Element> mThumbDiv;
 
   /**
    * Cached style context for -moz-focus-outer CSS pseudo-element style.
    */
   nsRefPtr<nsStyleContext> mOuterFocusStyle;
+
+  class DummyTouchListener MOZ_FINAL : public nsIDOMEventListener
+  {
+  private:
+    ~DummyTouchListener() {}
+
+  public:
+    NS_DECL_ISUPPORTS
+
+    NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent) MOZ_OVERRIDE
+    {
+      return NS_OK;
+    }
+  };
+
+  /**
+   * A no-op touch-listener used for APZ purposes (see nsRangeFrame::Init).
+   */
+  nsRefPtr<DummyTouchListener> mDummyTouchListener;
 };
 
 #endif