pointerevent_capture_suppressing_mouse.html (9879B)
1 <!doctype html> 2 <html> 3 <head> 4 <title>Set/Release capture</title> 5 <meta name="viewport" content="width=device-width"> 6 <link rel="stylesheet" type="text/css" href="pointerevent_styles.css"> 7 <script src="/resources/testharness.js"></script> 8 <script src="/resources/testharnessreport.js"></script> 9 <script src="/resources/testdriver.js"></script> 10 <script src="/resources/testdriver-actions.js"></script> 11 <script src="/resources/testdriver-vendor.js"></script> 12 <!-- Additional helper script for common checks across event types --> 13 <script type="text/javascript" src="pointerevent_support.js"></script> 14 </head> 15 <body> 16 <div class="spacer"></div> 17 <div id="target0"></div> 18 <div class="spacer"></div> 19 <div id="target1"></div> 20 <div class="spacer"></div> 21 <input type="button" id="captureButton" value="Set Capture"> 22 </body> 23 <script type='text/javascript'> 24 window.onload = () => { 25 let eventLog = []; 26 let nextUncheckedEventIndex = 0; 27 const target0 = document.getElementById('target0'); 28 const target1 = document.getElementById('target1'); 29 const captureButton = document.getElementById('captureButton'); 30 31 function eventLabel(target, eventName) { 32 return `${eventName}@${target.id}`; 33 } 34 35 function recordEvent(target, eventName) { 36 eventLog.push(eventLabel(target, eventName)); 37 } 38 39 // Ensure match to the next sequence of events in the event log. 40 function assert_next_events(target, expectedEventNames, message) { 41 for (let i = 0; i < expectedEventNames.length; i++) { 42 assert_true(nextUncheckedEventIndex < eventLog.length, 43 `${message}: empty event queue`); 44 const observed = eventLog[nextUncheckedEventIndex++]; 45 const expected = eventLabel(target, expectedEventNames[i]); 46 assert_equals(observed, expected,`${message}: Event mismatch`); 47 } 48 } 49 50 // After validating the expected events, all entries in the event map 51 // must be false or we have recorded an unexpected event. 52 function assert_empty_event_queue(message) { 53 const uncheckedEvents = eventLog.length - nextUncheckedEventIndex; 54 assert_equals(uncheckedEvents, 0, 55 `${message}: Unexpected events ` + 56 `${eventLog.slice(-uncheckedEvents).join(", ")}`); 57 } 58 59 // Adds listeners for all element-pointerevent combinations. Each listener 60 // records the event for validation. the pointerdown event on the button 61 // triggers an extra step of triggering pointer capture. 62 function addEventListeners(t) { 63 // Adds a single event that is removed at the conclusion of the test. 64 const addListener = (target, eventName, fn) => { 65 const callback = (e) => { 66 recordEvent(target, eventName); 67 // Additional event handling is optional. 68 if (fn) 69 fn(e); 70 }; 71 target.addEventListener(eventName, callback); 72 t.add_cleanup(() => { 73 target.removeEventListener(eventName, callback); 74 }); 75 }; 76 [target0, target1, captureButton].forEach(el => { 77 ['gotpointercapture', 'lostpointercapture', 'pointerenter', 78 'pointerleave', 'pointermove', 'pointerout', 79 'pointerover'].forEach(eventName => { 80 addListener(el, eventName); 81 }); 82 }); 83 addListener(captureButton, 'pointerdown', (e) => { 84 target0.setPointerCapture(e.pointerId); 85 }); 86 t.add_cleanup(() => { 87 eventLog = []; 88 nextUncheckedEventIndex = 0; 89 }); 90 } 91 92 // Trigger and wait for a pointer move. The wait is to ensure there is 93 // no coalescence of pointer move events. 94 async function moveTo(x, y, target) { 95 const movePromise = getEvent('pointermove', target); 96 let actions = new test_driver.Actions() 97 .pointerMove(x, y, { origin: target }) 98 .send(); 99 await actions; 100 await movePromise; 101 } 102 103 promise_test(async t => { 104 // Reset pointer position. 105 await moveTo(0, 0, document.body); 106 addEventListeners(t); 107 // Move to the first target. 108 await moveTo(0, 0, target0); 109 assert_next_events(target0,["pointerover", "pointerenter", "pointermove"], 110 'Move to first target'); 111 assert_empty_event_queue('Check after first move'); 112 113 // Move to the second taret. 114 await moveTo(0, 0, target1); 115 assert_next_events(target0, ['pointerout', 'pointerleave'], 116 'Exit first target'); 117 assert_next_events(target1, 118 ["pointerover", "pointerenter", "pointermove"], 119 'Move to second target'); 120 assert_empty_event_queue('Check after second move'); 121 122 // Move to the capture button. 123 await moveTo(0, 0, captureButton); 124 assert_next_events(target1, ['pointerout', 'pointerleave'], 125 'Exit second target'); 126 assert_next_events( 127 captureButton, ["pointerover", "pointerenter", "pointermove"], 128 'Move to button'); 129 assert_empty_event_queue('Check after third move'); 130 }, 'Validate pointer events track pointer movement without pointer ' 131 + 'capture.'); 132 133 async function runCaptureAndHoverTargetActionSequence(t, hoverTarget) { 134 const pointerUpPromise = getEvent('pointerup', document); 135 const actionsPromise = 136 new test_driver.Actions() 137 // Start outside capture button. 138 .pointerMove(0, 0) 139 .pointerDown() 140 .pointerUp() 141 // Move to the capture button 142 .pointerMove(0, 0, {origin: captureButton}) 143 // Trigger pointer capture 144 .pointerDown() 145 // Hover over the target element 146 .pointerMove(10, 0, {origin: hoverTarget}) 147 // Release capture 148 .pointerUp() 149 .send(); 150 await actionsPromise; 151 await pointerUpPromise; 152 } 153 154 promise_test(async t => { 155 // Reset pointer position. 156 await moveTo(0, 0, document.body); 157 addEventListeners(t); 158 159 // On entry for this sub-test, the pointer is at the document origin. 160 await runCaptureAndHoverTargetActionSequence(t, captureButton); 161 assert_next_events( 162 captureButton, 163 ['pointerover', 'pointerenter', 'pointermove'], 164 'Move to button from origin'); 165 assert_next_events( 166 captureButton, 167 ['pointerdown', 'pointerout', 'pointerleave'], 168 'Pointer down on button to trigger capture'); 169 assert_next_events( 170 target0, 171 ['pointerover', 'pointerenter', 'gotpointercapture', 'pointermove'], 172 'Capture triggered while hovering over button'); 173 assert_next_events( 174 target0, 175 ['lostpointercapture', 'pointerout', 'pointerleave'], 176 'Lose pointer capture while hovering over button'); 177 // Post pointer capture. 178 assert_next_events( 179 captureButton, 180 ['pointerover', 'pointerenter'], 181 'Post capture while hovering over button'); 182 assert_empty_event_queue('Check after button hover'); 183 184 // On entry for this sub-test, the pointer is over the button. 185 await runCaptureAndHoverTargetActionSequence(t, target0); 186 assert_next_events( 187 captureButton, 188 ['pointerout', 'pointerleave'], 189 'Move from button to document origin'); 190 assert_next_events( 191 captureButton, 192 ['pointerover', 'pointerenter', 'pointermove'], 193 'Move from document origin to button'); 194 assert_next_events( 195 captureButton, 196 [ 'pointerdown', 'pointerout', 'pointerleave'], 197 'Pointer down on button to trigger capture'); 198 assert_next_events( 199 target0, 200 ['pointerover', 'pointerenter', 'gotpointercapture', 'pointermove'], 201 'Capture triggered while hovering over capture target'); 202 assert_next_events( 203 target0, 204 ['lostpointercapture'], 205 'Lose pointer capture while hovering over capture target'); 206 assert_empty_event_queue('Check after hover on capture target'); 207 208 209 // On entry for this sub-test, the pointer is over the capture target. 210 await runCaptureAndHoverTargetActionSequence(t, target1); 211 assert_next_events( 212 target0, 213 ['pointerout', 'pointerleave'], 214 'Move from capture target to button'); 215 assert_next_events( 216 captureButton, 217 ['pointerover', 'pointerenter', 'pointermove'], 218 'Move from capture target to button'); 219 assert_next_events( 220 captureButton, 221 [ 'pointerdown', 'pointerout', 'pointerleave'], 222 'Pointer down on button to trigger capture'); 223 assert_next_events( 224 target0, 225 ['pointerover', 'pointerenter', 'gotpointercapture', 'pointermove'], 226 'Capture triggered while hovering over non-capture target'); 227 assert_next_events( 228 target0, 229 ['lostpointercapture', 'pointerout', 'pointerleave'], 230 'Lose pointer capture while hovering over non-capture target'); 231 assert_next_events( 232 target1, 233 ["pointerover", "pointerenter"], 234 'Post capture while hovering over non-capture target'); 235 assert_empty_event_queue('Check after hover on non-capture target '); 236 }, 'Test pointer capture.'); 237 }; 238 </script> 239 </html>