diff --git a/src/dispatcher.js b/src/dispatcher.js index dd87275a..be9f8268 100644 --- a/src/dispatcher.js +++ b/src/dispatcher.js @@ -95,7 +95,8 @@ */ var dispatcher = { pointermap: new scope.PointerMap(), - eventMap: {}, + eventMap: Object.create(null), + captureInfo: Object.create(null), // Scope objects for native events. // This exists for ease of testing. eventSources: Object.create(null), @@ -227,7 +228,7 @@ */ makeEvent: function(inType, inEvent) { // relatedTarget must be null if pointer is captured - if (this.captureInfo) { + if (this.captureInfo[inEvent.pointerId]) { inEvent.relatedTarget = null; } var e = new PointerEvent(inType, inEvent); @@ -274,18 +275,13 @@ getTarget: function(inEvent) { // if pointer capture is set, route all events for the specified pointerId // to the capture target - if (this.captureInfo) { - if (this.captureInfo.id === inEvent.pointerId) { - return this.captureInfo.target; - } - } - return inEvent._target; + return this.captureInfo[inEvent.pointerId] || inEvent._target; }, setCapture: function(inPointerId, inTarget) { - if (this.captureInfo) { - this.releaseCapture(this.captureInfo.id); + if (this.captureInfo[inPointerId]) { + this.releaseCapture(inPointerId); } - this.captureInfo = {id: inPointerId, target: inTarget}; + this.captureInfo[inPointerId] = inTarget; var e = document.createEvent('Event'); e.initEvent('gotpointercapture', true, false); e.pointerId = inPointerId; @@ -296,12 +292,12 @@ this.asyncDispatchEvent(e); }, releaseCapture: function(inPointerId) { - if (this.captureInfo && this.captureInfo.id === inPointerId) { + var t = this.captureInfo[inPointerId]; + if (t) { var e = document.createEvent('Event'); e.initEvent('lostpointercapture', true, false); e.pointerId = inPointerId; - var t = this.captureInfo.target; - this.captureInfo = null; + this.captureInfo[inPointerId] = undefined; document.removeEventListener('pointerup', this.implicitRelease); document.removeEventListener('pointercancel', this.implicitRelease); e._target = t; diff --git a/src/touch.js b/src/touch.js index 912c982e..b8599bbf 100644 --- a/src/touch.js +++ b/src/touch.js @@ -6,6 +6,7 @@ (function(scope) { var dispatcher = scope.dispatcher; + var captureInfo = dispatcher.captureInfo; var findTarget = scope.findTarget; var allShadows = scope.targetFinding.allShadows.bind(scope.targetFinding); var pointermap = dispatcher.pointermap; @@ -149,10 +150,8 @@ // Spec specifies that pointerId 1 is reserved for Mouse. // Touch identifiers can start at 0. // Add 2 to the touch identifier for compatibility. - var pi = e.pointerId = inTouch.identifier + 2; - var ci = dispatcher.captureInfo; - var t = ci && ci.id === pi && ci.target; - e.target = t || findTarget(e); + var id = e.pointerId = inTouch.identifier + 2; + e.target = captureInfo[id] || findTarget(e); e.bubbles = true; e.cancelable = true; e.detail = this.clickCount; diff --git a/test/capture.js b/test/capture.js index 07247a35..09c34c44 100644 --- a/test/capture.js +++ b/test/capture.js @@ -5,11 +5,11 @@ */ suite('Pointer Capture', function() { - var set = function(el) { - el.setPointerCapture(1); + var set = function(el, id) { + el.setPointerCapture(id || 1); }; - var release = function(el) { - el.releasePointerCapture(1); + var release = function(el, id) { + el.releasePointerCapture(id || 1); }; test('Element has setPointerCapture and releasePointerCapture', function() { @@ -90,5 +90,26 @@ suite('Pointer Capture', function() { fire('up', host); } }); + + test('capture multiple pointers', function(done) { + var pm = PointerEventsPolyfill.dispatcher.pointermap; + var ids = 0; + function wait(e) { + ids += e.pointerId; + if (ids == 3) { + pm.clear(); + done(); + } + } + host.addEventListener('gotpointercapture', wait); + var e = new PointerEvent('pointerdown', {pointerId: 1}); + pm.set(1, e); + host.dispatchEvent(e); + set(host, 1); + e = new PointerEvent('pointerdown', {pointerId: 2}); + pm.set(2, e); + host.dispatchEvent(e); + set(host, 2); + }); }); });