diff -r 000000000000 -r 6474c204b198 dom/browser-element/BrowserElementPanning.js --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/dom/browser-element/BrowserElementPanning.js Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,860 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=2 sw=2 sts=2 et: */ + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +"use strict"; +dump("############################### browserElementPanning.js loaded\n"); + +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", + "Activity:Error" +]; + +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, + /* wantsUntrusted = */ false); + + addMessageListener("Viewport:Change", this._recvViewportChange.bind(this)); + addMessageListener("Gesture:DoubleTap", this._recvDoubleTap.bind(this)); + addEventListener("visibilitychange", this._handleVisibilityChange.bind(this)); + kObservedEvents.forEach((topic) => { + Services.obs.addObserver(this, topic, false); + }); + }, + + _setupListenersForPanning: function cp_setupListenersForPanning() { + var events; + try { + content.document.createEvent('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 + } catch(e) { + // 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 a