Skip to content

Commit

Permalink
Merge pull request #4829 from Polymer/optional-passive-gestures
Browse files Browse the repository at this point in the history
App-level support for passive gesture touch listeners
  • Loading branch information
Steve Orvell authored Sep 11, 2017
2 parents 5ab0a86 + 3547fd3 commit 4a2d427
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 6 deletions.
36 changes: 30 additions & 6 deletions lib/utils/gestures.html
Original file line number Diff line number Diff line change
Expand Up @@ -40,22 +40,44 @@
}
})();

/**
* @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) {}
})();

/**
* Generate settings for event listeners, dependant on `Polymer.passiveTouchGestures`
*
* @return {{passive: boolean} | undefined} Options to use for addEventListener and removeEventListener
*/
function PASSIVE_TOUCH() {
if (HAS_NATIVE_TA && SUPPORTS_PASSIVE && Polymer.passiveTouchGestures) {
return {passive: true};
} else {
return;
}
}

// 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 +162,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 +472,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();
node.addEventListener(dep, this._handleNative, options);
}
gd[name] = (gd[name] || 0) + 1;
gd._count = (gd._count || 0) + 1;
Expand Down Expand Up @@ -491,7 +514,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();
node.removeEventListener(dep, this._handleNative, options);
}
}
}
Expand Down
22 changes: 22 additions & 0 deletions lib/utils/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,5 +93,27 @@
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
*/
let passiveTouchGestures = false;

Polymer.passiveTouchGestures = passiveTouchGestures;

/**
* Sets `passiveTouchGestures` globally for all elements using Polymer Gestures.
*
* @memberof Polymer
* @param {boolean} usePassive enable or disable passive touch gestures globally
*/
Polymer.setPassiveTouchGestures = function(usePassive) {
Polymer.passiveTouchGestures = usePassive;
};
})();
</script>
53 changes: 53 additions & 0 deletions test/smoke/passive-gestures.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<!doctype html>
<!--
@license
Copyright (c) 2017 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
<head>
<script src="../../../webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="../../polymer.html">
<script>Polymer.setPassiveTouchGestures(true);</script>
<style>
html, body {
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<dom-module id="x-passive">
<template>
<style>
:host {
display: block;
height: 2000px;
background-color: -webkit-gradient(linear, left top, left bottom, from(blue), to(red));
background-image: -webkit-linear-gradient(top, blue, red);
background-image: -moz-linear-gradient(top, blue, red);
background-image: linear-gradient(to bottom, blue, red);
}
</style>
</template>
</dom-module>
<script>
Polymer({
is: 'x-passive',
listeners: {
'down': 'prevent',
'move': 'prevent'
},
prevent(e) {
e.preventDefault();
console.log('prevented!');
}
});
</script>
<x-passive></x-passive>
</body>
</html>

0 comments on commit 4a2d427

Please sign in to comment.