| <!doctype html> |
| <html> |
| <head> |
| <title>Pointer Events pointerdown tests</title> |
| <meta name="viewport" content="width=device-width"> |
| <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> |
| <link rel="help" href="https://w3c.github.io/pointerevents/#dom-pointerevent-pointerid"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/resources/testdriver.js"></script> |
| <script src="/resources/testdriver-actions.js"></script> |
| <script src="/resources/testdriver-vendor.js"></script> |
| <!-- Additional helper script for common checks across event types --> |
| <script type="text/javascript" src="pointerevent_support.js"></script> |
| <script> |
| "use strict" |
| |
| function loadFrame() { |
| return new Promise(resolve => { |
| const innerframe = document.getElementById("innerframe"); |
| innerframe.onload = resolve; |
| innerframe.src = |
| "resources/pointerevent_pointerId_scope-iframe.html"; |
| }); |
| } |
| |
| const eventList = [ |
| 'pointerenter', |
| 'pointerover', |
| 'pointermove', |
| 'pointerout', |
| 'pointerleave' |
| ]; |
| |
| function recordEvents(test) { |
| const target0 = document.getElementById("target0"); |
| const innerframe = document.getElementById("innerframe"); |
| let activePointerId = undefined; |
| let activePointerType = undefined; |
| const eventsReceived = { |
| 'inner': {}, |
| 'outer': {}, |
| }; |
| |
| // Records the last event of a given type in the case of multiple |
| // events. |
| const recordEvent = (event, context) => { |
| if (activePointerId === undefined) { |
| activePointerId = event.pointerId; |
| } |
| if (activePointerType == undefined) { |
| activePointerType= event.pointerType; |
| } |
| eventsReceived[context][event.type] = { |
| pointerId: event.pointerId, |
| pointerType: event.pointerType |
| }; |
| } |
| |
| const listener = (event) => { |
| recordEvent(event, 'outer'); |
| }; |
| eventList.forEach(eventType => { |
| target0.addEventListener(eventType, listener); |
| }); |
| |
| const messageListener = (event) => { |
| if (event.source != innerframe.contentWindow) { |
| return; |
| } |
| recordEvent(event.data, 'inner'); |
| }; |
| window.addEventListener('message', messageListener); |
| |
| test.add_cleanup(() => { |
| eventList.forEach(eventType => { |
| target0.removeEventListener(eventType, listener); |
| }); |
| window.removeEventListener('message', messageListener); |
| }); |
| |
| return new Promise(resolve => { |
| document.addEventListener('pointerup', () => { |
| // As pointer events for the inner frame are routed via a post |
| // message, the outer frame won't see the event until the following |
| // event processing loop. Allow 2 additional animation frames to |
| // ensure adequate time to receive the events. |
| waitForAnimationFrames(2).then(() => { |
| eventsReceived.activePointerId = activePointerId; |
| eventsReceived.activePointerType = activePointerType; |
| resolve(eventsReceived); |
| }); |
| }, { once: true }); |
| }); |
| |
| }; |
| |
| async function run() { |
| await loadFrame(); |
| |
| const target0 = document.getElementById("target0"); |
| const innerframe = document.getElementById("innerframe"); |
| const target1 = |
| innerframe.contentWindow.document.getElementsByTagName("div")[0]; |
| |
| promise_test(async t => { |
| const results = recordEvents(t); |
| // Move from the target in the outer-frame to a target in the inner- |
| // frame, click on second target, move back to the first and click. |
| // The inner target is not centered in the iframe, thus its position |
| // needs to be calculated. |
| const iframeRect = innerframe.getClientRects()[0]; |
| const rect = target1.getClientRects()[0]; |
| const center_x = |
| Math.round(iframeRect.left + (rect.left + rect.right) / 2); |
| const center_y = |
| Math.round(iframeRect.top + (rect.top + rect.bottom) / 2); |
| |
| await new test_driver.Actions() |
| .pointerMove(0, 0, { origin: target0 }) |
| .pointerMove(center_x, center_y) |
| .pointerDown() |
| .pointerUp() |
| .pointerMove(0, 0, { origin: target0 }) |
| .pointerDown() |
| .pointerUp() |
| .send(); |
| |
| const events = await results; |
| |
| assert_equals( |
| Object.keys(events.outer).length, eventList.length, |
| "Missing events for outer target"); |
| assert_equals( |
| Object.keys(events.inner).length, eventList.length, |
| "Missing events for inner target"); |
| |
| const activePointerId = events.activePointerId; |
| const activePointerType = events.activePointerType; |
| eventList.forEach(eventName => { |
| assert_equals( |
| events.inner[eventName].pointerId, activePointerId, |
| `PointerId of ${eventName} in the inner frame is not correct`); |
| assert_equals( |
| events.outer[eventName].pointerId, activePointerId, |
| `PointerId of ${eventName} in the outer frame is not correct`); |
| assert_equals( |
| events.inner[eventName].pointerType, activePointerType, |
| `PointerType of ${eventName} in the inner frame is not correct`); |
| assert_equals( |
| events.outer[eventName].pointerType, activePointerType, |
| `PointerType of ${eventName} in the outer frame is not correct`); |
| }); |
| }, 'pointerId of an active pointer is the same across same origin ' + |
| 'frames'); |
| } |
| </script> |
| </head> |
| <body onload="run()"> |
| <h1>Pointer Events pointer ID tests</h1> |
| <div id="target0" class="touchActionNone"></div> |
| <!-- Document onload does not guarantee that child iframes have loaded. |
| Force synchronization by deferring setting the iframe's source |
| until a promise is set up to capture its load event. The root |
| document will load first, then the iframe. This ordering ensures |
| deterministic behavior. |
| --> |
| <iframe id="innerframe"></iframe> |
| </body> |
| </html> |