| <meta name="variant" content="?mouse"> |
| <meta name="variant" content="?touch"> |
| <meta name="variant" content="?pen"> |
| <script src="/resources/testharness.js"></script> |
| <script src="/resources/testharnessreport.js"></script> |
| <script src="/resources/testdriver.js"></script> |
| <script src="/resources/testdriver-vendor.js"></script> |
| <script src="/resources/testdriver-actions.js"></script> |
| <script type="text/javascript" src="pointerevent_support.js"></script> |
| <style> |
| iframe { |
| width: 300px; |
| height: 300px; |
| top: 100px; |
| left: 100px; |
| border: 0; |
| position: absolute; |
| background: green; |
| } |
| #outerFrame { |
| width: 500px; |
| height: 500px; |
| background: blue; |
| } |
| body { |
| touch-action:none; |
| } |
| </style> |
| <body id="outerFrame body" onload="run()"> |
| <div id='outerFrame'> |
| <iframe id='innerFrameElement' src="resources/pointerevent_pointercapture-iframe.html"></iframe> |
| </div> |
| </body> |
| <script> |
| var receivedEventList = []; |
| // |start_logging| is set to true in the pointerdown event handler, and as such |
| // also tracks if pointerdown happened already in the test. |
| var start_logging = false; |
| var first_pointermove_happened = false; |
| |
| // Add a timeout promise when waiting for lostpointercapture and pointerup. |
| // We add this to make it easy to know which event wasn't fired on the right |
| // element. |
| var eventTimeout = ()=>(()=>new Promise((resolve, reject)=>{ |
| const msToWait = 4000; |
| let start; |
| function wait(timestamp){ |
| if(start === undefined) |
| start = timestamp; |
| if(timestamp - start < msToWait) |
| requestAnimationFrame(wait); |
| else |
| resolve(); |
| } |
| requestAnimationFrame(wait); |
| })); |
| |
| |
| function handleEvent(event) { |
| if (event.type == 'pointerdown') { |
| start_logging = true; |
| if (document.setPointerCaptureOnPointerDown) { |
| event.target.setPointerCapture(event.pointerId); |
| } |
| } |
| |
| // Only log the first pointermove event after pointerdown. We need to account |
| // for coalesced pointermove events and for the pointermove events that |
| // happen after lostpointercapture. |
| if (start_logging && (event.type !== "pointermove" || !first_pointermove_happened)) |
| receivedEventList.push(event.target.id + ' received ' + event.type); |
| |
| if (event.type == "pointermove"){ |
| if (document.releasePointerCaptureOnFirstMove && event.target.hasPointerCapture(event.pointerId)) |
| event.target.releasePointerCapture(event.pointerId); |
| if(start_logging) |
| first_pointermove_happened = true; |
| } |
| }; |
| |
| document.testEventList = ['pointerup', 'pointerdown', 'pointermove', 'gotpointercapture', 'lostpointercapture']; |
| document.testEventList.forEach(function(eventName) { |
| document.getElementById('outerFrame').addEventListener(eventName, handleEvent); |
| }); |
| |
| function Reset() { |
| document.setPointerCaptureOnPointerDown = false; |
| document.releasePointerCaptureOnFirstMove = false; |
| receivedEventList = []; |
| start_logging = false; |
| first_pointermove_happened = false; |
| } |
| |
| function run() { |
| var pointerType = location.search.substring(1); |
| promise_test (async(t) => { |
| Reset(); |
| document.setPointerCaptureOnPointerDown = true; |
| expectedEventList = ["innerFrame received pointerdown", |
| "innerFrame received gotpointercapture", |
| "innerFrame received pointermove", |
| "innerFrame received pointerup", |
| "innerFrame received lostpointercapture"]; |
| var pointerId = pointerType + "Pointer1"; |
| |
| var innerFrame = document.getElementById('innerFrameElement'); |
| var innerFrameDocument = innerFrame.contentDocument; |
| // We are interested in tracking events only after pointerdown |
| var pointerdown_happened = new Promise((resolve, reject)=>{innerFrameDocument.addEventListener("pointerdown",resolve);}); |
| var watcher_promise = pointerdown_happened.then(()=>{ |
| var watch_inner_frame = new EventWatcher(t, innerFrameDocument, ["lostpointercapture"], eventTimeout()); |
| return watch_inner_frame.wait_for(["lostpointercapture"]); |
| }); |
| |
| await new test_driver.Actions() |
| .addPointer(pointerId, pointerType) |
| .pointerMove(200, 200) |
| .pointerDown() |
| .pointerMove(150, 150) |
| .pointerMove(50, 50) |
| .pointerUp() |
| .pointerMove(75, 75) |
| .send(); |
| // Wait for lostpointercapture to fire. |
| await watcher_promise; |
| assert_array_equals(receivedEventList, expectedEventList, "Received events: " + receivedEventList); |
| document.setPointerCaptureOnPointerDown = false; |
| }, "Test " + pointerType + "pointer capture in same-origin frame: Pointer down at inner frame and set pointer capture."); |
| |
| promise_test (async(t) => { |
| Reset(); |
| document.setPointerCaptureOnPointerDown = true; |
| expectedEventList = ["outerFrame received pointerdown", |
| "outerFrame received gotpointercapture", |
| "outerFrame received pointermove", |
| "outerFrame received pointerup", |
| "outerFrame received lostpointercapture"]; |
| var pointerId = pointerType + "Pointer1"; |
| |
| // We are interested in tracking events only after pointerdown |
| var pointerdown_happened = new Promise((resolve, reject)=>{document.getElementById('outerFrame').addEventListener("pointerdown",resolve);}); |
| var watcher_promise = pointerdown_happened.then(()=>{ |
| // For this test we're going to wait for both pointerup and lostpointercapture, |
| // as pointerup fires on innerFrame on Windows (see crbug.com/1186788) |
| var watch_outer_frame_for_pointerup = new EventWatcher(t, document.getElementById('outerFrame'), ["pointerup"], eventTimeout()); |
| return watch_outer_frame_for_pointerup.wait_for(["pointerup"]).then(()=>{ |
| var watch_outer_frame_for_lostpointercapture = new EventWatcher(t, document.getElementById('outerFrame'), ["lostpointercapture"], eventTimeout()); |
| return watch_outer_frame_for_lostpointercapture.wait_for(["lostpointercapture"]); |
| }); |
| }); |
| |
| await new test_driver.Actions() |
| .addPointer(pointerId, pointerType) |
| .pointerMove(25, 25) |
| .pointerDown() |
| .pointerMove(200, 200) |
| .pointerUp() |
| .pointerMove(25, 25) |
| .send(); |
| // Wait for lostpointercapture to fire. |
| await watcher_promise; |
| assert_array_equals(receivedEventList, expectedEventList, "Received events: " + receivedEventList); |
| document.setPointerCaptureOnPointerDown = false; |
| }, "Test " + pointerType + "pointer capture in same-origin frame: Pointer down at outer frame body and set pointer capture."); |
| |
| |
| promise_test (async(t) => { |
| Reset(); |
| document.setPointerCaptureOnPointerDown = true; |
| document.releasePointerCaptureOnFirstMove = true; |
| // Mouse event has the frame capture, so after pointer capture released, events are |
| // dispatched to innerFrameDocument. |
| expectedEventList = ["innerFrame received pointerdown", |
| "innerFrame received gotpointercapture", |
| "innerFrame received pointermove", |
| "innerFrame received lostpointercapture", |
| (pointerType == "touch" ? "outerFrame": "innerFrameDocument") + " received pointerup",]; |
| var pointerId = pointerType + "Pointer1"; |
| |
| var innerFrame = document.getElementById('innerFrameElement'); |
| var innerFrameDocument = innerFrame.contentDocument; |
| // We are interested in tracking events only after pointerdown |
| var pointerdown_happened = new Promise((resolve, reject)=>{innerFrameDocument.addEventListener("pointerdown",resolve);}); |
| var watcher_promise = pointerdown_happened.then(()=>{ |
| if(pointerType === "touch"){ |
| var watch_outer_frame = new EventWatcher(t, document.getElementById('outerFrame'), ["pointerup"], eventTimeout()); |
| return watch_outer_frame.wait_for("pointerup"); |
| }else{ |
| var watch_inner_frame = new EventWatcher(t, innerFrameDocument, ["pointerup"], eventTimeout()); |
| return watch_inner_frame.wait_for("pointerup"); |
| } |
| }); |
| |
| await new test_driver.Actions() |
| .addPointer(pointerId, pointerType) |
| .pointerMove(200, 200) |
| .pointerDown() |
| .pointerMove(150, 150) |
| .pointerMove(50, 50) |
| .pointerUp() |
| .pointerMove(150, 150) |
| .send(); |
| // Wait for pointerup to fire. |
| await watcher_promise; |
| assert_array_equals(receivedEventList, expectedEventList, "Received events: " + receivedEventList); |
| document.releasePointerCaptureOnFirstMove = false; |
| document.setPointerCaptureOnPointerDown = false; |
| }, "Test " + pointerType + "pointer capture in same-origin frame: Pointerdown with set capture at inner frame, then release on next pointermove."); |
| |
| |
| promise_test (async(t) => { |
| Reset(); |
| document.setPointerCaptureOnPointerDown = true; |
| document.releasePointerCaptureOnFirstMove = true; |
| expectedEventList = ["outerFrame received pointerdown", |
| "outerFrame received gotpointercapture", |
| "outerFrame received pointermove", |
| "outerFrame received lostpointercapture", |
| "innerFrame received pointerup"]; |
| var pointerId = pointerType + "Pointer1"; |
| |
| var innerFrame = document.getElementById('innerFrameElement'); |
| var innerFrameDocument = innerFrame.contentDocument; |
| // We are interested in tracking events only after pointerdown |
| var pointerdown_happened = new Promise((resolve, reject)=>{document.getElementById('outerFrame').addEventListener("pointerdown",resolve);}); |
| var watcher_promise = pointerdown_happened.then(()=>{ |
| var watch_inner_frame = new EventWatcher(t, innerFrameDocument, ["pointerup"], eventTimeout()); |
| return watch_inner_frame.wait_for(["pointerup"]); |
| }); |
| |
| await new test_driver.Actions() |
| .addPointer(pointerId, pointerType) |
| .pointerMove(50, 50) |
| .pointerDown() |
| .pointerMove(200, 200) |
| // Pause here to make sure that the previous and following pointer moves |
| // are not coalesced. If they are coalesced, we will not see the second |
| // move event which is when the pending lostpointercapture should be fired |
| // (Since the pointerup event is targeted at a different frame, it won't dispatch |
| // the pending lostpointercapture event). |
| .pause(300) |
| .pointerMove(250, 250) |
| .pointerUp() |
| .send(); |
| // Wait for pointerup to fire. |
| await watcher_promise; |
| assert_array_equals(receivedEventList, expectedEventList, "Received events: " + receivedEventList); |
| document.releasePointerCaptureOnFirstMove = false; |
| document.setPointerCaptureOnPointerDown = false; |
| }, "Test " + pointerType + "pointer capture in same-origin frame: Pointerdown with set capture at outer frame, then release on next pointermove."); |
| } |
| </script> |
| |
| </body> |