From 947172f85e3490323b61e9cf016146a3e1f8941c Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 3 Nov 2016 17:25:10 -0700 Subject: [PATCH 1/4] Use document-wide passive touch listener to update ghostclick blocker target Fixes #4128 --- src/standard/gestures.html | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/src/standard/gestures.html b/src/standard/gestures.html index f5e13ad4ae..5681e907b0 100644 --- a/src/standard/gestures.html +++ b/src/standard/gestures.html @@ -38,6 +38,17 @@ } })(); + // check for passive event listeners + var SUPPORTS_PASSIVE = (function() { + var sp = false; + try { + var opts = Object.defineProperty({}, 'passive', {get: function() {sp = true;}}) + window.addEventListener('test', null, opts); + window.removeEventListener('test', null, opts); + return sp; + } catch(e) {} + })(); + // Check for touch-only devices var IS_TOUCH_ONLY = navigator.userAgent.match(/iP(?:[oa]d|hone)|Android/); @@ -82,7 +93,7 @@ } } - function ignoreMouse() { + function ignoreMouse(ev) { if (!POINTERSTATE.mouse.mouseIgnoreJob) { setupTeardownMouseCanceller(true); } @@ -91,6 +102,7 @@ POINTERSTATE.mouse.target = null; POINTERSTATE.mouse.mouseIgnoreJob = null; }; + POINTERSTATE.mouse.target = Polymer.dom(ev).rootTarget; POINTERSTATE.mouse.mouseIgnoreJob = Polymer.Debounce(POINTERSTATE.mouse.mouseIgnoreJob, unset, MOUSE_TIMEOUT); } @@ -178,6 +190,10 @@ stateObj.upfn = null; } + if (HAS_NATIVE_TA) { + document.addEventListener('touchend', ignoreMouse, SUPPORTS_PASSIVE ? {passive: true} : false); + } + var Gestures = { gestures: {}, recognizers: [], @@ -234,14 +250,11 @@ if (!HAS_NATIVE_TA) { if (type === 'touchstart' || type === 'touchmove') { Gestures.handleTouchAction(ev); + } else if (type === 'touchend') { + // ignore syntethic mouse events after a touch + ignoreMouse(ev); } } - // disable synth mouse events, unless this event is itself simulated - if (type === 'touchend') { - POINTERSTATE.mouse.target = Polymer.dom(ev).rootTarget; - // ignore syntethic mouse events after a touch - ignoreMouse(); - } } } handled = ev[HANDLED_OBJ]; From 9c8eaa9d4b767f9c3a25f5310857585934e2ace2 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Thu, 3 Nov 2016 17:48:58 -0700 Subject: [PATCH 2/4] fix lint error --- src/standard/gestures.html | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/standard/gestures.html b/src/standard/gestures.html index 5681e907b0..2e41c258f0 100644 --- a/src/standard/gestures.html +++ b/src/standard/gestures.html @@ -38,14 +38,14 @@ } })(); + /* eslint no-empty: ["error", { "allowEmptyCatch": true }] */ // check for passive event listeners - var SUPPORTS_PASSIVE = (function() { - var sp = false; + var SUPPORTS_PASSIVE = false; + (function() { try { - var opts = Object.defineProperty({}, 'passive', {get: function() {sp = true;}}) + var opts = Object.defineProperty({}, 'passive', {get: function() {SUPPORTS_PASSIVE = true;}}) window.addEventListener('test', null, opts); window.removeEventListener('test', null, opts); - return sp; } catch(e) {} })(); From 4be7e9f62158f58ba2aa14b764580d13d558f99d Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Fri, 4 Nov 2016 10:28:02 -0700 Subject: [PATCH 3/4] Add tests for no-gesture interop --- test/unit/gestures-elements.html | 14 ++++++++++++ test/unit/gestures.html | 37 ++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/test/unit/gestures-elements.html b/test/unit/gestures-elements.html index 93dff59533..1bb4a62fd6 100644 --- a/test/unit/gestures-elements.html +++ b/test/unit/gestures-elements.html @@ -205,3 +205,17 @@ }); + + + + + \ No newline at end of file diff --git a/test/unit/gestures.html b/test/unit/gestures.html index 52f343f1da..5840ded1c5 100644 --- a/test/unit/gestures.html +++ b/test/unit/gestures.html @@ -489,6 +489,43 @@ assert.isNull(r.info.upfn, r.name + ' upfn'); }); }); + + suite('Interop', function() { + teardown(function() { + Polymer.Gestures.resetMouseCanceller(); + }); + function tap(target) { + var options = {bubbles: true, cancelable: true}; + ['touchstart', 'touchmove', 'touchend'].forEach(function(n) { + var ev = new CustomEvent(n, options); + ev.touches = ev.changedTouches = [ + { + clientX: 0, + clientY: 0, + identifier: 1, + target: target + } + ]; + ev.clientX = 0; + ev.clientY = 0; + target.dispatchEvent(ev); + }); + ['mousedown', 'mousemove', 'mouseup', 'click'].forEach(function(n) { + var ev = new CustomEvent(n, options); + ev.button = 0; + ev.buttons = 1; + target.dispatchEvent(ev); + }); + } + test('elements without gestures click reliably', function() { + var el = document.createElement('x-no-gesture'); + document.body.appendChild(el); + CustomElements.takeRecords(); + tap(el.$.one); + tap(el.$.two); + assert.equal(el.stream.length, 2); + }); + }); }); From 5ddcb8d14b90b57c201804f877e95cde91c4e322 Mon Sep 17 00:00:00 2001 From: Daniel Freedman Date: Fri, 4 Nov 2016 10:46:47 -0700 Subject: [PATCH 4/4] always use the document listener --- src/standard/gestures.html | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/standard/gestures.html b/src/standard/gestures.html index 2e41c258f0..63c9a9cdbb 100644 --- a/src/standard/gestures.html +++ b/src/standard/gestures.html @@ -190,9 +190,9 @@ stateObj.upfn = null; } - if (HAS_NATIVE_TA) { - document.addEventListener('touchend', ignoreMouse, SUPPORTS_PASSIVE ? {passive: true} : false); - } + // use a document-wide touchend listener to start the ghost-click prevention mechanism + // Use passive event listeners, if supported, to not affect scrolling performance + document.addEventListener('touchend', ignoreMouse, SUPPORTS_PASSIVE ? {passive: true} : false); var Gestures = { gestures: {}, @@ -250,9 +250,6 @@ if (!HAS_NATIVE_TA) { if (type === 'touchstart' || type === 'touchmove') { Gestures.handleTouchAction(ev); - } else if (type === 'touchend') { - // ignore syntethic mouse events after a touch - ignoreMouse(ev); } } }