diff --git a/dom/browser-element/BrowserElementChild.js b/dom/browser-element/BrowserElementChild.js index d93b2002d204..81747115e43f 100644 --- a/dom/browser-element/BrowserElementChild.js +++ b/dom/browser-element/BrowserElementChild.js @@ -42,19 +42,11 @@ if (!('BrowserElementIsPreloaded' in this)) { } } - if (docShell.asyncPanZoomEnabled === false) { - Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanningAPZDisabled.js"); - ContentPanningAPZDisabled.init(); - } - Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanning.js"); ContentPanning.init(); Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js"); } else { - if (docShell.asyncPanZoomEnabled === false) { - ContentPanningAPZDisabled.init(); - } ContentPanning.init(); } diff --git a/dom/browser-element/BrowserElementPanning.js b/dom/browser-element/BrowserElementPanning.js index 3800c505575a..828a430b1098 100644 --- a/dom/browser-element/BrowserElementPanning.js +++ b/dom/browser-element/BrowserElementPanning.js @@ -12,6 +12,8 @@ let { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components; Cu.import("resource://gre/modules/Services.jsm"); Cu.import("resource://gre/modules/Geometry.jsm"); +var global = this; + const kObservedEvents = [ "BEC:ShownModalPrompt", "Activity:Success", @@ -19,7 +21,21 @@ const kObservedEvents = [ ]; 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() { + // If APZ is enabled, we do active element handling in C++ + // (see widget/xpwidgets/ActiveElementManager.h), and panning + // itself in APZ, so we don't need to handle any touch events here. + if (docShell.asyncPanZoomEnabled === false) { + this._setupListenersForPanning(); + } + addEventListener("unload", this._unloadHandler.bind(this), /* useCapture = */ false, @@ -33,16 +49,441 @@ const ContentPanning = { }); }, + _setupListenersForPanning: function cp_setupListenersForPanning() { + let events; + + if (content.TouchEvent) { + events = ['touchstart', 'touchend', 'touchmove']; + 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) + .processType == Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT; + this.hybridEvents = isParentProcess; +#endif + } else { + // Touch events aren't supported, so fall back on mouse. + events = ['mousedown', 'mouseup', 'mousemove']; + this.watchedEventsType = 'mouse'; + } + + 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)); + }, + + handleEvent: function cp_handleEvent(evt) { + // Ignore events targeting an oop