From 5f7597f7a4f3841e1ef763915c644e62d47e1112 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Wed, 6 Sep 2017 12:27:42 -0700 Subject: [PATCH 1/3] Optional passive touch listeners for gestures Set Polymer.passiveTouchGestures to true to enable --- lib/utils/gestures.html | 26 ++++++++++++++++++++------ lib/utils/settings.html | 10 ++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) 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; })(); From 6312da57006ec18b1dc18c6e119a63b61d9eb619 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Wed, 6 Sep 2017 12:40:12 -0700 Subject: [PATCH 2/3] Fix setting, add smoke test --- lib/utils/settings.html | 2 +- test/smoke/passive-gestures.html | 53 ++++++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) create mode 100644 test/smoke/passive-gestures.html diff --git a/lib/utils/settings.html b/lib/utils/settings.html index 56e91f1945..0548ad3c2c 100644 --- a/lib/utils/settings.html +++ b/lib/utils/settings.html @@ -102,6 +102,6 @@ * * @memberof Polymer */ - Polymer.passiveTouchGestures = false; + Polymer.passiveTouchGestures = Polymer.passiveTouchGestures || false; })(); diff --git a/test/smoke/passive-gestures.html b/test/smoke/passive-gestures.html new file mode 100644 index 0000000000..300496065d --- /dev/null +++ b/test/smoke/passive-gestures.html @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file From 3547fd37852555e957707d3d07818e96872c82e2 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Mon, 11 Sep 2017 11:31:23 -0700 Subject: [PATCH 3/3] Provide a `Polymer.setPassiveTouchGestures()` function Clean up event listener options inside gestures that use passive touch --- lib/utils/gestures.html | 18 ++++++++++++++---- lib/utils/settings.html | 14 +++++++++++++- test/smoke/passive-gestures.html | 2 +- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/lib/utils/gestures.html b/lib/utils/gestures.html index ebe1eac8a3..ea2e29c4be 100644 --- a/lib/utils/gestures.html +++ b/lib/utils/gestures.html @@ -59,8 +59,18 @@ } 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); + /** + * 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/); @@ -470,7 +480,7 @@ gobj[dep] = gd = {_count: 0}; } if (gd._count === 0) { - let options = !isMouseEvent(dep) && PASSIVE_TOUCH ? {passive: true} : undefined; + let options = !isMouseEvent(dep) && PASSIVE_TOUCH(); node.addEventListener(dep, this._handleNative, options); } gd[name] = (gd[name] || 0) + 1; @@ -504,7 +514,7 @@ gd[name] = (gd[name] || 1) - 1; gd._count = (gd._count || 1) - 1; if (gd._count === 0) { - let options = !isMouseEvent(dep) && PASSIVE_TOUCH ? {passive: true} : undefined; + let options = !isMouseEvent(dep) && PASSIVE_TOUCH(); node.removeEventListener(dep, this._handleNative, options); } } diff --git a/lib/utils/settings.html b/lib/utils/settings.html index 0548ad3c2c..7d5163e848 100644 --- a/lib/utils/settings.html +++ b/lib/utils/settings.html @@ -102,6 +102,18 @@ * * @memberof Polymer */ - Polymer.passiveTouchGestures = Polymer.passiveTouchGestures || false; + 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; + }; })(); diff --git a/test/smoke/passive-gestures.html b/test/smoke/passive-gestures.html index 300496065d..90e7a9363c 100644 --- a/test/smoke/passive-gestures.html +++ b/test/smoke/passive-gestures.html @@ -11,8 +11,8 @@ - +