diff --git a/lib/utils/gestures.html b/lib/utils/gestures.html
index 451433a639..ebe1eac8a3 100644
--- a/lib/utils/gestures.html
+++ b/lib/utils/gestures.html
@@ -40,22 +40,34 @@
}
})();
+ /**
+ * @param {string} name Possible mouse event name
+ * @return {boolean} true if mouse event, false if not
+ */
+ function isMouseEvent(name) {
+ return MOUSE_EVENTS.indexOf(name) > -1;
+ }
+
/* eslint no-empty: ["error", { "allowEmptyCatch": true }] */
// check for passive event listeners
let SUPPORTS_PASSIVE = false;
(function() {
try {
- let opts = Object.defineProperty({}, 'passive', {get: function() {SUPPORTS_PASSIVE = true;}});
+ let opts = Object.defineProperty({}, 'passive', {get() {SUPPORTS_PASSIVE = true;}});
window.addEventListener('test', null, opts);
window.removeEventListener('test', null, opts);
} catch(e) {}
})();
+ // decide whether to use {passive: true} for gestures listening for touch events
+ let PASSIVE_TOUCH = Boolean(HAS_NATIVE_TA && SUPPORTS_PASSIVE && Polymer.passiveTouchGestures);
+
// Check for touch-only devices
let IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/);
let GestureRecognizer = function(){}; // eslint-disable-line no-unused-vars
- GestureRecognizer.prototype.reset = function(){};
+ /** @type {function()} */
+ GestureRecognizer.prototype.reset;
/** @type {function(MouseEvent) | undefined} */
GestureRecognizer.prototype.mousedown;
/** @type {(function(MouseEvent) | undefined)} */
@@ -140,7 +152,7 @@
function hasLeftMouseButton(ev) {
let type = ev.type;
// exit early if the event is not a mouse event
- if (MOUSE_EVENTS.indexOf(type) === -1) {
+ if (!isMouseEvent(type)) {
return false;
}
// ev.button is not reliable for mousemove (0 is overloaded as both left button and no buttons)
@@ -450,7 +462,7 @@
for (let i = 0, dep, gd; i < deps.length; i++) {
dep = deps[i];
// don't add mouse handlers on iOS because they cause gray selection overlays
- if (IS_TOUCH_ONLY && MOUSE_EVENTS.indexOf(dep) > -1 && dep !== 'click') {
+ if (IS_TOUCH_ONLY && isMouseEvent(dep) && dep !== 'click') {
continue;
}
gd = gobj[dep];
@@ -458,7 +470,8 @@
gobj[dep] = gd = {_count: 0};
}
if (gd._count === 0) {
- node.addEventListener(dep, this._handleNative);
+ let options = !isMouseEvent(dep) && PASSIVE_TOUCH ? {passive: true} : undefined;
+ node.addEventListener(dep, this._handleNative, options);
}
gd[name] = (gd[name] || 0) + 1;
gd._count = (gd._count || 0) + 1;
@@ -491,7 +504,8 @@
gd[name] = (gd[name] || 1) - 1;
gd._count = (gd._count || 1) - 1;
if (gd._count === 0) {
- node.removeEventListener(dep, this._handleNative);
+ let options = !isMouseEvent(dep) && PASSIVE_TOUCH ? {passive: true} : undefined;
+ node.removeEventListener(dep, this._handleNative, options);
}
}
}
diff --git a/lib/utils/settings.html b/lib/utils/settings.html
index 4846ef5334..56e91f1945 100644
--- a/lib/utils/settings.html
+++ b/lib/utils/settings.html
@@ -93,5 +93,15 @@
Polymer.setSanitizeDOMValue = function(newSanitizeDOMValue) {
Polymer.sanitizeDOMValue = newSanitizeDOMValue;
};
+
+ /**
+ * Globally settable property to make Polymer Gestures use passive TouchEvent listeners when recognizing gestures.
+ * When set to `true`, gestures made from touch will not be able to prevent scrolling, allowing for smoother
+ * scrolling performance.
+ * Defaults to `false` for backwards compatibility.
+ *
+ * @memberof Polymer
+ */
+ Polymer.passiveTouchGestures = false;
})();