--- a/dom/browser-element/BrowserElementChild.js
+++ b/dom/browser-element/BrowserElementChild.js
@@ -53,26 +53,16 @@ if (!BrowserElementIsReady) {
if (isTopBrowserElement(docShell)) {
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js");
}
} else {
// rocketbar in system app and other in-process case (ex. B2G desktop client)
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js");
}
- if (Services.prefs.getIntPref("dom.w3c_touch_events.enabled") != 0) {
- 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 (Services.prefs.getIntPref("dom.w3c_touch_events.enabled") != 0) {
if (docShell.asyncPanZoomEnabled === false) {
ContentPanningAPZDisabled.init();
}
ContentPanning.init();
}
--- a/dom/browser-element/BrowserElementChildPreload.js
+++ b/dom/browser-element/BrowserElementChildPreload.js
@@ -450,18 +450,16 @@ BrowserElementChild.prototype = {
.getInterface(Ci.nsIDOMWindowUtils);
args.windowID = { outer: utils.outerWindowID,
inner: this._tryGetInnerWindowID(win) };
sendAsyncMsg('showmodalprompt', args);
let returnValue = this._waitForResult(win);
- Services.obs.notifyObservers(null, 'BEC:ShownModalPrompt', null);
-
if (args.promptType == 'prompt' ||
args.promptType == 'confirm' ||
args.promptType == 'custom-prompt') {
return returnValue;
}
},
/**
deleted file mode 100644
--- a/dom/browser-element/BrowserElementPanning.js
+++ /dev/null
@@ -1,256 +0,0 @@
-/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 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";
-
-function debug(msg) {
- // dump("BrowserElementPanning - " + msg + "\n");
-}
-
-debug("loaded");
-
-var { classes: Cc, interfaces: Ci, results: Cr, utils: Cu } = Components;
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Geometry.jsm");
-
-var kObservedEvents = [
- "BEC:ShownModalPrompt",
- "Activity:Success",
- "Activity:Error"
-];
-
-var ContentPanning = {
- init: function cp_init() {
- addEventListener("unload", this,
- /* useCapture = */ false, /* wantsUntrusted = */ false);
- addMessageListener("Viewport:Change", this);
- addMessageListener("Gesture:DoubleTap", this);
- addEventListener("visibilitychange", this);
- kObservedEvents.forEach((topic) => {
- Services.obs.addObserver(this, topic, false);
- });
- },
-
- destroy: function() {
- removeEventListener("unload", this,
- /* useCapture = */ false, /* wantsUntrusted = */ false);
- removeMessageListener("Viewport:Change", this);
- removeMessageListener("Gesture:DoubleTap", this);
- removeEventListener("visibilitychange", this);
- kObservedEvents.forEach((topic) => {
- Services.obs.removeObserver(this, topic, false);
- });
- },
-
- handleEvent: function(event) {
- switch (event.type) {
- case "unload":
- this._unloadHandler(event);
- break;
- case "visibilitychange":
- this._handleVisibilityChange(event);
- break;
- }
- },
-
- receiveMessage: function(message) {
- switch (message.name) {
- case "Viewport:Change":
- this._recvViewportChange(message);
- break;
- case "Gesture:DoubleTap":
- this._recvDoubleTap(message);
- break;
- }
- },
-
- observe: function cp_observe(subject, topic, data) {
- this._resetHover();
- },
-
- get _domUtils() {
- delete this._domUtils;
- return this._domUtils = Cc['@mozilla.org/inspector/dom-utils;1']
- .getService(Ci.inIDOMUtils);
- },
-
- _resetHover: function cp_resetHover() {
- const kStateHover = 0x00000004;
- try {
- let element = content.document.createElement('foo');
- this._domUtils.setContentState(element, kStateHover);
- } catch(e) {}
- },
-
- _recvViewportChange: function(data) {
- let metrics = data.json;
- this._viewport = new Rect(metrics.x, metrics.y,
- metrics.viewport.width,
- metrics.viewport.height);
- this._cssCompositedRect = new Rect(metrics.x, metrics.y,
- metrics.cssCompositedRect.width,
- metrics.cssCompositedRect.height);
- this._cssPageRect = new Rect(metrics.cssPageRect.x,
- metrics.cssPageRect.y,
- metrics.cssPageRect.width,
- metrics.cssPageRect.height);
- },
-
- _recvDoubleTap: function(data) {
- data = data.json;
-
- // We haven't received a metrics update yet; don't do anything.
- if (this._viewport == null) {
- return;
- }
-
- let win = content;
-
- let element = ElementTouchHelper.anyElementFromPoint(win, data.x, data.y);
- if (!element) {
- this._zoomOut();
- return;
- }
-
- while (element && !this._shouldZoomToElement(element))
- element = element.parentNode;
-
- if (!element) {
- this._zoomOut();
- } else {
- const margin = 15;
- let rect = ElementTouchHelper.getBoundingContentRect(element);
-
- let cssPageRect = this._cssPageRect;
- let viewport = this._viewport;
- let bRect = new Rect(Math.max(cssPageRect.x, rect.x - margin),
- rect.y,
- rect.w + 2 * margin,
- rect.h);
- // constrict the rect to the screen's right edge
- bRect.width = Math.min(bRect.width, cssPageRect.right - bRect.x);
-
- // if the rect is already taking up most of the visible area and is stretching the
- // width of the page, then we want to zoom out instead.
- if (this._isRectZoomedIn(bRect, this._cssCompositedRect)) {
- this._zoomOut();
- return;
- }
-
- rect.x = Math.round(bRect.x);
- rect.y = Math.round(bRect.y);
- rect.w = Math.round(bRect.width);
- rect.h = Math.round(bRect.height);
-
- // if the block we're zooming to is really tall, and the user double-tapped
- // more than a screenful of height from the top of it, then adjust the y-coordinate
- // so that we center the actual point the user double-tapped upon. this prevents
- // flying to the top of a page when double-tapping to zoom in (bug 761721).
- // the 1.2 multiplier is just a little fuzz to compensate for bRect including horizontal
- // margins but not vertical ones.
- let cssTapY = viewport.y + data.y;
- if ((bRect.height > rect.h) && (cssTapY > rect.y + (rect.h * 1.2))) {
- rect.y = cssTapY - (rect.h / 2);
- }
-
- Services.obs.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
- }
- },
-
- _handleVisibilityChange: function(evt) {
- if (!evt.target.hidden)
- return;
-
- this._resetHover();
- },
-
- _shouldZoomToElement: function(aElement) {
- let win = aElement.ownerDocument.defaultView;
- if (win.getComputedStyle(aElement, null).display == "inline")
- return false;
- if (aElement instanceof Ci.nsIDOMHTMLLIElement)
- return false;
- if (aElement instanceof Ci.nsIDOMHTMLQuoteElement)
- return false;
- return true;
- },
-
- _zoomOut: function() {
- let rect = new Rect(0, 0, 0, 0);
- Services.obs.notifyObservers(docShell, 'browser-zoom-to-rect', JSON.stringify(rect));
- },
-
- _isRectZoomedIn: function(aRect, aViewport) {
- // This function checks to see if the area of the rect visible in the
- // viewport (i.e. the "overlapArea" variable below) is approximately
- // the max area of the rect we can show.
- let vRect = new Rect(aViewport.x, aViewport.y, aViewport.width, aViewport.height);
- let overlap = vRect.intersect(aRect);
- let overlapArea = overlap.width * overlap.height;
- let availHeight = Math.min(aRect.width * vRect.height / vRect.width, aRect.height);
- let showing = overlapArea / (aRect.width * availHeight);
- let ratioW = (aRect.width / vRect.width);
- let ratioH = (aRect.height / vRect.height);
-
- return (showing > 0.9 && (ratioW > 0.9 || ratioH > 0.9));
- },
-
- _unloadHandler: function() {
- kObservedEvents.forEach((topic) => {
- Services.obs.removeObserver(this, topic);
- });
- }
-};
-
-var ElementTouchHelper = {
- anyElementFromPoint: function(aWindow, aX, aY) {
- let cwu = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
- let elem = cwu.elementFromPoint(aX, aY, true, true);
-
- let HTMLIFrameElement = Ci.nsIDOMHTMLIFrameElement;
- let HTMLFrameElement = Ci.nsIDOMHTMLFrameElement;
- while (elem && (elem instanceof HTMLIFrameElement || elem instanceof HTMLFrameElement)) {
- let rect = elem.getBoundingClientRect();
- aX -= rect.left;
- aY -= rect.top;
- cwu = elem.contentDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
- elem = cwu.elementFromPoint(aX, aY, true, true);
- }
-
- return elem;
- },
-
- getBoundingContentRect: function(aElement) {
- if (!aElement)
- return {x: 0, y: 0, w: 0, h: 0};
-
- let document = aElement.ownerDocument;
- while (document.defaultView.frameElement)
- document = document.defaultView.frameElement.ownerDocument;
-
- let cwu = document.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
- let scrollX = {}, scrollY = {};
- cwu.getScrollXY(false, scrollX, scrollY);
-
- let r = aElement.getBoundingClientRect();
-
- // step out of iframes and frames, offsetting scroll values
- for (let frame = aElement.ownerDocument.defaultView; frame.frameElement && frame != content; frame = frame.parent) {
- // adjust client coordinates' origin to be top left of iframe viewport
- let rect = frame.frameElement.getBoundingClientRect();
- let left = frame.getComputedStyle(frame.frameElement, "").borderLeftWidth;
- let top = frame.getComputedStyle(frame.frameElement, "").borderTopWidth;
- scrollX.value += rect.left + parseInt(left);
- scrollY.value += rect.top + parseInt(top);
- }
-
- return {x: r.left + scrollX.value,
- y: r.top + scrollY.value,
- w: r.width,
- h: r.height };
- }
-};
deleted file mode 100644
--- a/dom/browser-element/BrowserElementPanningAPZDisabled.js
+++ /dev/null
@@ -1,685 +0,0 @@
-/* -*- tab-width: 2; indent-tabs-mode: nil; js-indent-level: 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("############################### browserElementPanningAPZDisabled.js loaded\n");
-
-var { 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;
-
-var ContentPanningAPZDisabled = {
- // 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 events = this._getEventsList();
- let els = Cc["@mozilla.org/eventlistenerservice;1"]
- .getService(Ci.nsIEventListenerService);
- events.forEach(type => {
- // Using the system group for mouse/touch events to avoid
- // missing events if .stopPropagation() has been called.
- els.addSystemEventListener(global, type, this, /* useCapture = */ false);
- });
- },
-
- destroy: function () {
- let events = this._getEventsList();
- let els = Cc["@mozilla.org/eventlistenerservice;1"]
- .getService(Ci.nsIEventListenerService);
- events.forEach(type => {
- els.removeSystemEventListener(global, type, this, /* useCapture = */ false);
- });
- },
-
- _getEventsList: function () {
- 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';
- }
-
- return events;
- },
-
- handleEvent: function cp_handleEvent(evt) {
- // Ignore events targeting an oop <iframe mozbrowser> since those will be
- // handle by the BrowserElementPanning.js instance in the child process.
- if (evt.target instanceof Ci.nsIMozBrowserFrame) {
- return;
- }
-
- // For in-process <iframe mozbrowser> the events are not targetting
- // directly the container iframe element, but some node of the document.
- // So, the BrowserElementPanning instance of the system app will receive
- // the sequence of touch events, as well as the BrowserElementPanning
- // instance in the targetted app.
- // As a result, multiple mozbrowser iframes will try to interpret the
- // sequence of touch events, which may results into multiple clicks.
- let targetWindow = evt.target.ownerDocument.defaultView;
- let frameElement = targetWindow.frameElement;
- while (frameElement) {
- targetWindow = frameElement.ownerDocument.defaultView;
- frameElement = targetWindow.frameElement;
- }
-
- if (content !== targetWindow) {
- return;
- }
-
- 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;
- }
-
- switch (evt.type) {
- case 'mousedown':
- case 'touchstart':
- this.onTouchStart(evt);
- break;
- case 'mousemove':
- case 'touchmove':
- this.onTouchMove(evt);
- break;
- case 'mouseup':
- case 'touchend':
- this.onTouchEnd(evt);
- break;
- case 'click':
- evt.stopPropagation();
- evt.preventDefault();
-
- let target = evt.target;
- let view = target.ownerDocument ? target.ownerDocument.defaultView
- : target;
- view.removeEventListener('click', this, true, true);
- break;
- }
- },
-
- position: new Point(0 , 0),
-
- findPrimaryPointer: function cp_findPrimaryPointer(touches) {
- if (!('primaryPointerId' in this))
- return null;
-
- for (let i = 0; i < touches.length; i++) {
- if (touches[i].identifier === this.primaryPointerId) {
- return touches[i];
- }
- }
- return null;
- },
-
- onTouchStart: function cp_onTouchStart(evt) {
- let screenX, screenY;
- if (this.watchedEventsType == 'touch') {
- if ('primaryPointerId' in this || evt.touches.length >= 2) {
- this._resetActive();
- return;
- }
-
- let firstTouch = evt.changedTouches[0];
- this.primaryPointerId = firstTouch.identifier;
- this.pointerDownTarget = firstTouch.target;
- screenX = firstTouch.screenX;
- screenY = firstTouch.screenY;
- } else {
- this.pointerDownTarget = evt.target;
- screenX = evt.screenX;
- screenY = evt.screenY;
- }
- this.dragging = true;
- this.panning = false;
-
- let oldTarget = this.target;
- [this.target, this.scrollCallback] = this.getPannable(this.pointerDownTarget);
-
- // If we have a pointer down target, we may need to fill in for EventStateManager
- // in setting the active state on the target element. Set a timer to
- // ensure the pointer-down target is active. (If it's already
- // active, the timer is a no-op.)
- if (this.pointerDownTarget !== null) {
- // If there's no possibility this is a drag/pan, activate now.
- // Otherwise wait a little bit to see if the gesture isn't a
- // tap.
- if (this.target === null) {
- this.notify(this._activationTimer);
- } else {
- this._activationTimer.initWithCallback(this,
- this._activationDelayMs,
- Ci.nsITimer.TYPE_ONE_SHOT);
- }
- }
-
- // If there is a pan animation running (from a previous pan gesture) and
- // the user touch back the screen, stop this animation immediatly and
- // prevent the possible click action if the touch happens on the same
- // target.
- this.preventNextClick = false;
- if (KineticPanning.active) {
- KineticPanning.stop();
-
- if (oldTarget && oldTarget == this.target)
- this.preventNextClick = true;
- }
-
- this.position.set(screenX, screenY);
- KineticPanning.reset();
- 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)) {
- evt.preventDefault();
- }
- },
-
- onTouchEnd: function cp_onTouchEnd(evt) {
- let touch = null;
- if (!this.dragging ||
- (this.watchedEventsType == 'touch' &&
- !(touch = this.findPrimaryPointer(evt.changedTouches)))) {
- return;
- }
-
- // !isPan() and evt.detail should always give the same answer here
- // since they use the same heuristics, but use the native gecko
- // computation when possible.
- //
- // NB: when we're using touch events, then !KineticPanning.isPan()
- // => this.panning, so we'll never attempt to block the click
- // event. That's OK however, because we won't fire a synthetic
- // click when we're using touch events and this touch series
- // wasn't a "tap" gesture.
- let click = (this.watchedEventsType == 'mouse') ?
- evt.detail : !KineticPanning.isPan();
- // Additionally, if we're seeing non-compliant hybrid events, a
- // "real" click will be generated if we started and ended on the
- // same element.
- if (this.hybridEvents) {
- let target =
- content.document.elementFromPoint(touch.clientX, touch.clientY);
- click |= (target === this.pointerDownTarget);
- }
-
- 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 {
- // 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._finishPanning();
-
- // Now that we're done, avoid entraining the thing we just panned.
- this.pointerDownTarget = null;
- },
-
- onTouchMove: function cp_onTouchMove(evt) {
- if (!this.dragging)
- return;
-
- let screenX, screenY;
- if (this.watchedEventsType == 'touch') {
- let primaryTouch = this.findPrimaryPointer(evt.changedTouches);
- if (evt.touches.length > 1 || !primaryTouch)
- return;
- screenX = primaryTouch.screenX;
- screenY = primaryTouch.screenY;
- } else {
- screenX = evt.screenX;
- screenY = evt.screenY;
- }
-
- let current = this.position;
- let delta = new Point(screenX - current.x, screenY - current.y);
- current.set(screenX, screenY);
-
- KineticPanning.record(delta, evt.timeStamp);
-
- let isPan = KineticPanning.isPan();
-
- // If we've detected a pan gesture, cancel the active state of the
- // current target.
- if (!this.panning && isPan) {
- this._resetActive();
- }
-
- // There's no possibility of us panning anything.
- if (!this.scrollCallback) {
- return;
- }
-
- // Scroll manually.
- this.scrollCallback(delta.scale(-1));
-
- if (!this.panning && isPan) {
- this.panning = true;
- this._activationTimer.cancel();
- }
-
- if (this.panning) {
- // Only do this when we're actually executing a pan gesture.
- // Otherwise synthetic mouse events will be canceled.
- evt.stopPropagation();
- evt.preventDefault();
- }
- },
-
- // nsITimerCallback
- notify: function cp_notify(timer) {
- this._setActive(this.pointerDownTarget);
- },
-
- onKineticBegin: function cp_onKineticBegin(evt) {
- },
-
- onKineticPan: function cp_onKineticPan(delta) {
- return !this.scrollCallback(delta);
- },
-
- onKineticEnd: function cp_onKineticEnd() {
- if (!this.dragging)
- this.scrollCallback = null;
- },
-
- getPannable: function cp_getPannable(node) {
- let pannableNode = this._findPannable(node);
- if (pannableNode) {
- return [pannableNode, this._generateCallback(pannableNode)];
- }
-
- return [null, null];
- },
-
- _findPannable: function cp_findPannable(node) {
- if (!(node instanceof Ci.nsIDOMHTMLElement) || node.tagName == 'HTML') {
- return null;
- }
-
- let nodeContent = node.ownerDocument.defaultView;
- while (!(node instanceof Ci.nsIDOMHTMLBodyElement)) {
- let style = nodeContent.getComputedStyle(node, null);
-
- let overflow = [style.getPropertyValue('overflow'),
- style.getPropertyValue('overflow-x'),
- style.getPropertyValue('overflow-y')];
-
- let rect = node.getBoundingClientRect();
- let isAuto = (overflow.indexOf('auto') != -1 &&
- (rect.height < node.scrollHeight ||
- rect.width < node.scrollWidth));
-
- let isScroll = (overflow.indexOf('scroll') != -1);
-
- let isScrollableTextarea = (node.tagName == 'TEXTAREA' &&
- (node.scrollHeight > node.clientHeight ||
- node.scrollWidth > node.clientWidth ||
- ('scrollLeftMin' in node && 'scrollLeftMax' in node &&
- node.scrollLeftMin != node.scrollLeftMax) ||
- ('scrollTopMin' in node && 'scrollTopMax' in node &&
- node.scrollTopMin != node.scrollTopMax)));
- if (isScroll || isAuto || isScrollableTextarea) {
- return node;
- }
-
- node = node.parentNode;
- }
-
- if (nodeContent.scrollMaxX != nodeContent.scrollMinX ||
- nodeContent.scrollMaxY != nodeContent.scrollMinY) {
- return nodeContent;
- }
-
- if (nodeContent.frameElement) {
- return this._findPannable(nodeContent.frameElement);
- }
-
- return null;
- },
-
- _generateCallback: function cp_generateCallback(root) {
- let firstScroll = true;
- let target;
- let current;
- let win, doc, htmlNode, bodyNode;
-
- function doScroll(node, delta) {
- if (node instanceof Ci.nsIDOMHTMLElement) {
- return node.scrollByNoFlush(delta.x, delta.y);
- } else if (node instanceof Ci.nsIDOMWindow) {
- win = node;
- doc = win.document;
-
- // "overflow:hidden" on either the <html> or the <body> node should
- // prevent the user from scrolling the root viewport.
- if (doc instanceof Ci.nsIDOMHTMLDocument) {
- htmlNode = doc.documentElement;
- bodyNode = doc.body;
- if (win.getComputedStyle(htmlNode, null).overflowX == "hidden" ||
- win.getComputedStyle(bodyNode, null).overflowX == "hidden") {
- delta.x = 0;
- }
- if (win.getComputedStyle(htmlNode, null).overflowY == "hidden" ||
- win.getComputedStyle(bodyNode, null).overflowY == "hidden") {
- delta.y = 0;
- }
- }
- let oldX = node.scrollX;
- let oldY = node.scrollY;
- node.scrollBy(delta.x, delta.y);
- return (node.scrollX != oldX || node.scrollY != oldY);
- }
- // If we get here, |node| isn't an HTML element and it's not a window,
- // but findPannable apparently thought it was scrollable... What is it?
- return false;
- }
-
- function targetParent(node) {
- return node.parentNode || node.frameElement || null;
- }
-
- function scroll(delta) {
- current = root;
- firstScroll = true;
- while (current) {
- if (doScroll(current, delta)) {
- firstScroll = false;
- return true;
- }
-
- // TODO The current code looks for possible scrolling regions only if
- // this is the first scroll action but this should be more dynamic.
- if (!firstScroll) {
- return false;
- }
-
- current = ContentPanningAPZDisabled._findPannable(targetParent(current));
- }
-
- // There is nothing scrollable here.
- return false;
- }
- return scroll;
- },
-
- get _activationTimer() {
- delete this._activationTimer;
- return this._activationTimer = Cc["@mozilla.org/timer;1"]
- .createInstance(Ci.nsITimer);
- },
-
- get _activationDelayMs() {
- let delay = Services.prefs.getIntPref('ui.touch_activation.delay_ms');
- delete this._activationDelayMs;
- return this._activationDelayMs = delay;
- },
-
- get _domUtils() {
- delete this._domUtils;
- return this._domUtils = Cc['@mozilla.org/inspector/dom-utils;1']
- .getService(Ci.inIDOMUtils);
- },
-
- _resetActive: function cp_resetActive() {
- let elt = this.pointerDownTarget || this.target;
- let root = elt.ownerDocument || elt.document;
- this._setActive(root.documentElement);
- },
-
- _setActive: function cp_setActive(elt) {
- const kStateActive = 0x00000001;
- this._domUtils.setContentState(elt, kStateActive);
- },
-
- _finishPanning: function() {
- this.dragging = false;
- delete this.primaryPointerId;
- this._activationTimer.cancel();
-
- // If there is a scroll action, let's do a manual kinetic panning action.
- if (this.panning) {
- KineticPanning.start(this);
- }
- },
-};
-
-// Min/max velocity of kinetic panning. This is in pixels/millisecond.
-var kMinVelocity = 0.2;
-var kMaxVelocity = 6;
-
-// Constants that affect the "friction" of the scroll pane.
-var kExponentialC = 1000;
-var kPolynomialC = 100 / 1000000;
-
-// How often do we change the position of the scroll pane?
-// Too often and panning may jerk near the end.
-// Too little and panning will be choppy. In milliseconds.
-var kUpdateInterval = 16;
-
-// The numbers of momentums to use for calculating the velocity of the pan.
-// Those are taken from the end of the action
-var kSamples = 5;
-
-var KineticPanning = {
- _position: new Point(0, 0),
- _velocity: new Point(0, 0),
- _acceleration: new Point(0, 0),
-
- get active() {
- return this.target !== null;
- },
-
- target: null,
- start: function kp_start(target) {
- this.target = target;
-
- // Calculate the initial velocity of the movement based on user input
- let momentums = this.momentums;
- let flick = momentums[momentums.length - 1].time - momentums[0].time < 300;
-
- let distance = new Point(0, 0);
- momentums.forEach(function(momentum) {
- distance.add(momentum.dx, momentum.dy);
- });
-
- function clampFromZero(x, min, max) {
- if (x >= 0)
- return Math.max(min, Math.min(max, x));
- return Math.min(-min, Math.max(-max, x));
- }
-
- let elapsed = momentums[momentums.length - 1].time - momentums[0].time;
- let velocityX = clampFromZero(distance.x / elapsed, 0, kMaxVelocity);
- let velocityY = clampFromZero(distance.y / elapsed, 0, kMaxVelocity);
-
- let velocity = this._velocity;
- if (flick) {
- // Very fast pan action that does not generate a click are very often pan
- // action. If this is a small gesture then it will not move the view a lot
- // and so it will be above the minimun threshold and not generate any
- // kinetic panning. This does not look on a device since this is often
- // a real gesture, so let's lower the velocity threshold for such moves.
- velocity.set(velocityX, velocityY);
- } else {
- velocity.set(Math.abs(velocityX) < kMinVelocity ? 0 : velocityX,
- Math.abs(velocityY) < kMinVelocity ? 0 : velocityY);
- }
- this.momentums = [];
-
- // Set acceleration vector to opposite signs of velocity
- function sign(x) {
- return x ? (x > 0 ? 1 : -1) : 0;
- }
-
- this._acceleration.set(velocity.clone().map(sign).scale(-kPolynomialC));
-
- // Reset the position
- this._position.set(0, 0);
-
- this._startAnimation();
-
- this.target.onKineticBegin();
- },
-
- stop: function kp_stop() {
- this.reset();
-
- if (!this.target)
- return;
-
- this.target.onKineticEnd();
- this.target = null;
- },
-
- reset: function kp_reset() {
- this.momentums = [];
- this.distance.set(0, 0);
- },
-
- momentums: [],
- record: function kp_record(delta, timestamp) {
- this.momentums.push({ 'time': this._getTime(timestamp),
- 'dx' : delta.x, 'dy' : delta.y });
-
- // We only need to keep kSamples in this.momentums.
- if (this.momentums.length > kSamples) {
- this.momentums.shift();
- }
-
- this.distance.add(delta.x, delta.y);
- },
-
- _getTime: function kp_getTime(time) {
- // Touch events generated by the platform or hand-made are defined in
- // microseconds instead of milliseconds. Bug 77992 will fix this at the
- // platform level.
- if (time > Date.now()) {
- return Math.floor(time / 1000);
- } else {
- return time;
- }
- },
-
- get threshold() {
- let dpi = content.QueryInterface(Ci.nsIInterfaceRequestor)
- .getInterface(Ci.nsIDOMWindowUtils)
- .displayDPI;
-
- let threshold = Services.prefs.getIntPref('ui.dragThresholdX') / 240 * dpi;
-
- delete this.threshold;
- return this.threshold = threshold;
- },
-
- distance: new Point(0, 0),
- isPan: function cp_isPan() {
- return (Math.abs(this.distance.x) > this.threshold ||
- Math.abs(this.distance.y) > this.threshold);
- },
-
- _startAnimation: function kp_startAnimation() {
- let c = kExponentialC;
- function getNextPosition(position, v, a, t) {
- // Important traits for this function:
- // p(t=0) is 0
- // p'(t=0) is v0
- //
- // We use exponential to get a smoother stop, but by itself exponential
- // is too smooth at the end. Adding a polynomial with the appropriate
- // weight helps to balance
- position.set(v.x * Math.exp(-t / c) * -c + a.x * t * t + v.x * c,
- v.y * Math.exp(-t / c) * -c + a.y * t * t + v.y * c);
- }
-
- let startTime = content.performance.now();
- let elapsedTime = 0, targetedTime = 0, averageTime = 0;
-
- let velocity = this._velocity;
- let acceleration = this._acceleration;
-
- let position = this._position;
- let nextPosition = new Point(0, 0);
- let delta = new Point(0, 0);
-
- let callback = (function(timestamp) {
- if (!this.target)
- return;
-
- // To make animation end fast enough but to keep smoothness, average the
- // ideal time frame (smooth animation) with the actual time lapse
- // (end fast enough).
- // Animation will never take longer than 2 times the ideal length of time.
- elapsedTime = timestamp - startTime;
- targetedTime += kUpdateInterval;
- averageTime = (targetedTime + elapsedTime) / 2;
-
- // Calculate new position.
- getNextPosition(nextPosition, velocity, acceleration, averageTime);
- delta.set(Math.round(nextPosition.x - position.x),
- Math.round(nextPosition.y - position.y));
-
- // Test to see if movement is finished for each component.
- if (delta.x * acceleration.x > 0)
- delta.x = position.x = velocity.x = acceleration.x = 0;
-
- if (delta.y * acceleration.y > 0)
- delta.y = position.y = velocity.y = acceleration.y = 0;
-
- if (velocity.equals(0, 0) || delta.equals(0, 0)) {
- this.stop();
- return;
- }
-
- position.add(delta);
- if (this.target.onKineticPan(delta.scale(-1))) {
- this.stop();
- return;
- }
-
- content.requestAnimationFrame(callback);
- }).bind(this);
-
- content.requestAnimationFrame(callback);
- }
-};
--- a/dom/ipc/jar.mn
+++ b/dom/ipc/jar.mn
@@ -3,13 +3,11 @@
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
toolkit.jar:
content/global/test-ipc.xul (test.xul)
content/global/remote-test-ipc.js (remote-test.js)
content/global/BrowserElementChild.js (../browser-element/BrowserElementChild.js)
content/global/BrowserElementChildPreload.js (../browser-element/BrowserElementChildPreload.js)
content/global/BrowserElementCopyPaste.js (../browser-element/BrowserElementCopyPaste.js)
- content/global/BrowserElementPanning.js (../browser-element/BrowserElementPanning.js)
-* content/global/BrowserElementPanningAPZDisabled.js (../browser-element/BrowserElementPanningAPZDisabled.js)
content/global/extensions.js (extensions.js)
content/global/manifestMessages.js (manifestMessages.js)
content/global/preload.js (preload.js)
--- a/dom/ipc/preload.js
+++ b/dom/ipc/preload.js
@@ -87,27 +87,16 @@ var DoPreloadPostfork = function(aCallba
try {
if (Services.prefs.getBoolPref("dom.mozInputMethod.enabled")) {
Services.scriptloader.loadSubScript("chrome://global/content/forms.js", global);
}
} catch (e) {
}
- if (Services.prefs.getIntPref("dom.w3c_touch_events.enabled") != 0) {
- try {
- if (Services.prefs.getBoolPref("layers.async-pan-zoom.enabled") === false) {
- Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanningAPZDisabled.js", global);
- }
- } catch (e) {
- }
-
- Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementPanning.js", global);
- }
-
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementCopyPaste.js", global);
Services.scriptloader.loadSubScript("chrome://global/content/BrowserElementChildPreload.js", global);
Services.io.getProtocolHandler("app");
Services.io.getProtocolHandler("default");
// Register an observer for topic "preload_postfork" after we fork a content
// process.