browser/base/content/test/general/browser_gestureSupport.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/browser/base/content/test/general/browser_gestureSupport.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,671 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +// Simple gestures tests
     1.9 +//
    1.10 +// These tests require the ability to disable the fact that the
    1.11 +// Firefox chrome intentionally prevents "simple gesture" events from
    1.12 +// reaching web content.
    1.13 +
    1.14 +let test_utils;
    1.15 +let test_commandset;
    1.16 +let test_prefBranch = "browser.gesture.";
    1.17 +
    1.18 +function test()
    1.19 +{
    1.20 +  waitForExplicitFinish();
    1.21 +
    1.22 +  // Disable the default gestures support during the test
    1.23 +  gGestureSupport.init(false);
    1.24 +
    1.25 +  test_utils = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor).
    1.26 +    getInterface(Components.interfaces.nsIDOMWindowUtils);
    1.27 +
    1.28 +  // Run the tests of "simple gesture" events generally
    1.29 +  test_EnsureConstantsAreDisjoint();
    1.30 +  test_TestEventListeners();
    1.31 +  test_TestEventCreation();
    1.32 +
    1.33 +  // Reenable the default gestures support. The remaining tests target
    1.34 +  // the Firefox gesture functionality.
    1.35 +  gGestureSupport.init(true);
    1.36 +
    1.37 +  // Test Firefox's gestures support.
    1.38 +  test_commandset = document.getElementById("mainCommandSet");
    1.39 +  test_swipeGestures();
    1.40 +  test_latchedGesture("pinch", "out", "in", "MozMagnifyGesture");
    1.41 +  test_thresholdGesture("pinch", "out", "in", "MozMagnifyGesture");
    1.42 +  test_rotateGestures();
    1.43 +}
    1.44 +
    1.45 +let test_eventCount = 0;
    1.46 +let test_expectedType;
    1.47 +let test_expectedDirection;
    1.48 +let test_expectedDelta;
    1.49 +let test_expectedModifiers;
    1.50 +let test_expectedClickCount;
    1.51 +let test_imageTab;
    1.52 +
    1.53 +function test_gestureListener(evt)
    1.54 +{
    1.55 +  is(evt.type, test_expectedType,
    1.56 +     "evt.type (" + evt.type + ") does not match expected value");
    1.57 +  is(evt.target, test_utils.elementFromPoint(20, 20, false, false),
    1.58 +     "evt.target (" + evt.target + ") does not match expected value");
    1.59 +  is(evt.clientX, 20,
    1.60 +     "evt.clientX (" + evt.clientX + ") does not match expected value");
    1.61 +  is(evt.clientY, 20,
    1.62 +     "evt.clientY (" + evt.clientY + ") does not match expected value");
    1.63 +  isnot(evt.screenX, 0,
    1.64 +        "evt.screenX (" + evt.screenX + ") does not match expected value");
    1.65 +  isnot(evt.screenY, 0,
    1.66 +        "evt.screenY (" + evt.screenY + ") does not match expected value");
    1.67 +
    1.68 +  is(evt.direction, test_expectedDirection,
    1.69 +     "evt.direction (" + evt.direction + ") does not match expected value");
    1.70 +  is(evt.delta, test_expectedDelta,
    1.71 +     "evt.delta (" + evt.delta + ") does not match expected value");
    1.72 +
    1.73 +  is(evt.shiftKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.SHIFT_MASK) != 0,
    1.74 +     "evt.shiftKey did not match expected value");
    1.75 +  is(evt.ctrlKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.CONTROL_MASK) != 0,
    1.76 +     "evt.ctrlKey did not match expected value");
    1.77 +  is(evt.altKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.ALT_MASK) != 0,
    1.78 +     "evt.altKey did not match expected value");
    1.79 +  is(evt.metaKey, (test_expectedModifiers & Components.interfaces.nsIDOMEvent.META_MASK) != 0,
    1.80 +     "evt.metaKey did not match expected value");
    1.81 +
    1.82 +  if (evt.type == "MozTapGesture") {
    1.83 +    is(evt.clickCount, test_expectedClickCount, "evt.clickCount does not match");
    1.84 +  }
    1.85 +
    1.86 +  test_eventCount++;
    1.87 +}
    1.88 +
    1.89 +function test_helper1(type, direction, delta, modifiers)
    1.90 +{
    1.91 +  // Setup the expected values
    1.92 +  test_expectedType = type;
    1.93 +  test_expectedDirection = direction;
    1.94 +  test_expectedDelta = delta;
    1.95 +  test_expectedModifiers = modifiers;
    1.96 +
    1.97 +  let expectedEventCount = test_eventCount + 1;
    1.98 +
    1.99 +  document.addEventListener(type, test_gestureListener, true);
   1.100 +  test_utils.sendSimpleGestureEvent(type, 20, 20, direction, delta, modifiers);
   1.101 +  document.removeEventListener(type, test_gestureListener, true);
   1.102 +
   1.103 +  is(expectedEventCount, test_eventCount, "Event (" + type + ") was never received by event listener");
   1.104 +}
   1.105 +
   1.106 +function test_clicks(type, clicks)
   1.107 +{
   1.108 +  // Setup the expected values
   1.109 +  test_expectedType = type;
   1.110 +  test_expectedDirection = 0;
   1.111 +  test_expectedDelta = 0;
   1.112 +  test_expectedModifiers = 0;
   1.113 +  test_expectedClickCount = clicks;
   1.114 +
   1.115 +  let expectedEventCount = test_eventCount + 1;
   1.116 +
   1.117 +  document.addEventListener(type, test_gestureListener, true);
   1.118 +  test_utils.sendSimpleGestureEvent(type, 20, 20, 0, 0, 0, clicks);
   1.119 +  document.removeEventListener(type, test_gestureListener, true);
   1.120 +
   1.121 +  is(expectedEventCount, test_eventCount, "Event (" + type + ") was never received by event listener");
   1.122 +}
   1.123 +
   1.124 +function test_TestEventListeners()
   1.125 +{
   1.126 +  let e = test_helper1;  // easier to type this name
   1.127 +
   1.128 +  // Swipe gesture animation events
   1.129 +  e("MozSwipeGestureStart", 0, -0.7, 0);
   1.130 +  e("MozSwipeGestureUpdate", 0, -0.4, 0);
   1.131 +  e("MozSwipeGestureEnd", 0, 0, 0);
   1.132 +  e("MozSwipeGestureStart", 0, 0.6, 0);
   1.133 +  e("MozSwipeGestureUpdate", 0, 0.3, 0);
   1.134 +  e("MozSwipeGestureEnd", 0, 1, 0);
   1.135 +
   1.136 +  // Swipe gesture event
   1.137 +  e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0);
   1.138 +  e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0);
   1.139 +  e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_UP, 0.0, 0);
   1.140 +  e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_DOWN, 0.0, 0);
   1.141 +  e("MozSwipeGesture",
   1.142 +    SimpleGestureEvent.DIRECTION_UP | SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0);
   1.143 +  e("MozSwipeGesture",
   1.144 +    SimpleGestureEvent.DIRECTION_DOWN | SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0);
   1.145 +  e("MozSwipeGesture",
   1.146 +    SimpleGestureEvent.DIRECTION_UP | SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0);
   1.147 +  e("MozSwipeGesture",
   1.148 +    SimpleGestureEvent.DIRECTION_DOWN | SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0);
   1.149 +
   1.150 +  // magnify gesture events
   1.151 +  e("MozMagnifyGestureStart", 0, 50.0, 0);
   1.152 +  e("MozMagnifyGestureUpdate", 0, -25.0, 0);
   1.153 +  e("MozMagnifyGestureUpdate", 0, 5.0, 0);
   1.154 +  e("MozMagnifyGesture", 0, 30.0, 0);
   1.155 +
   1.156 +  // rotate gesture events
   1.157 +  e("MozRotateGestureStart", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0);
   1.158 +  e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE, -13.0, 0);
   1.159 +  e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_CLOCKWISE, 13.0, 0);
   1.160 +  e("MozRotateGesture", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0);
   1.161 +  
   1.162 +  // Tap and presstap gesture events
   1.163 +  test_clicks("MozTapGesture", 1);
   1.164 +  test_clicks("MozTapGesture", 2);
   1.165 +  test_clicks("MozTapGesture", 3);
   1.166 +  test_clicks("MozPressTapGesture", 1);
   1.167 +
   1.168 +  // simple delivery test for edgeui gestures
   1.169 +  e("MozEdgeUIStarted", 0, 0, 0);
   1.170 +  e("MozEdgeUICanceled", 0, 0, 0);
   1.171 +  e("MozEdgeUICompleted", 0, 0, 0);
   1.172 +
   1.173 +  // event.shiftKey
   1.174 +  let modifier = Components.interfaces.nsIDOMEvent.SHIFT_MASK;
   1.175 +  e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
   1.176 +
   1.177 +  // event.metaKey
   1.178 +  modifier = Components.interfaces.nsIDOMEvent.META_MASK;
   1.179 +  e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
   1.180 +
   1.181 +  // event.altKey
   1.182 +  modifier = Components.interfaces.nsIDOMEvent.ALT_MASK;
   1.183 +  e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
   1.184 +
   1.185 +  // event.ctrlKey
   1.186 +  modifier = Components.interfaces.nsIDOMEvent.CONTROL_MASK;
   1.187 +  e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
   1.188 +}
   1.189 +
   1.190 +function test_eventDispatchListener(evt)
   1.191 +{
   1.192 +  test_eventCount++;
   1.193 +  evt.stopPropagation();
   1.194 +}
   1.195 +
   1.196 +function test_helper2(type, direction, delta, altKey, ctrlKey, shiftKey, metaKey)
   1.197 +{
   1.198 +  let event = null;
   1.199 +  let successful;
   1.200 +
   1.201 +  try {
   1.202 +    event = document.createEvent("SimpleGestureEvent");
   1.203 +    successful = true;
   1.204 +  }
   1.205 +  catch (ex) {
   1.206 +    successful = false;
   1.207 +  }
   1.208 +  ok(successful, "Unable to create SimpleGestureEvent");
   1.209 +
   1.210 +  try {
   1.211 +    event.initSimpleGestureEvent(type, true, true, window, 1,
   1.212 +                                 10, 10, 10, 10,
   1.213 +                                 ctrlKey, altKey, shiftKey, metaKey,
   1.214 +                                 1, window,
   1.215 +                                 0, direction, delta, 0);
   1.216 +    successful = true;
   1.217 +  }
   1.218 +  catch (ex) {
   1.219 +    successful = false;
   1.220 +  }
   1.221 +  ok(successful, "event.initSimpleGestureEvent should not fail");
   1.222 +
   1.223 +  // Make sure the event fields match the expected values
   1.224 +  is(event.type, type, "Mismatch on evt.type");
   1.225 +  is(event.direction, direction, "Mismatch on evt.direction");
   1.226 +  is(event.delta, delta, "Mismatch on evt.delta");
   1.227 +  is(event.altKey, altKey, "Mismatch on evt.altKey");
   1.228 +  is(event.ctrlKey, ctrlKey, "Mismatch on evt.ctrlKey");
   1.229 +  is(event.shiftKey, shiftKey, "Mismatch on evt.shiftKey");
   1.230 +  is(event.metaKey, metaKey, "Mismatch on evt.metaKey");
   1.231 +  is(event.view, window, "Mismatch on evt.view");
   1.232 +  is(event.detail, 1, "Mismatch on evt.detail");
   1.233 +  is(event.clientX, 10, "Mismatch on evt.clientX");
   1.234 +  is(event.clientY, 10, "Mismatch on evt.clientY");
   1.235 +  is(event.screenX, 10, "Mismatch on evt.screenX");
   1.236 +  is(event.screenY, 10, "Mismatch on evt.screenY");
   1.237 +  is(event.button, 1, "Mismatch on evt.button");
   1.238 +  is(event.relatedTarget, window, "Mismatch on evt.relatedTarget");
   1.239 +
   1.240 +  // Test event dispatch
   1.241 +  let expectedEventCount = test_eventCount + 1;
   1.242 +  document.addEventListener(type, test_eventDispatchListener, true);
   1.243 +  document.dispatchEvent(event);
   1.244 +  document.removeEventListener(type, test_eventDispatchListener, true);
   1.245 +  is(expectedEventCount, test_eventCount, "Dispatched event was never received by listener");
   1.246 +}
   1.247 +
   1.248 +function test_TestEventCreation()
   1.249 +{
   1.250 +  // Event creation
   1.251 +  test_helper2("MozMagnifyGesture", SimpleGestureEvent.DIRECTION_RIGHT, 20.0,
   1.252 +               true, false, true, false);
   1.253 +  test_helper2("MozMagnifyGesture", SimpleGestureEvent.DIRECTION_LEFT, -20.0,
   1.254 +               false, true, false, true);
   1.255 +}
   1.256 +
   1.257 +function test_EnsureConstantsAreDisjoint()
   1.258 +{
   1.259 +  let up = SimpleGestureEvent.DIRECTION_UP;
   1.260 +  let down = SimpleGestureEvent.DIRECTION_DOWN;
   1.261 +  let left = SimpleGestureEvent.DIRECTION_LEFT;
   1.262 +  let right = SimpleGestureEvent.DIRECTION_RIGHT;
   1.263 +
   1.264 +  let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE;
   1.265 +  let cclockwise = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE;
   1.266 +
   1.267 +  ok(up ^ down, "DIRECTION_UP and DIRECTION_DOWN are not bitwise disjoint");
   1.268 +  ok(up ^ left, "DIRECTION_UP and DIRECTION_LEFT are not bitwise disjoint");
   1.269 +  ok(up ^ right, "DIRECTION_UP and DIRECTION_RIGHT are not bitwise disjoint");
   1.270 +  ok(down ^ left, "DIRECTION_DOWN and DIRECTION_LEFT are not bitwise disjoint");
   1.271 +  ok(down ^ right, "DIRECTION_DOWN and DIRECTION_RIGHT are not bitwise disjoint");
   1.272 +  ok(left ^ right, "DIRECTION_LEFT and DIRECTION_RIGHT are not bitwise disjoint");
   1.273 +  ok(clockwise ^ cclockwise, "ROTATION_CLOCKWISE and ROTATION_COUNTERCLOCKWISE are not bitwise disjoint");
   1.274 +}
   1.275 +
   1.276 +// Helper for test of latched event processing. Emits the actual
   1.277 +// gesture events to test whether the commands associated with the
   1.278 +// gesture will only trigger once for each direction of movement.
   1.279 +function test_emitLatchedEvents(eventPrefix, initialDelta, cmd)
   1.280 +{
   1.281 +  let cumulativeDelta = 0;
   1.282 +  let isIncreasing = initialDelta > 0;
   1.283 +
   1.284 +  let expect = {};
   1.285 +  // Reset the call counters and initialize expected values
   1.286 +  for (let dir in cmd)
   1.287 +    cmd[dir].callCount = expect[dir] = 0;
   1.288 +
   1.289 +  let check = function(aDir, aMsg) ok(cmd[aDir].callCount == expect[aDir], aMsg);
   1.290 +  let checkBoth = function(aNum, aInc, aDec) {
   1.291 +    let prefix = "Step " + aNum + ": ";
   1.292 +    check("inc", prefix + aInc);
   1.293 +    check("dec", prefix + aDec);
   1.294 +  };
   1.295 +
   1.296 +  // Send the "Start" event.
   1.297 +  test_utils.sendSimpleGestureEvent(eventPrefix + "Start", 0, 0, 0, initialDelta, 0);
   1.298 +  cumulativeDelta += initialDelta;
   1.299 +  if (isIncreasing) {
   1.300 +    expect.inc++;
   1.301 +    checkBoth(1, "Increasing command was not triggered", "Decreasing command was triggered");
   1.302 +  } else {
   1.303 +    expect.dec++;
   1.304 +    checkBoth(1, "Increasing command was triggered", "Decreasing command was not triggered");
   1.305 +  }
   1.306 +
   1.307 +  // Send random values in the same direction and ensure neither
   1.308 +  // command triggers.
   1.309 +  for (let i = 0; i < 5; i++) {
   1.310 +      let delta = Math.random() * (isIncreasing ? 100 : -100);
   1.311 +    test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, delta, 0);
   1.312 +    cumulativeDelta += delta;
   1.313 +    checkBoth(2, "Increasing command was triggered", "Decreasing command was triggered");
   1.314 +  }
   1.315 +
   1.316 +  // Now go back in the opposite direction.
   1.317 +  test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0,
   1.318 +				    - initialDelta, 0);
   1.319 +  cumulativeDelta += - initialDelta;
   1.320 +  if (isIncreasing) {
   1.321 +    expect.dec++;
   1.322 +    checkBoth(3, "Increasing command was triggered", "Decreasing command was not triggered");
   1.323 +  } else {
   1.324 +    expect.inc++;
   1.325 +    checkBoth(3, "Increasing command was not triggered", "Decreasing command was triggered");
   1.326 +  }
   1.327 +
   1.328 +  // Send random values in the opposite direction and ensure neither
   1.329 +  // command triggers.
   1.330 +  for (let i = 0; i < 5; i++) {
   1.331 +    let delta = Math.random() * (isIncreasing ? -100 : 100);
   1.332 +    test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, delta, 0);
   1.333 +    cumulativeDelta += delta;
   1.334 +    checkBoth(4, "Increasing command was triggered", "Decreasing command was triggered");
   1.335 +  }
   1.336 +
   1.337 +  // Go back to the original direction. The original command should trigger.
   1.338 +  test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0,
   1.339 +				    initialDelta, 0);
   1.340 +  cumulativeDelta += initialDelta;
   1.341 +  if (isIncreasing) {
   1.342 +    expect.inc++;
   1.343 +    checkBoth(5, "Increasing command was not triggered", "Decreasing command was triggered");
   1.344 +  } else {
   1.345 +    expect.dec++;
   1.346 +    checkBoth(5, "Increasing command was triggered", "Decreasing command was not triggered");
   1.347 +  }
   1.348 +
   1.349 +  // Send the wrap-up event. No commands should be triggered.
   1.350 +  test_utils.sendSimpleGestureEvent(eventPrefix, 0, 0, 0, cumulativeDelta, 0);
   1.351 +  checkBoth(6, "Increasing command was triggered", "Decreasing command was triggered");
   1.352 +}
   1.353 +
   1.354 +function test_addCommand(prefName, id)
   1.355 +{
   1.356 +  let cmd = test_commandset.appendChild(document.createElement("command"));
   1.357 +  cmd.setAttribute("id", id);
   1.358 +  cmd.setAttribute("oncommand", "this.callCount++;");
   1.359 +
   1.360 +  cmd.origPrefName = prefName;
   1.361 +  cmd.origPrefValue = gPrefService.getCharPref(prefName);
   1.362 +  gPrefService.setCharPref(prefName, id);
   1.363 +
   1.364 +  return cmd;
   1.365 +}
   1.366 +
   1.367 +function test_removeCommand(cmd)
   1.368 +{
   1.369 +  gPrefService.setCharPref(cmd.origPrefName, cmd.origPrefValue);
   1.370 +  test_commandset.removeChild(cmd);
   1.371 +}
   1.372 +
   1.373 +// Test whether latched events are only called once per direction of motion.
   1.374 +function test_latchedGesture(gesture, inc, dec, eventPrefix)
   1.375 +{
   1.376 +  let branch = test_prefBranch + gesture + ".";
   1.377 +
   1.378 +  // Put the gesture into latched mode.
   1.379 +  let oldLatchedValue = gPrefService.getBoolPref(branch + "latched");
   1.380 +  gPrefService.setBoolPref(branch + "latched", true);
   1.381 +
   1.382 +  // Install the test commands for increasing and decreasing motion.
   1.383 +  let cmd = {
   1.384 +    inc: test_addCommand(branch + inc, "test:incMotion"),
   1.385 +    dec: test_addCommand(branch + dec, "test:decMotion"),
   1.386 +  };
   1.387 +
   1.388 +  // Test the gestures in each direction.
   1.389 +  test_emitLatchedEvents(eventPrefix, 500, cmd);
   1.390 +  test_emitLatchedEvents(eventPrefix, -500, cmd);
   1.391 +
   1.392 +  // Restore the gesture to its original configuration.
   1.393 +  gPrefService.setBoolPref(branch + "latched", oldLatchedValue);
   1.394 +  for (let dir in cmd)
   1.395 +    test_removeCommand(cmd[dir]);
   1.396 +}
   1.397 +
   1.398 +// Test whether non-latched events are triggered upon sufficient motion.
   1.399 +function test_thresholdGesture(gesture, inc, dec, eventPrefix)
   1.400 +{
   1.401 +  let branch = test_prefBranch + gesture + ".";
   1.402 +
   1.403 +  // Disable latched mode for this gesture.
   1.404 +  let oldLatchedValue = gPrefService.getBoolPref(branch + "latched");
   1.405 +  gPrefService.setBoolPref(branch + "latched", false);
   1.406 +
   1.407 +  // Set the triggering threshold value to 50.
   1.408 +  let oldThresholdValue = gPrefService.getIntPref(branch + "threshold");
   1.409 +  gPrefService.setIntPref(branch + "threshold", 50);
   1.410 +
   1.411 +  // Install the test commands for increasing and decreasing motion.
   1.412 +  let cmdInc = test_addCommand(branch + inc, "test:incMotion");
   1.413 +  let cmdDec = test_addCommand(branch + dec, "test:decMotion");
   1.414 +
   1.415 +  // Send the start event but stop short of triggering threshold.
   1.416 +  cmdInc.callCount = cmdDec.callCount = 0;
   1.417 +  test_utils.sendSimpleGestureEvent(eventPrefix + "Start", 0, 0, 0, 49.5, 0);
   1.418 +  ok(cmdInc.callCount == 0, "Increasing command was triggered");
   1.419 +  ok(cmdDec.callCount == 0, "Decreasing command was triggered");
   1.420 +
   1.421 +  // Now trigger the threshold.
   1.422 +  cmdInc.callCount = cmdDec.callCount = 0;
   1.423 +  test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, 1, 0);
   1.424 +  ok(cmdInc.callCount == 1, "Increasing command was not triggered");
   1.425 +  ok(cmdDec.callCount == 0, "Decreasing command was triggered");
   1.426 +
   1.427 +  // The tracking counter should go to zero. Go back the other way and
   1.428 +  // stop short of triggering the threshold.
   1.429 +  cmdInc.callCount = cmdDec.callCount = 0;
   1.430 +  test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, -49.5, 0);
   1.431 +  ok(cmdInc.callCount == 0, "Increasing command was triggered");
   1.432 +  ok(cmdDec.callCount == 0, "Decreasing command was triggered");
   1.433 +
   1.434 +  // Now cross the threshold and trigger the decreasing command.
   1.435 +  cmdInc.callCount = cmdDec.callCount = 0;
   1.436 +  test_utils.sendSimpleGestureEvent(eventPrefix + "Update", 0, 0, 0, -1.5, 0);
   1.437 +  ok(cmdInc.callCount == 0, "Increasing command was triggered");
   1.438 +  ok(cmdDec.callCount == 1, "Decreasing command was not triggered");
   1.439 +
   1.440 +  // Send the wrap-up event. No commands should trigger.
   1.441 +  cmdInc.callCount = cmdDec.callCount = 0;
   1.442 +  test_utils.sendSimpleGestureEvent(eventPrefix, 0, 0, 0, -0.5, 0);
   1.443 +  ok(cmdInc.callCount == 0, "Increasing command was triggered");
   1.444 +  ok(cmdDec.callCount == 0, "Decreasing command was triggered");
   1.445 +
   1.446 +  // Restore the gesture to its original configuration.
   1.447 +  gPrefService.setBoolPref(branch + "latched", oldLatchedValue);
   1.448 +  gPrefService.setIntPref(branch + "threshold", oldThresholdValue);
   1.449 +  test_removeCommand(cmdInc);
   1.450 +  test_removeCommand(cmdDec);
   1.451 +}
   1.452 +
   1.453 +function test_swipeGestures()
   1.454 +{
   1.455 +  // easier to type names for the direction constants
   1.456 +  let up = SimpleGestureEvent.DIRECTION_UP;
   1.457 +  let down = SimpleGestureEvent.DIRECTION_DOWN;
   1.458 +  let left = SimpleGestureEvent.DIRECTION_LEFT;
   1.459 +  let right = SimpleGestureEvent.DIRECTION_RIGHT;
   1.460 +
   1.461 +  let branch = test_prefBranch + "swipe.";
   1.462 +
   1.463 +  // Install the test commands for the swipe gestures.
   1.464 +  let cmdUp = test_addCommand(branch + "up", "test:swipeUp");
   1.465 +  let cmdDown = test_addCommand(branch + "down", "test:swipeDown");
   1.466 +  let cmdLeft = test_addCommand(branch + "left", "test:swipeLeft");
   1.467 +  let cmdRight = test_addCommand(branch + "right", "test:swipeRight");
   1.468 +
   1.469 +  function resetCounts() {
   1.470 +    cmdUp.callCount = 0;
   1.471 +    cmdDown.callCount = 0;
   1.472 +    cmdLeft.callCount = 0;
   1.473 +    cmdRight.callCount = 0;
   1.474 +  }
   1.475 +
   1.476 +  // UP
   1.477 +  resetCounts();
   1.478 +  test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, up, 0, 0);
   1.479 +  ok(cmdUp.callCount == 1, "Step 1: Up command was not triggered");
   1.480 +  ok(cmdDown.callCount == 0, "Step 1: Down command was triggered");
   1.481 +  ok(cmdLeft.callCount == 0, "Step 1: Left command was triggered");
   1.482 +  ok(cmdRight.callCount == 0, "Step 1: Right command was triggered");
   1.483 +
   1.484 +  // DOWN
   1.485 +  resetCounts();
   1.486 +  test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, down, 0, 0);
   1.487 +  ok(cmdUp.callCount == 0, "Step 2: Up command was triggered");
   1.488 +  ok(cmdDown.callCount == 1, "Step 2: Down command was not triggered");
   1.489 +  ok(cmdLeft.callCount == 0, "Step 2: Left command was triggered");
   1.490 +  ok(cmdRight.callCount == 0, "Step 2: Right command was triggered");
   1.491 +
   1.492 +  // LEFT
   1.493 +  resetCounts();
   1.494 +  test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, left, 0, 0);
   1.495 +  ok(cmdUp.callCount == 0, "Step 3: Up command was triggered");
   1.496 +  ok(cmdDown.callCount == 0, "Step 3: Down command was triggered");
   1.497 +  ok(cmdLeft.callCount == 1, "Step 3: Left command was not triggered");
   1.498 +  ok(cmdRight.callCount == 0, "Step 3: Right command was triggered");
   1.499 +
   1.500 +  // RIGHT
   1.501 +  resetCounts();
   1.502 +  test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, right, 0, 0);
   1.503 +  ok(cmdUp.callCount == 0, "Step 4: Up command was triggered");
   1.504 +  ok(cmdDown.callCount == 0, "Step 4: Down command was triggered");
   1.505 +  ok(cmdLeft.callCount == 0, "Step 4: Left command was triggered");
   1.506 +  ok(cmdRight.callCount == 1, "Step 4: Right command was not triggered");
   1.507 +
   1.508 +  // Make sure combinations do not trigger events.
   1.509 +  let combos = [ up | left, up | right, down | left, down | right];
   1.510 +  for (let i = 0; i < combos.length; i++) {
   1.511 +    resetCounts();
   1.512 +    test_utils.sendSimpleGestureEvent("MozSwipeGesture", 0, 0, combos[i], 0, 0);
   1.513 +    ok(cmdUp.callCount == 0, "Step 5-"+i+": Up command was triggered");
   1.514 +    ok(cmdDown.callCount == 0, "Step 5-"+i+": Down command was triggered");
   1.515 +    ok(cmdLeft.callCount == 0, "Step 5-"+i+": Left command was triggered");
   1.516 +    ok(cmdRight.callCount == 0, "Step 5-"+i+": Right command was triggered");
   1.517 +  }
   1.518 +
   1.519 +  // Remove the test commands.
   1.520 +  test_removeCommand(cmdUp);
   1.521 +  test_removeCommand(cmdDown);
   1.522 +  test_removeCommand(cmdLeft);
   1.523 +  test_removeCommand(cmdRight);
   1.524 +}
   1.525 +
   1.526 +
   1.527 +function test_rotateHelperGetImageRotation(aImageElement)
   1.528 +{
   1.529 +  // Get the true image rotation from the transform matrix, bounded
   1.530 +  // to 0 <= result < 360
   1.531 +  let transformValue = content.window.getComputedStyle(aImageElement, null)
   1.532 +                                     .transform;
   1.533 +  if (transformValue == "none")
   1.534 +    return 0;
   1.535 +
   1.536 +  transformValue = transformValue.split("(")[1]
   1.537 +                                 .split(")")[0]
   1.538 +                                 .split(",");
   1.539 +  var rotation = Math.round(Math.atan2(transformValue[1], transformValue[0]) *
   1.540 +                            (180 / Math.PI));
   1.541 +  return (rotation < 0 ? rotation + 360 : rotation);
   1.542 +}
   1.543 +
   1.544 +function test_rotateHelperOneGesture(aImageElement, aCurrentRotation,
   1.545 +                                     aDirection, aAmount, aStop)
   1.546 +{
   1.547 +  if (aAmount <= 0 || aAmount > 90) // Bound to 0 < aAmount <= 90
   1.548 +    return;
   1.549 +
   1.550 +  // easier to type names for the direction constants
   1.551 +  let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE;
   1.552 +  let cclockwise = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE;
   1.553 +
   1.554 +  let delta = aAmount * (aDirection == clockwise ? 1 : -1);
   1.555 +
   1.556 +  // Kill transition time on image so test isn't wrong and doesn't take 10 seconds
   1.557 +  aImageElement.style.transitionDuration = "0s";
   1.558 +
   1.559 +  // Start the gesture, perform an update, and force flush
   1.560 +  test_utils.sendSimpleGestureEvent("MozRotateGestureStart", 0, 0, aDirection, .001, 0);
   1.561 +  test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, aDirection, delta, 0);
   1.562 +  aImageElement.clientTop;
   1.563 +
   1.564 +  // If stop, check intermediate
   1.565 +  if (aStop) {
   1.566 +    // Send near-zero-delta to stop, and force flush
   1.567 +    test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, aDirection, .001, 0);
   1.568 +    aImageElement.clientTop;
   1.569 +
   1.570 +    let stopExpectedRotation = (aCurrentRotation + delta) % 360;
   1.571 +    if (stopExpectedRotation < 0)
   1.572 +      stopExpectedRotation += 360;
   1.573 +
   1.574 +    is(stopExpectedRotation, test_rotateHelperGetImageRotation(aImageElement),
   1.575 +       "Image rotation at gesture stop/hold: expected=" + stopExpectedRotation +
   1.576 +       ", observed=" + test_rotateHelperGetImageRotation(aImageElement) +
   1.577 +       ", init=" + aCurrentRotation +
   1.578 +       ", amt=" + aAmount +
   1.579 +       ", dir=" + (aDirection == clockwise ? "cl" : "ccl"));
   1.580 +  }
   1.581 +  // End it and force flush
   1.582 +  test_utils.sendSimpleGestureEvent("MozRotateGesture", 0, 0, aDirection, 0, 0);
   1.583 +  aImageElement.clientTop;
   1.584 +
   1.585 +  let finalExpectedRotation;
   1.586 +
   1.587 +  if (aAmount < 45 && aStop) {
   1.588 +    // Rotate a bit, then stop.  Expect no change at end of gesture.
   1.589 +    finalExpectedRotation = aCurrentRotation;
   1.590 +  }
   1.591 +  else {
   1.592 +    // Either not stopping (expect 90 degree change in aDirection), OR
   1.593 +    // stopping but after 45, (expect 90 degree change in aDirection)
   1.594 +    finalExpectedRotation = (aCurrentRotation +
   1.595 +                             (aDirection == clockwise ? 1 : -1) * 90) % 360;
   1.596 +    if (finalExpectedRotation < 0)
   1.597 +      finalExpectedRotation += 360;
   1.598 +  }
   1.599 +
   1.600 +  is(finalExpectedRotation, test_rotateHelperGetImageRotation(aImageElement),
   1.601 +     "Image rotation gesture end: expected=" + finalExpectedRotation +
   1.602 +     ", observed=" + test_rotateHelperGetImageRotation(aImageElement) +
   1.603 +     ", init=" + aCurrentRotation +
   1.604 +     ", amt=" + aAmount +
   1.605 +     ", dir=" + (aDirection == clockwise ? "cl" : "ccl"));
   1.606 +}
   1.607 +
   1.608 +function test_rotateGesturesOnTab()
   1.609 +{
   1.610 +  gBrowser.selectedBrowser.removeEventListener("load", test_rotateGesturesOnTab, true);
   1.611 +
   1.612 +  if (!(content.document instanceof ImageDocument)) {
   1.613 +    ok(false, "Image document failed to open for rotation testing");
   1.614 +    gBrowser.removeTab(test_imageTab);
   1.615 +    finish();
   1.616 +    return;
   1.617 +  }
   1.618 +
   1.619 +  // easier to type names for the direction constants
   1.620 +  let cl = SimpleGestureEvent.ROTATION_CLOCKWISE;
   1.621 +  let ccl = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE;
   1.622 +
   1.623 +  let imgElem = content.document.body &&
   1.624 +                content.document.body.firstElementChild;
   1.625 +
   1.626 +  if (!imgElem) {
   1.627 +    ok(false, "Could not get image element on ImageDocument for rotation!");
   1.628 +    gBrowser.removeTab(test_imageTab);
   1.629 +    finish();
   1.630 +    return;
   1.631 +  }
   1.632 +
   1.633 +  // Quick function to normalize rotation to 0 <= r < 360
   1.634 +  var normRot = function(rotation) {
   1.635 +    rotation = rotation % 360;
   1.636 +    if (rotation < 0)
   1.637 +      rotation += 360;
   1.638 +    return rotation;
   1.639 +  }
   1.640 +
   1.641 +  for (var initRot = 0; initRot < 360; initRot += 90) {
   1.642 +    // Test each case: at each 90 degree snap; cl/ccl;
   1.643 +    // amount more or less than 45; stop and hold or don't (32 total tests)
   1.644 +    // The amount added to the initRot is where it is expected to be
   1.645 +    test_rotateHelperOneGesture(imgElem, normRot(initRot +   0), cl,  35, true );
   1.646 +    test_rotateHelperOneGesture(imgElem, normRot(initRot +   0), cl,  35, false);
   1.647 +    test_rotateHelperOneGesture(imgElem, normRot(initRot +  90), cl,  55, true );
   1.648 +    test_rotateHelperOneGesture(imgElem, normRot(initRot + 180), cl,  55, false);
   1.649 +    test_rotateHelperOneGesture(imgElem, normRot(initRot + 270), ccl, 35, true );
   1.650 +    test_rotateHelperOneGesture(imgElem, normRot(initRot + 270), ccl, 35, false);
   1.651 +    test_rotateHelperOneGesture(imgElem, normRot(initRot + 180), ccl, 55, true );
   1.652 +    test_rotateHelperOneGesture(imgElem, normRot(initRot +  90), ccl, 55, false);
   1.653 +
   1.654 +    // Manually rotate it 90 degrees clockwise to prepare for next iteration,
   1.655 +    // and force flush
   1.656 +    test_utils.sendSimpleGestureEvent("MozRotateGestureStart", 0, 0, cl, .001, 0);
   1.657 +    test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, cl, 90, 0);
   1.658 +    test_utils.sendSimpleGestureEvent("MozRotateGestureUpdate", 0, 0, cl, .001, 0);
   1.659 +    test_utils.sendSimpleGestureEvent("MozRotateGesture", 0, 0, cl, 0, 0);
   1.660 +    imgElem.clientTop;
   1.661 +  }
   1.662 +
   1.663 +  gBrowser.removeTab(test_imageTab);
   1.664 +  test_imageTab = null;
   1.665 +  finish();
   1.666 +}
   1.667 +
   1.668 +function test_rotateGestures()
   1.669 +{
   1.670 +  test_imageTab = gBrowser.addTab("chrome://branding/content/about-logo.png");
   1.671 +  gBrowser.selectedTab = test_imageTab;
   1.672 +
   1.673 +  gBrowser.selectedBrowser.addEventListener("load", test_rotateGesturesOnTab, true);
   1.674 +}

mercurial