toolkit/content/tests/chrome/test_contextmenu_list.xul

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/toolkit/content/tests/chrome/test_contextmenu_list.xul	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,278 @@
     1.4 +<?xml version="1.0"?>
     1.5 +<?xml-stylesheet href="chrome://global/skin" type="text/css"?>
     1.6 +<?xml-stylesheet href="chrome://mochikit/content/tests/SimpleTest/test.css" type="text/css"?>
     1.7 +
     1.8 +<window title="Context Menu on List Tests"
     1.9 +        onload="setTimeout(startTest, 0);"
    1.10 +        xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
    1.11 +
    1.12 +  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>      
    1.13 +  <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>      
    1.14 +
    1.15 +<spacer height="5"/>
    1.16 +
    1.17 +<hbox style="padding-left: 10px;">
    1.18 +  <spacer width="5"/>
    1.19 +  <richlistbox id="list" context="themenu" style="padding: 0;" oncontextmenu="checkContextMenu(event)">
    1.20 +    <richlistitem id="item1" style="padding-top: 3px; margin: 0;"><button label="One"/></richlistitem>
    1.21 +    <richlistitem id="item2" height="22"><checkbox label="Checkbox"/></richlistitem>
    1.22 +    <richlistitem id="item3"><button label="Three"/></richlistitem>
    1.23 +    <richlistitem id="item4"><checkbox label="Four"/></richlistitem>
    1.24 +  </richlistbox>
    1.25 +
    1.26 +  <tree id="tree" rows="5" flex="1" context="themenu" style="-moz-appearance: none; border: 0">
    1.27 +    <treecols>
    1.28 +      <treecol label="Name" flex="1"/>
    1.29 +      <splitter class="tree-splitter"/>
    1.30 +      <treecol label="Moons"/>
    1.31 +    </treecols>
    1.32 +    <treechildren id="treechildren">
    1.33 +      <treeitem>
    1.34 +        <treerow>
    1.35 +          <treecell label="Mercury"/>
    1.36 +          <treecell label="0"/>
    1.37 +        </treerow>
    1.38 +      </treeitem>
    1.39 +      <treeitem>
    1.40 +        <treerow>
    1.41 +          <treecell label="Venus"/>
    1.42 +          <treecell label="0"/>
    1.43 +        </treerow>
    1.44 +      </treeitem>
    1.45 +      <treeitem>
    1.46 +        <treerow>
    1.47 +          <treecell label="Earth"/>
    1.48 +          <treecell label="1"/>
    1.49 +        </treerow>
    1.50 +      </treeitem>
    1.51 +      <treeitem>
    1.52 +        <treerow>
    1.53 +          <treecell label="Mars"/>
    1.54 +          <treecell label="2"/>
    1.55 +        </treerow>
    1.56 +       </treeitem>
    1.57 +    </treechildren>
    1.58 +  </tree>
    1.59 +
    1.60 +  <menu id="menu" label="Menu">
    1.61 +    <menupopup id="menupopup" onpopupshown="menuTests()" onpopuphidden="nextTest()"
    1.62 +               oncontextmenu="checkContextMenuForMenu(event)">
    1.63 +      <menuitem id="menu1" label="Menu 1"/>
    1.64 +      <menuitem id="menu2" label="Menu 2"/>
    1.65 +      <menuitem id="menu3" label="Menu 3"/>
    1.66 +    </menupopup>
    1.67 +  </menu>
    1.68 +
    1.69 +</hbox>
    1.70 +
    1.71 +<menupopup id="themenu" onpopupshowing="if (gTestId == -1) event.preventDefault()"
    1.72 +                        onpopupshown="checkPopup()" onpopuphidden="setTimeout(nextTest, 0);">
    1.73 +  <menuitem label="Item"/>
    1.74 +</menupopup>
    1.75 +
    1.76 +<script class="testbody" type="application/javascript">
    1.77 +<![CDATA[
    1.78 +
    1.79 +SimpleTest.waitForExplicitFinish();
    1.80 +
    1.81 +var gTestId = -1;
    1.82 +var gTestElement = "list";
    1.83 +var gSelectionStep = 0;
    1.84 +var gContextMenuFired = false;
    1.85 +
    1.86 +function startTest()
    1.87 +{
    1.88 +  // first, check if the richlistbox selection changes on a contextmenu mouse event
    1.89 +  var element = $("list");
    1.90 +  synthesizeMouse(element.getItemAtIndex(3), 7, 1, { type : "mousedown", button: 2, ctrlKey: true });
    1.91 +  synthesizeMouse(element, 7, 4, { type : "contextmenu", button: 2 });
    1.92 +
    1.93 +  gSelectionStep++;
    1.94 +  synthesizeMouse(element.getItemAtIndex(1), 7, 1, { type : "mousedown", button: 2, ctrlKey: true, shiftKey: true });
    1.95 +  synthesizeMouse(element, 7, 4, { type : "contextmenu", button: 2 });
    1.96 +
    1.97 +  gSelectionStep++;
    1.98 +  synthesizeMouse(element.getItemAtIndex(1), 7, 1, { type : "mousedown", button: 2 });
    1.99 +  synthesizeMouse(element, 7, 4, { type : "contextmenu", button: 2 });
   1.100 +
   1.101 +  $("menu").open = true;
   1.102 +}
   1.103 +
   1.104 +function menuTests()
   1.105 +{
   1.106 +  gSelectionStep = 0;
   1.107 +  var element = $("menu");
   1.108 +  synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
   1.109 +  is(gContextMenuFired, true, "context menu fired when menu open");
   1.110 +
   1.111 +  gSelectionStep = 1;
   1.112 +  $("menu").boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject).activeChild = $("menu2");
   1.113 +  synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
   1.114 +
   1.115 +  $("menu").open = false;
   1.116 +}
   1.117 +
   1.118 +function nextTest()
   1.119 +{
   1.120 +  gTestId++;
   1.121 +  if (gTestId > 2) {
   1.122 +    if (gTestElement == "list") {
   1.123 +      gTestElement = "tree";
   1.124 +      gTestId = 0;
   1.125 +    }
   1.126 +    else {
   1.127 +      SimpleTest.finish();
   1.128 +      return;
   1.129 +    }
   1.130 +  }
   1.131 +  var element = $(gTestElement);
   1.132 +  element.focus();
   1.133 +  if (gTestId == 0) {
   1.134 +    if (gTestElement == "list")
   1.135 +      element.selectedIndex = 2;
   1.136 +    element.currentIndex = 2;
   1.137 +    synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
   1.138 +  }
   1.139 +  else if (gTestId == 1) {
   1.140 +    synthesizeMouse(element, 7, 4, { type : "contextmenu", button: 2 });
   1.141 +  }
   1.142 +  else {
   1.143 +    element.currentIndex = -1;
   1.144 +    element.selectedIndex = -1;
   1.145 +    synthesizeMouse(element, 0, 0, { type : "contextmenu", button: 0 });
   1.146 +  }
   1.147 +}
   1.148 +
   1.149 +// This is nasty so I'd better explain what's going on.
   1.150 +// The basic problem is that the synthetic mouse coordinate generated
   1.151 +// by DOMWindowUtils.sendMouseEvent and also the synthetic mouse coordinate
   1.152 +// generated internally when contextmenu events are redirected to the focused
   1.153 +// element are rounded to the nearest device pixel. But this rounding is done
   1.154 +// while the coordinates are relative to the nearest widget. When this test
   1.155 +// is run in the mochitest harness, the nearest widget is the main mochitest
   1.156 +// window, and our document can have a fractional position within that
   1.157 +// mochitest window. So when we round coordinates for comparison in this
   1.158 +// test, we need to do so very carefully, especially if the target element
   1.159 +// also has a fractional position within our document.
   1.160 +//
   1.161 +// For example, if the y-offset of our containing IFRAME is 100.4px,
   1.162 +// and the offset of our expected point is 10.3px in our document, the actual
   1.163 +// mouse event is dispatched to round(110.7) == 111px. This comes back
   1.164 +// with a clientY of round(111 - 100.4) == round(10.6) == 11. This is not
   1.165 +// equal to round(10.3) as you might expect.
   1.166 +
   1.167 +function isRoundedX(a, b, msg)
   1.168 +{
   1.169 +  is(Math.round(a + mozInnerScreenX), Math.round(b + mozInnerScreenX), msg);
   1.170 +}
   1.171 +
   1.172 +function isRoundedY(a, b, msg)
   1.173 +{
   1.174 +  is(Math.round(a + mozInnerScreenY), Math.round(b + mozInnerScreenY), msg);
   1.175 +}
   1.176 +
   1.177 +function checkContextMenu(event)
   1.178 +{
   1.179 +  var rect = $(gTestElement).getBoundingClientRect();
   1.180 +
   1.181 +  var frombase = (gTestId == -1 || gTestId == 1);
   1.182 +  if (!frombase)
   1.183 +    rect = event.originalTarget.getBoundingClientRect();
   1.184 +  var left = frombase ? rect.left + 7 : rect.left;
   1.185 +  var top = frombase ? rect.top + 4 : rect.bottom;
   1.186 +
   1.187 +  isRoundedX(event.clientX, left, gTestElement + " clientX " + gSelectionStep + " " + gTestId + "," + frombase);
   1.188 +  isRoundedY(event.clientY, top, gTestElement + " clientY " + gSelectionStep + " " + gTestId);
   1.189 +  ok(event.screenX > left, gTestElement + " screenX " + gSelectionStep + " " + gTestId);
   1.190 +  ok(event.screenY > top, gTestElement + " screenY " + gSelectionStep + " " + gTestId);
   1.191 +
   1.192 +  // context menu from mouse click
   1.193 +  switch (gTestId) {
   1.194 +    case -1:
   1.195 +      var expected = gSelectionStep == 2 ? 1 : (navigator.platform.indexOf("Mac") >= 0 ? 3 : 0);
   1.196 +      is($(gTestElement).selectedIndex, expected, "index after click " + gSelectionStep);
   1.197 +      break;
   1.198 +    case 0:
   1.199 +      if (gTestElement == "list")
   1.200 +        is(event.originalTarget, $("item3"), "list selection target");
   1.201 +      else
   1.202 +        is(event.originalTarget, $("treechildren"), "tree selection target");
   1.203 +      break;
   1.204 +    case 1:
   1.205 +      is(event.originalTarget.id, $("item1").id, "list mouse selection target");
   1.206 +      break;
   1.207 +    case 2:
   1.208 +      is(event.originalTarget, $("list"), "list no selection target");
   1.209 +      break;
   1.210 +  }
   1.211 +}
   1.212 +
   1.213 +function checkContextMenuForMenu(event)
   1.214 +{
   1.215 +  gContextMenuFired = true;
   1.216 +
   1.217 +  var popuprect = (gSelectionStep ? $("menu2") : $("menupopup")).getBoundingClientRect();
   1.218 +  is(event.clientX, Math.round(popuprect.left), "menu left " + gSelectionStep);
   1.219 +  // the clientY is off by one sometimes on Windows (when loaded in the testing iframe
   1.220 +  // but not when loaded separately) so just check for both cases for now
   1.221 +  ok(event.clientY == Math.round(popuprect.bottom) ||
   1.222 +     event.clientY - 1 == Math.round(popuprect.bottom), "menu top " + gSelectionStep);
   1.223 +}
   1.224 +
   1.225 +function checkPopup()
   1.226 +{
   1.227 +  var menurect = $("themenu").getBoundingClientRect();
   1.228 +
   1.229 +  if (gTestId == 0) {
   1.230 +    if (gTestElement == "list") {
   1.231 +      var itemrect = $("item3").getBoundingClientRect();
   1.232 +      isRoundedX(menurect.left, itemrect.left + 2,
   1.233 +         "list selection keyboard left");
   1.234 +      isRoundedY(menurect.top, itemrect.bottom + 2,
   1.235 +         "list selection keyboard top");
   1.236 +    }
   1.237 +    else {
   1.238 +      var tree = $("tree");
   1.239 +      var bodyrect = $("treechildren").getBoundingClientRect();
   1.240 +      isRoundedX(menurect.left, bodyrect.left + 2,
   1.241 +         "tree selection keyboard left");
   1.242 +      isRoundedY(menurect.top, bodyrect.top +
   1.243 +         tree.treeBoxObject.rowHeight * 3 + 2,
   1.244 +         "tree selection keyboard top");
   1.245 +    }
   1.246 +  }
   1.247 +  else if (gTestId == 1) {
   1.248 +    // activating a context menu with the mouse from position (7, 1).
   1.249 +    // Add 2 pixels to these values as context menus are offset by 2 pixels
   1.250 +    // so that they don't appear exactly only the menu making them easier to
   1.251 +    // dismiss. See nsXULPopupListener.
   1.252 +    var elementrect = $(gTestElement).getBoundingClientRect();
   1.253 +    isRoundedX(menurect.left, elementrect.left + 9,
   1.254 +       gTestElement + " mouse left");
   1.255 +    isRoundedY(menurect.top, elementrect.top + 6,
   1.256 +       gTestElement + " mouse top");
   1.257 +  }
   1.258 +  else {
   1.259 +    var elementrect = $(gTestElement).getBoundingClientRect();
   1.260 +    isRoundedX(menurect.left, elementrect.left + 2,
   1.261 +       gTestElement + " no selection keyboard left");
   1.262 +    isRoundedY(menurect.top, elementrect.bottom + 2,
   1.263 +       gTestElement + " no selection keyboard top");
   1.264 +  }
   1.265 +
   1.266 +  $("themenu").hidePopup();
   1.267 +}
   1.268 +
   1.269 +]]>
   1.270 +</script>
   1.271 +
   1.272 +<body xmlns="http://www.w3.org/1999/xhtml">
   1.273 +<p id="display">
   1.274 +</p>
   1.275 +<div id="content" style="display: none">
   1.276 +</div>
   1.277 +<pre id="test">
   1.278 +</pre>
   1.279 +</body>
   1.280 +
   1.281 +</window>

mercurial