1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/layout/base/tests/test_event_target_radius.html Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,258 @@ 1.4 +<!DOCTYPE HTML> 1.5 +<html id="html" style="height:100%"> 1.6 +<!-- 1.7 +https://bugzilla.mozilla.org/show_bug.cgi?id=780847 1.8 +--> 1.9 +<head> 1.10 + <title>Test radii for mouse events</title> 1.11 + <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> 1.12 + <script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script> 1.13 + <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/> 1.14 + <style> 1.15 + .target { position:absolute; left:100px; top:100px; width:100px; height:100px; background:blue; } 1.16 + </style> 1.17 +</head> 1.18 +<body id="body" onload="setTimeout(startTest, 0)" style="margin:0; width:100%; height:100%; overflow:hidden"> 1.19 +<p id="display"></p> 1.20 +<div id="content"> 1.21 + <div id="ruler" style="position:absolute; left:0; top:0; width:1mozmm; height:0;"></div> 1.22 + 1.23 + <div class="target" id="t" onmousedown="x=1"></div> 1.24 + 1.25 + <div class="target" id="t2" hidden></div> 1.26 + 1.27 + <input class="target" id="t3_1" hidden></input> 1.28 + <a href="#" class="target" id="t3_2" hidden></a> 1.29 + <label class="target" id="t3_3" hidden></label> 1.30 + <button class="target" id="t3_4" hidden></button> 1.31 + <select class="target" id="t3_5" hidden></select> 1.32 + <textarea class="target" id="t3_6" hidden></textarea> 1.33 + <div role="button" class="target" id="t3_7" hidden></div> 1.34 + <div role="key" class="target" id="t3_8" hidden></div> 1.35 + <img class="target" id="t3_9" hidden></img> 1.36 + 1.37 + <div class="target" style="transform:translate(-80px,0);" id="t4" onmousedown="x=1" hidden></div> 1.38 + 1.39 + <div class="target" style="left:0; z-index:1" id="t5_left" onmousedown="x=1" hidden></div> 1.40 + <div class="target" style="left:106px;" id="t5_right" onmousedown="x=1" hidden></div> 1.41 + <div class="target" style="left:0; top:210px;" id="t5_below" onmousedown="x=1" hidden></div> 1.42 + 1.43 + <div class="target" id="t6" onmousedown="x=1" hidden> 1.44 + <div id="t6_inner" style="position:absolute; left:-20px; top:20px; width:60px; height:60px; background:yellow;"></div> 1.45 + </div> 1.46 + 1.47 + <div class="target" id="t7" onmousedown="x=1" hidden></div> 1.48 + <div class="target" id="t7_over" hidden></div> 1.49 + 1.50 + <div id="t8" contenteditable="true" class="target" hidden></div> 1.51 + 1.52 + <div id="t9" class="target" ontouchend="x=1" hidden></div> 1.53 + 1.54 + <div id="t10_left" class="target" style="left:-50px;" onmousedown="x=1" hidden></div> 1.55 + <div id="t10_right" class="target" style="left:auto;right:-50px" onmousedown="x=1" hidden></div> 1.56 + <div id="t10_top" class="target" style="top:-50px;" onmousedown="x=1" hidden></div> 1.57 + <div id="t10_bottom" class="target" style="top:auto;bottom:-50px;" onmousedown="x=1" hidden></div> 1.58 + <div id="t10_over" style="position:absolute; left:0; top:0; width:100%; height:100%; background:yellow;" hidden></div> 1.59 +</div> 1.60 +<pre id="test"> 1.61 +<script type="application/javascript"> 1.62 +function startTest() { 1.63 + SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.enabled", true], 1.64 + ["ui.mouse.radius.inputSource.touchOnly", false], 1.65 + ["ui.mouse.radius.leftmm", 12], 1.66 + ["ui.mouse.radius.topmm", 8], 1.67 + ["ui.mouse.radius.rightmm", 4], 1.68 + ["ui.mouse.radius.bottommm", 4], 1.69 + ["ui.mouse.radius.visitedweight", 50]]}, runTest); 1.70 +} 1.71 + 1.72 + 1.73 +SimpleTest.waitForExplicitFinish(); 1.74 + 1.75 +function endTest() { 1.76 + SimpleTest.finish(); 1.77 +} 1.78 + 1.79 +var eventTarget; 1.80 +window.onmousedown = function(event) { eventTarget = event.target; }; 1.81 + 1.82 +function testMouseClick(idPosition, dx, dy, idTarget, msg, options) { 1.83 + eventTarget = null; 1.84 + synthesizeMouse(document.getElementById(idPosition), dx, dy, options || {}); 1.85 + try { 1.86 + is(eventTarget.id, idTarget, 1.87 + "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]"); 1.88 + } catch (ex) { 1.89 + ok(false, "checking '" + idPosition + "' offset " + dx + "," + dy + " [" + msg + "]; got " + eventTarget); 1.90 + } 1.91 +} 1.92 + 1.93 +function setShowing(id, show) { 1.94 + var e = document.getElementById(id); 1.95 + e.hidden = !show; 1.96 +} 1.97 + 1.98 +var mm; 1.99 +function runTest() { 1.100 + mm = document.getElementById("ruler").getBoundingClientRect().width; 1.101 + ok(4*mm >= 10, "WARNING: mm " + mm + " too small in this configuration. Test results will be bogus"); 1.102 + 1.103 + // Test basic functionality: clicks sufficiently close to the element 1.104 + // should be allowed to hit the element. We test points just inside and 1.105 + // just outside the edges we set up in the prefs. 1.106 + testMouseClick("t", 100 + 13*mm, 10, "body", "basic functionality"); 1.107 + testMouseClick("t", 100 + 11*mm, 10, "t", "basic functionality"); 1.108 + testMouseClick("t", 10, 100 + 9*mm, "body", "basic functionality"); 1.109 + testMouseClick("t", 10, 100 + 7*mm, "t", "basic functionality"); 1.110 + testMouseClick("t", -5*mm, 10, "body", "basic functionality"); 1.111 + testMouseClick("t", -3*mm, 10, "t", "basic functionality"); 1.112 + testMouseClick("t", 10, -5*mm, "body", "basic functionality"); 1.113 + testMouseClick("t", 10, -3*mm, "t", "basic functionality"); 1.114 + 1.115 + // When inputSource.touchOnly is true, mouse input is not retargeted. 1.116 + SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.inputSource.touchOnly", true]]}, test2); 1.117 +} 1.118 + 1.119 +function test2() { 1.120 + testMouseClick("t", 100 + 11*mm, 10, "body", "disabled for mouse input"); 1.121 + testMouseClick("t", 100 + 11*mm, 10, "t", "enabled for touch input", { 1.122 + inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH 1.123 + }); 1.124 + testMouseClick("t", 100 + 13*mm, 10, "body", "basic functionality for touch", { 1.125 + inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH 1.126 + }); 1.127 + SpecialPowers.pushPrefEnv({"set": [["ui.mouse.radius.inputSource.touchOnly", false]]}, test3); 1.128 +} 1.129 + 1.130 +function test3() { 1.131 + setShowing("t", false); 1.132 + 1.133 + // Now test the criteria we use to determine which elements are hittable 1.134 + // this way. 1.135 + 1.136 + setShowing("t2", true); 1.137 + var t2 = document.getElementById("t2"); 1.138 + // Unadorned DIVs are not click radius targets 1.139 + testMouseClick("t2", 100 + 11*mm, 10, "body", "unadorned DIV"); 1.140 + // DIVs with the right event handlers are click radius targets 1.141 + t2.onmousedown = function() {}; 1.142 + testMouseClick("t2", 100 + 11*mm, 10, "t2", "DIV with onmousedown"); 1.143 + t2.onmousedown = null; 1.144 + testMouseClick("t2", 100 + 11*mm, 10, "body", "DIV with onmousedown removed"); 1.145 + t2.onmouseup = function() {}; 1.146 + testMouseClick("t2", 100 + 11*mm, 10, "t2", "DIV with onmouseup"); 1.147 + t2.onmouseup = null; 1.148 + t2.onclick = function() {}; 1.149 + testMouseClick("t2", 100 + 11*mm, 10, "t2", "DIV with onclick"); 1.150 + t2.onclick = null; 1.151 + // Keypresses don't make click radius targets 1.152 + t2.onkeypress = function() {}; 1.153 + testMouseClick("t2", 100 + 11*mm, 10, "body", "DIV with onkeypress"); 1.154 + t2.onkeypress = null; 1.155 + setShowing("t2", false); 1.156 + 1.157 + // Now check that certain elements are click radius targets and others are not 1.158 + for (var i = 1; i <= 9; ++i) { 1.159 + var id = "t3_" + i; 1.160 + var shouldHit = i <= 8; 1.161 + setShowing(id, true); 1.162 + testMouseClick(id, 100 + 11*mm, 10, shouldHit ? id : "body", 1.163 + "<" + document.getElementById(id).tagName + "> element"); 1.164 + setShowing(id, false); 1.165 + } 1.166 + 1.167 + // Check that our targeting computations take into account the effects of 1.168 + // CSS transforms 1.169 + setShowing("t4", true); 1.170 + testMouseClick("t4", -1, 10, "t4", "translated DIV"); 1.171 + setShowing("t4", false); 1.172 + 1.173 + // Test the prioritization of multiple targets based on distance to 1.174 + // the target. 1.175 + setShowing("t5_left", true); 1.176 + setShowing("t5_right", true); 1.177 + setShowing("t5_below", true); 1.178 + testMouseClick("t5_left", 102, 10, "t5_left", "closest DIV is left"); 1.179 + testMouseClick("t5_left", 102.5, 10, "t5_left", 1.180 + "closest DIV to midpoint is left because of its higher z-index"); 1.181 + testMouseClick("t5_left", 104, 10, "t5_right", "closest DIV is right"); 1.182 + testMouseClick("t5_left", 10, 104, "t5_left", "closest DIV is left"); 1.183 + testMouseClick("t5_left", 10, 105, "t5_left", 1.184 + "closest DIV to midpoint is left because of its higher z-index"); 1.185 + testMouseClick("t5_left", 10, 106, "t5_below", "closest DIV is below"); 1.186 + setShowing("t5_left", false); 1.187 + setShowing("t5_right", false); 1.188 + setShowing("t5_below", false); 1.189 + 1.190 + // Test behavior of nested elements. 1.191 + // The following behaviors are questionable and may need to be changed. 1.192 + setShowing("t6", true); 1.193 + testMouseClick("t6_inner", -1, 10, "t6_inner", 1.194 + "inner element is clickable because its parent is, even when it sticks outside parent"); 1.195 + testMouseClick("t6_inner", 19, -1, "t6_inner", 1.196 + "when outside both inner and parent, but in range of both, the inner is selected"); 1.197 + testMouseClick("t6_inner", 25, -1, "t6", 1.198 + "clicking in clickable parent close to inner activates parent, not inner"); 1.199 + setShowing("t6", false); 1.200 + 1.201 + setShowing("t7", true); 1.202 + setShowing("t7_over", true); 1.203 + testMouseClick("t7", 100 + 11*mm, 10, "body", "covered div is not clickable"); 1.204 + testMouseClick("t7", 10, 10, "t7_over", "covered div is not clickable even within its bounds"); 1.205 + setShowing("t7", false); 1.206 + setShowing("t7_over", false); 1.207 + 1.208 + // Check that contenteditable elements are considered clickable for fluffing. 1.209 + setShowing("t8", true); 1.210 + var rect = document.getElementById("t8").getBoundingClientRect(); 1.211 + testMouseClick("t8", rect.left + 1, rect.top + 1, "t8", "content editable enabled for mouse input"); 1.212 + testMouseClick("t8", rect.left + 1, rect.top + 1, "t8", "content editable enabled for touch input", { 1.213 + inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH 1.214 + }); 1.215 + setShowing("t8", false); 1.216 + 1.217 + // Check that elements are touchable 1.218 + setShowing("t9", true); 1.219 + var rect = document.getElementById("t9").getBoundingClientRect(); 1.220 + testMouseClick("t9", rect.left + 1, rect.top + 1, "t9", "div enabled with mouse input"); 1.221 + testMouseClick("t9", rect.left + 1, rect.top + 1, "t9", "div enabled with touch input", { 1.222 + inputSource: SpecialPowers.Ci.nsIDOMMouseEvent.MOZ_SOURCE_TOUCH 1.223 + }); 1.224 + setShowing("t9", false); 1.225 + 1.226 + setShowing("t10_over", true); 1.227 + setShowing("t10_left", true); 1.228 + setShowing("t10_right", true); 1.229 + setShowing("t10_top", true); 1.230 + setShowing("t10_bottom", true); 1.231 + testMouseClick("t10_left", 51, 10, "t10_over", "element outside of visible area is not selected"); 1.232 + if (self.frameElement && 1.233 + (self.frameElement.offsetLeft + self.innerWidth > 1.234 + SpecialPowers.wrap(top).innerWidth)) { 1.235 + info("WARNING: Window is too narrow, can't test t10_right"); 1.236 + } else { 1.237 + testMouseClick("t10_right", 49, 10, "t10_over", "element outside of visible area is not selected"); 1.238 + } 1.239 + testMouseClick("t10_top", 10, 51, "t10_over", "element outside of visible area is not selected"); 1.240 + if (self.frameElement && 1.241 + (self.frameElement.offsetTop + self.innerHeight > 1.242 + SpecialPowers.wrap(top).innerHeight)) { 1.243 + info("WARNING: Window is too short, can't test t10_bottom"); 1.244 + } else { 1.245 + testMouseClick("t10_bottom", 10, 49, "t10_over", "element outside of visible area is not selected"); 1.246 + } 1.247 + setShowing("t10_over", false); 1.248 + setShowing("t10_left", false); 1.249 + setShowing("t10_right", false); 1.250 + setShowing("t10_top", false); 1.251 + setShowing("t10_bottom", false); 1.252 + 1.253 + // Not yet tested: 1.254 + // -- visited link weight 1.255 + // -- "Closest" using Euclidean distance 1.256 + endTest(); 1.257 +} 1.258 +</script> 1.259 +</pre> 1.260 +</body> 1.261 +</html>