Bug 946339 - Tap and hold does not highlight the targeted element. r=fabrice, a=1.3+
authorVivien Nicolas <21@vingtetun.org>
Thu, 12 Dec 2013 11:43:45 +0100
changeset 168739 d99b36ffd3a67577f8ed6d108be03883325923c8
parent 168738 f9f15a1dceaea6ee221b6918652b458d8eca4553
child 168740 e2ae9f2da960e44d2c6e0d444fa9ce8bf0b87c27
push id4722
push userryanvm@gmail.com
push dateFri, 13 Dec 2013 14:44:54 +0000
treeherdermozilla-aurora@18037644cdec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice, 1
bugs946339
milestone28.0a2
Bug 946339 - Tap and hold does not highlight the targeted element. r=fabrice, a=1.3+
dom/browser-element/BrowserElementPanning.js
--- a/dom/browser-element/BrowserElementPanning.js
+++ b/dom/browser-element/BrowserElementPanning.js
@@ -40,60 +40,50 @@ const ContentPanning = {
       this.hybridEvents = isParentProcess;
 #endif
     } catch(e) {
       // Touch events aren't supported, so fall back on mouse.
       events = ['mousedown', 'mouseup', 'mousemove'];
       this.watchedEventsType = 'mouse';
     }
 
-    // If we are using an AsyncPanZoomController for the parent frame,
-    // it will handle subframe scrolling too. We don't need to listen for
-    // these events.
-    if (!docShell.asyncPanZoomEnabled) {
-      let els = Cc["@mozilla.org/eventlistenerservice;1"]
-                  .getService(Ci.nsIEventListenerService);
+    let els = Cc["@mozilla.org/eventlistenerservice;1"]
+                .getService(Ci.nsIEventListenerService);
 
-      events.forEach(function(type) {
-        // Using the system group for mouse/touch events to avoid
-        // missing events if .stopPropagation() has been called.
-        els.addSystemEventListener(global, type,
-                                   this.handleEvent.bind(this),
-                                   /* useCapture = */ false);
-      }.bind(this));
-    }
+    events.forEach(function(type) {
+      // Using the system group for mouse/touch events to avoid
+      // missing events if .stopPropagation() has been called.
+      els.addSystemEventListener(global, type,
+                                 this.handleEvent.bind(this),
+                                 /* useCapture = */ false);
+    }.bind(this));
 
     addMessageListener("Viewport:Change", this._recvViewportChange.bind(this));
     addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this));
     addEventListener("visibilitychange", this._handleVisibilityChange.bind(this));
     Services.obs.addObserver(this, "BEC:ShownModalPrompt", false);
     Services.obs.addObserver(this, "Activity:Success", false);
     Services.obs.addObserver(this, "Activity:Error", false);
   },
 
   handleEvent: function cp_handleEvent(evt) {
+    this._tryDelayMouseEvents();
+
     if (evt.defaultPrevented || evt.multipleActionsPrevented) {
       // clean up panning state even if touchend/mouseup has been preventDefault.
       if(evt.type === 'touchend' || evt.type === 'mouseup') {
         if (this.dragging &&
             (this.watchedEventsType === 'mouse' ||
              this.findPrimaryPointer(evt.changedTouches))) {
           this._finishPanning();
         }
       }
       return;
     }
 
-    let start = Date.now();
-    let thread = Services.tm.currentThread;
-    while (this._delayEvents && (Date.now() - start) < this._activeDurationMs) {
-      thread.processNextEvent(true);
-    }
-    this._delayEvents = false;
-
     switch (evt.type) {
       case 'mousedown':
       case 'touchstart':
         this.onTouchStart(evt);
         break;
       case 'mousemove':
       case 'touchmove':
         this.onTouchMove(evt);
@@ -184,17 +174,18 @@ const ContentPanning = {
         this.preventNextClick = true;
     }
 
     this.position.set(screenX, screenY);
     KineticPanning.record(new Point(0, 0), evt.timeStamp);
 
     // We prevent start events to avoid sending a focus event at the end of this
     // touch series. See bug 889717.
-    if (this.panning || this.preventNextClick) {
+    if (docShell.asyncPanZoomEnabled === false &&
+        (this.panning || this.preventNextClick)) {
       evt.preventDefault();
     }
   },
 
   onTouchEnd: function cp_onTouchEnd(evt) {
     let touch = null;
     if (!this.dragging ||
         (this.watchedEventsType == 'touch' &&
@@ -223,30 +214,25 @@ const ContentPanning = {
     }
 
     if (this.target && click && (this.panning || this.preventNextClick)) {
       if (this.hybridEvents) {
         let target = this.target;
         let view = target.ownerDocument ? target.ownerDocument.defaultView
                                         : target;
         view.addEventListener('click', this, true, true);
-      } else {
+      } else if (docShell.asyncPanZoomEnabled === false) {
         // We prevent end events to avoid sending a focus event. See bug 889717.
         evt.preventDefault();
       }
     } else if (this.target && click && !this.panning) {
       this.notify(this._activationTimer);
 
       this._delayEvents = true;
-      let start = Date.now();
-      let thread = Services.tm.currentThread;
-      while (this._delayEvents && (Date.now() - start) < this._activeDurationMs) {
-        thread.processNextEvent(true);
-      }
-      this._delayEvents = false;
+      this._tryDelayMouseEvents();
     }
 
     this._finishPanning();
 
     // Now that we're done, avoid entraining the thing we just panned.
     this.pointerDownTarget = null;
   },
 
@@ -273,17 +259,22 @@ const ContentPanning = {
     KineticPanning.record(delta, evt.timeStamp);
 
     // There's no possibility of us panning anything.
     if (!this.scrollCallback) {
       return;
     }
 
     let isPan = KineticPanning.isPan();
-    this.scrollCallback(delta.scale(-1));
+
+    // If the application is not managed by the AsyncPanZoomController, then
+    // scroll manually.
+    if (docShell.asyncPanZoomEnabled === false) {
+      this.scrollCallback(delta.scale(-1));
+    }
 
     // If we've detected a pan gesture, cancel the active state of the
     // current target.
     if (!this.panning && isPan) {
       this.panning = true;
       this._resetActive();
       this._activationTimer.cancel();
     }
@@ -449,16 +440,25 @@ const ContentPanning = {
   },
 
   get _activeDurationMs() {
     let duration = Services.prefs.getIntPref('ui.touch_activation.duration_ms');
     delete this._activeDurationMs;
     return this._activeDurationMs = duration;
   },
 
+  _tryDelayMouseEvents: function cp_tryDelayMouseEvents() {
+    let start = Date.now();
+    let thread = Services.tm.currentThread;
+    while (this._delayEvents && (Date.now() - start) < this._activeDurationMs) {
+      thread.processNextEvent(true);
+    }
+    this._delayEvents = false;
+  },
+
   _resetActive: function cp_resetActive() {
     let elt = this.pointerDownTarget || this.target;
     let root = elt.ownerDocument || elt.document;
     this._setActive(root.documentElement);
   },
 
   _resetHover: function cp_resetHover() {
     const kStateHover = 0x00000004;
@@ -589,17 +589,19 @@ const ContentPanning = {
   },
 
   _finishPanning: function() {
     this._resetActive();
     this.dragging = false;
     delete this.primaryPointerId;
     this._activationTimer.cancel();
 
-    if (this.panning) {
+    // If there is a scroll action but the application is not managed by
+    // the AsyncPanZoom controller, let's do a manual kinetic panning action.
+    if (this.panning && docShell.asyncPanZoomEnabled === false) {
       KineticPanning.start(this);
     }
   }
 };
 
 // Min/max velocity of kinetic panning. This is in pixels/millisecond.
 const kMinVelocity = 0.2;
 const kMaxVelocity = 6;