Bug 863702 - [B2G] :active state is sometime not rendered if you tap quickly. r=fabrice
☠☠ backed out by eb0f1d1bd9ca ☠ ☠
authorVivien Nicolas <vnicolas@mozilla.com>
Fri, 11 Oct 2013 17:29:19 +0200
changeset 164334 0f1efa209f534408d2188a55573e269c3a391dce
parent 164296 4a2c4921ff7cabb2ca41bdf30b0f58b0a9e16c67
child 164335 b4c3caf8f741c9465af765276d79faccf051fd85
push id3066
push userakeybl@mozilla.com
push dateMon, 09 Dec 2013 19:58:46 +0000
treeherdermozilla-beta@a31a0dce83aa [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfabrice
bugs863702
milestone27.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 863702 - [B2G] :active state is sometime not rendered if you tap quickly. r=fabrice
dom/browser-element/BrowserElementPanning.js
--- a/dom/browser-element/BrowserElementPanning.js
+++ b/dom/browser-element/BrowserElementPanning.js
@@ -19,20 +19,26 @@ const ContentPanning = {
   // Are we listening to touch or mouse events?
   watchedEventsType: '',
 
   // Are mouse events being delivered to this content along with touch
   // events, in violation of spec?
   hybridEvents: false,
 
   init: function cp_init() {
+    let els = Cc["@mozilla.org/eventlistenerservice;1"]
+                .getService(Ci.nsIEventListenerService);
+
     var events;
     try {
       content.document.createEvent('TouchEvent');
       events = ['touchstart', 'touchend', 'touchmove'];
+      els.addSystemEventListener(global, 'mousedown',
+                                 this.handleEvent.bind(this),
+                                 /* useCapture = */ true);
       this.watchedEventsType = 'touch';
 #ifdef MOZ_WIDGET_GONK
       // The gonk widget backend does not deliver mouse events per
       // spec.  Third-party content isn't exposed to this behavior,
       // but that behavior creates some extra work for us here.
       let appInfo = Cc["@mozilla.org/xre/app-info;1"];
       let isParentProcess =
         !appInfo || appInfo.getService(Ci.nsIXULRuntime)
@@ -44,19 +50,16 @@ const ContentPanning = {
       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 (!this._asyncPanZoomForViewportFrame) {
-      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));
     }
@@ -75,16 +78,34 @@ const ContentPanning = {
           this._finishPanning();
         }
       }
       return;
     }
 
     switch (evt.type) {
       case 'mousedown':
+        // Touch events will generate a quick sequence of mouse events
+        // (mousemove, mousedown, mouseup) right after touchend. But
+        // the :active pseudo state is set during mousedown and is
+        // cleared during mouseup. The above code will delay the
+        // mouseup for a small amount of ms.
+        if (this.watchedEventsType == 'touch' && !this.hybridEvents) {
+          this._setActive(evt.target);
+
+          var start = Date.now();
+          var thread = Services.tm.currentThread;
+          while ((Date.now() - start) < 100) {
+            thread.processNextEvent(true);
+          }
+
+          // Don't consider this mousedown as the beginning of a
+          // panning sequence and just bail out.
+          return;
+        }
       case 'touchstart':
         this.onTouchStart(evt);
         break;
       case 'mousemove':
       case 'touchmove':
         this.onTouchMove(evt);
         break;
       case 'mouseup':