Skip to content

Commit

Permalink
Optional passive touch listeners for gestures
Browse files Browse the repository at this point in the history
Set Polymer.passiveTouchGestures to true to enable
  • Loading branch information
dfreedm committed Sep 7, 2017
1 parent e45e5bb commit 5f7597f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 6 deletions.
26 changes: 20 additions & 6 deletions lib/utils/gestures.html
Original file line number Diff line number Diff line change
Expand Up @@ -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)} */
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -450,15 +462,16 @@
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];
if (!gd) {
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;
Expand Down Expand Up @@ -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);
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions lib/utils/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -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;
})();
</script>

0 comments on commit 5f7597f

Please sign in to comment.