helper_doubletap_zoom_smooth.html (5658B)
1 <!DOCTYPE HTML> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <meta name="viewport" content="width=2100"/> 6 <title>Check that double tapping zoom out animation is smooth</title> 7 <script type="application/javascript" src="apz_test_native_event_utils.js"></script> 8 <script type="application/javascript" src="apz_test_utils.js"></script> 9 <script src="/tests/SimpleTest/paint_listener.js"></script> 10 <script type="application/javascript"> 11 12 let hasPrev = false; 13 let zoomingIn = true; 14 let lastVVLeft = 0, lastVVTop = 0, lastVVWidth = 0, lastVVHeight = 0; 15 let lastScrollX = 0, lastScrollY = 0; 16 let lastResolution = 0; 17 18 function within(a, b, tolerance) { 19 return (Math.abs(a-b) < tolerance); 20 } 21 22 async function afterpaint() { 23 info("vv pos " + visualViewport.pageLeft + "," + visualViewport.pageTop); 24 info("vv size " + visualViewport.width + "," + visualViewport.height); 25 info("win scroll " + window.scrollX + "," + window.scrollY); 26 info("res " + await getResolution()); 27 if (hasPrev) { 28 ok(zoomingIn ? 29 lastVVLeft <= visualViewport.pageLeft : 30 lastVVLeft >= visualViewport.pageLeft, 31 "vvleft monotonic"); 32 // When zooming in pageTop stays 0, when zooming out (at least on mac) 33 // the final value of pageTop is 2.5. Hence why the direction of these 34 // inequalities. 35 ok(zoomingIn ? 36 lastVVTop >= visualViewport.pageTop : 37 lastVVTop <= visualViewport.pageTop, 38 "vvtop monotonic"); 39 ok(zoomingIn ? 40 lastVVWidth >= visualViewport.width : 41 lastVVWidth <= visualViewport.width, 42 "vvwidth monotonic"); 43 ok(zoomingIn ? 44 lastVVHeight >= visualViewport.height : 45 lastVVHeight <= visualViewport.height, 46 "vvheight monotonic"); 47 ok(zoomingIn ? 48 lastScrollX <= window.scrollX : 49 lastScrollX >= window.scrollX, 50 "scrollx monotonic"); 51 if (!within(lastScrollY, window.scrollY, 2)) { 52 ok(zoomingIn ? 53 lastScrollY >= window.scrollY : 54 lastScrollY <= window.scrollY, 55 "scrolly monotonic"); 56 } 57 58 // At the upper and lower limits of zoom constraints we can briefly go over 59 // the limit and then back because of floating point inaccuracies. 60 // In apzc callback helper we set the new content resolution to 61 // (last presshell resolution that apz knows about) * (apz async zoom) 62 // and (apz async zoom) is calculated as (apz zoom) / (last content resolution that apz knows about) 63 // and (last content resolution that apz knows about) = (dev pixels per css pixel) * (ps resolution) * (resolution induced by transforms) 64 // For simplicity we can assume that (dev pixels per css pixel) == (resolution induced by transforms) == 1 65 // and (ps resolution) == (last presshell resolution that apz knows about). 66 // The calculation then boils down to 67 // (ps resolution) * ((apz zoom) / (ps resolution)) 68 // The fact that we divide by (ps resolution) first, and then multiply by 69 // it means the result is not quite equal to (apz zoom). 70 const deviceScale = window.devicePixelRatio; 71 const maxZoom = 10.0; 72 if (!within(lastResolution, maxZoom/deviceScale, 0.0001) && 73 !within(await getResolution(), maxZoom/deviceScale, 0.0001) && 74 !within(lastResolution, 1, 0.0001) && 75 !within(await getResolution(), 1, 0.0001)) { 76 ok(zoomingIn ? 77 lastResolution <= await getResolution() : 78 lastResolution >= await getResolution(), 79 "resolution monotonic"); 80 } 81 82 } else { 83 hasPrev = true; 84 } 85 lastVVLeft = visualViewport.pageLeft; 86 lastVVTop = visualViewport.pageTop; 87 lastVVWidth = visualViewport.width; 88 lastVVHeight = visualViewport.height; 89 lastScrollX = window.scrollX; 90 if (!within(lastScrollY, window.scrollY, 2)) { 91 lastScrollY = window.scrollY; 92 } 93 lastResolution = await getResolution(); 94 } 95 96 async function test() { 97 let useTouchpad = (location.search == "?touchpad"); 98 99 info("dpi: " + window.devicePixelRatio); 100 101 window.addEventListener("MozAfterPaint", afterpaint); 102 let intervalID = setInterval(afterpaint, 16); 103 104 let resolution = await getResolution(); 105 ok(resolution > 0, 106 "The initial_resolution is " + resolution + ", which is some sane value"); 107 108 // Check that double-tapping once on a small element zooms in 109 info("sending first double tap"); 110 await doubleTapOn(document.getElementById("target2"), 10, 10, useTouchpad); 111 let prev_resolution = resolution; 112 resolution = await getResolution(); 113 ok(resolution > prev_resolution, "The first double-tap has increased the resolution to " + resolution); 114 115 await promiseApzFlushedRepaints(); 116 117 hasPrev = false; 118 zoomingIn = false; 119 120 // Double tap, this won't hit anything but the body/html, and so will zoom us out. 121 info("sending second double tap"); 122 await doubleTapOn(document.getElementById("target2"), 5, 65, useTouchpad); 123 await promiseApzFlushedRepaints(); 124 prev_resolution = resolution; 125 resolution = await getResolution(); 126 ok(resolution < prev_resolution, "The second double-tap has decreased the resolution to " + resolution); 127 128 clearInterval(intervalID); 129 window.removeEventListener("MozAfterPaint", afterpaint); 130 } 131 132 waitUntilApzStable() 133 .then(test) 134 .then(subtestDone, subtestFailed); 135 136 </script> 137 <style> 138 .container { 139 background-color: #eee; 140 width: 95vw; 141 height: 400vh; 142 } 143 .smallcontainer { 144 background-color: #aaa; 145 width: 40px; 146 height: 40px; 147 position: absolute; 148 right: 0; 149 top: 20px; 150 } 151 </style> 152 </head> 153 <body> 154 155 <div id="target" class="container"> 156 </div> 157 <div id="target2" class="smallcontainer"> 158 </div> 159 160 </body> 161 </html>