diff --git a/dom/browser-element/BrowserElementPanning.js b/dom/browser-element/BrowserElementPanning.js index 614da34064a6..14a513796180 100644 --- a/dom/browser-element/BrowserElementPanning.js +++ b/dom/browser-element/BrowserElementPanning.js @@ -24,10 +24,16 @@ const ContentPanning = { 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 @@ -49,9 +55,6 @@ const ContentPanning = { // 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. @@ -80,6 +83,24 @@ const ContentPanning = { 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;