mirror of
				https://github.com/mozilla/gecko-dev.git
				synced 2025-10-31 16:28:05 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			1150 lines
		
	
	
	
		
			29 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			1150 lines
		
	
	
	
		
			29 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| /* This Source Code Form is subject to the terms of the Mozilla Public
 | |
|  * License, v. 2.0. If a copy of the MPL was not distributed with this
 | |
|  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 | |
| 
 | |
| Services.scriptloader.loadSubScript(
 | |
|   "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_utils.js",
 | |
|   this
 | |
| );
 | |
| 
 | |
| Services.scriptloader.loadSubScript(
 | |
|   "chrome://mochitests/content/browser/gfx/layers/apz/test/mochitest/apz_test_native_event_utils.js",
 | |
|   this
 | |
| );
 | |
| 
 | |
| // Simple gestures tests
 | |
| //
 | |
| // Some of these tests require the ability to disable the fact that the
 | |
| // Firefox chrome intentionally prevents "simple gesture" events from
 | |
| // reaching web content.
 | |
| 
 | |
| var test_utils;
 | |
| var test_commandset;
 | |
| var test_prefBranch = "browser.gesture.";
 | |
| var test_normalTab;
 | |
| 
 | |
| async function test() {
 | |
|   waitForExplicitFinish();
 | |
| 
 | |
|   // Disable the default gestures support during this part of the test
 | |
|   gGestureSupport.init(false);
 | |
| 
 | |
|   test_utils = window.windowUtils;
 | |
| 
 | |
|   // Run the tests of "simple gesture" events generally
 | |
|   test_EnsureConstantsAreDisjoint();
 | |
|   test_TestEventListeners();
 | |
|   test_TestEventCreation();
 | |
| 
 | |
|   // Reenable the default gestures support. The remaining tests target
 | |
|   // the Firefox gesture functionality.
 | |
|   gGestureSupport.init(true);
 | |
| 
 | |
|   const aPage = "about:about";
 | |
|   test_normalTab = await BrowserTestUtils.openNewForegroundTab(
 | |
|     gBrowser,
 | |
|     aPage,
 | |
|     true /* waitForLoad */
 | |
|   );
 | |
| 
 | |
|   // Test Firefox's gestures support.
 | |
|   test_commandset = document.getElementById("mainCommandSet");
 | |
|   await test_swipeGestures();
 | |
|   await test_latchedGesture("pinch", "out", "in", "MozMagnifyGesture");
 | |
|   await test_thresholdGesture("pinch", "out", "in", "MozMagnifyGesture");
 | |
|   test_rotateGestures();
 | |
| }
 | |
| 
 | |
| var test_eventCount = 0;
 | |
| var test_expectedType;
 | |
| var test_expectedDirection;
 | |
| var test_expectedDelta;
 | |
| var test_expectedModifiers;
 | |
| var test_expectedClickCount;
 | |
| var test_imageTab;
 | |
| 
 | |
| function test_gestureListener(evt) {
 | |
|   is(
 | |
|     evt.type,
 | |
|     test_expectedType,
 | |
|     "evt.type (" + evt.type + ") does not match expected value"
 | |
|   );
 | |
|   is(
 | |
|     evt.target,
 | |
|     test_utils.elementFromPoint(60, 60, false, false),
 | |
|     "evt.target (" + evt.target + ") does not match expected value"
 | |
|   );
 | |
|   is(
 | |
|     evt.clientX,
 | |
|     60,
 | |
|     "evt.clientX (" + evt.clientX + ") does not match expected value"
 | |
|   );
 | |
|   is(
 | |
|     evt.clientY,
 | |
|     60,
 | |
|     "evt.clientY (" + evt.clientY + ") does not match expected value"
 | |
|   );
 | |
|   isnot(
 | |
|     evt.screenX,
 | |
|     0,
 | |
|     "evt.screenX (" + evt.screenX + ") does not match expected value"
 | |
|   );
 | |
|   isnot(
 | |
|     evt.screenY,
 | |
|     0,
 | |
|     "evt.screenY (" + evt.screenY + ") does not match expected value"
 | |
|   );
 | |
| 
 | |
|   is(
 | |
|     evt.direction,
 | |
|     test_expectedDirection,
 | |
|     "evt.direction (" + evt.direction + ") does not match expected value"
 | |
|   );
 | |
|   is(
 | |
|     evt.delta,
 | |
|     test_expectedDelta,
 | |
|     "evt.delta (" + evt.delta + ") does not match expected value"
 | |
|   );
 | |
| 
 | |
|   is(
 | |
|     evt.shiftKey,
 | |
|     (test_expectedModifiers & Event.SHIFT_MASK) != 0,
 | |
|     "evt.shiftKey did not match expected value"
 | |
|   );
 | |
|   is(
 | |
|     evt.ctrlKey,
 | |
|     (test_expectedModifiers & Event.CONTROL_MASK) != 0,
 | |
|     "evt.ctrlKey did not match expected value"
 | |
|   );
 | |
|   is(
 | |
|     evt.altKey,
 | |
|     (test_expectedModifiers & Event.ALT_MASK) != 0,
 | |
|     "evt.altKey did not match expected value"
 | |
|   );
 | |
|   is(
 | |
|     evt.metaKey,
 | |
|     (test_expectedModifiers & Event.META_MASK) != 0,
 | |
|     "evt.metaKey did not match expected value"
 | |
|   );
 | |
| 
 | |
|   if (evt.type == "MozTapGesture") {
 | |
|     is(
 | |
|       evt.clickCount,
 | |
|       test_expectedClickCount,
 | |
|       "evt.clickCount does not match"
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   test_eventCount++;
 | |
| }
 | |
| 
 | |
| function test_helper1(type, direction, delta, modifiers) {
 | |
|   // Setup the expected values
 | |
|   test_expectedType = type;
 | |
|   test_expectedDirection = direction;
 | |
|   test_expectedDelta = delta;
 | |
|   test_expectedModifiers = modifiers;
 | |
| 
 | |
|   let expectedEventCount = test_eventCount + 1;
 | |
| 
 | |
|   document.addEventListener(type, test_gestureListener, true);
 | |
|   test_utils.sendSimpleGestureEvent(type, 60, 60, direction, delta, modifiers);
 | |
|   document.removeEventListener(type, test_gestureListener, true);
 | |
| 
 | |
|   is(
 | |
|     expectedEventCount,
 | |
|     test_eventCount,
 | |
|     "Event (" + type + ") was never received by event listener"
 | |
|   );
 | |
| }
 | |
| 
 | |
| function test_clicks(type, clicks) {
 | |
|   // Setup the expected values
 | |
|   test_expectedType = type;
 | |
|   test_expectedDirection = 0;
 | |
|   test_expectedDelta = 0;
 | |
|   test_expectedModifiers = 0;
 | |
|   test_expectedClickCount = clicks;
 | |
| 
 | |
|   let expectedEventCount = test_eventCount + 1;
 | |
| 
 | |
|   document.addEventListener(type, test_gestureListener, true);
 | |
|   test_utils.sendSimpleGestureEvent(type, 60, 60, 0, 0, 0, clicks);
 | |
|   document.removeEventListener(type, test_gestureListener, true);
 | |
| 
 | |
|   is(
 | |
|     expectedEventCount,
 | |
|     test_eventCount,
 | |
|     "Event (" + type + ") was never received by event listener"
 | |
|   );
 | |
| }
 | |
| 
 | |
| function test_TestEventListeners() {
 | |
|   let e = test_helper1; // easier to type this name
 | |
| 
 | |
|   // Swipe gesture animation events
 | |
|   e("MozSwipeGestureStart", 0, -0.7, 0);
 | |
|   e("MozSwipeGestureUpdate", 0, -0.4, 0);
 | |
|   e("MozSwipeGestureEnd", 0, 0, 0);
 | |
|   e("MozSwipeGestureStart", 0, 0.6, 0);
 | |
|   e("MozSwipeGestureUpdate", 0, 0.3, 0);
 | |
|   e("MozSwipeGestureEnd", 0, 1, 0);
 | |
| 
 | |
|   // Swipe gesture event
 | |
|   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_LEFT, 0.0, 0);
 | |
|   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0.0, 0);
 | |
|   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_UP, 0.0, 0);
 | |
|   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_DOWN, 0.0, 0);
 | |
|   e(
 | |
|     "MozSwipeGesture",
 | |
|     SimpleGestureEvent.DIRECTION_UP | SimpleGestureEvent.DIRECTION_LEFT,
 | |
|     0.0,
 | |
|     0
 | |
|   );
 | |
|   e(
 | |
|     "MozSwipeGesture",
 | |
|     SimpleGestureEvent.DIRECTION_DOWN | SimpleGestureEvent.DIRECTION_RIGHT,
 | |
|     0.0,
 | |
|     0
 | |
|   );
 | |
|   e(
 | |
|     "MozSwipeGesture",
 | |
|     SimpleGestureEvent.DIRECTION_UP | SimpleGestureEvent.DIRECTION_RIGHT,
 | |
|     0.0,
 | |
|     0
 | |
|   );
 | |
|   e(
 | |
|     "MozSwipeGesture",
 | |
|     SimpleGestureEvent.DIRECTION_DOWN | SimpleGestureEvent.DIRECTION_LEFT,
 | |
|     0.0,
 | |
|     0
 | |
|   );
 | |
| 
 | |
|   // magnify gesture events
 | |
|   e("MozMagnifyGestureStart", 0, 50.0, 0);
 | |
|   e("MozMagnifyGestureUpdate", 0, -25.0, 0);
 | |
|   e("MozMagnifyGestureUpdate", 0, 5.0, 0);
 | |
|   e("MozMagnifyGesture", 0, 30.0, 0);
 | |
| 
 | |
|   // rotate gesture events
 | |
|   e("MozRotateGestureStart", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0);
 | |
|   e(
 | |
|     "MozRotateGestureUpdate",
 | |
|     SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE,
 | |
|     -13.0,
 | |
|     0
 | |
|   );
 | |
|   e("MozRotateGestureUpdate", SimpleGestureEvent.ROTATION_CLOCKWISE, 13.0, 0);
 | |
|   e("MozRotateGesture", SimpleGestureEvent.ROTATION_CLOCKWISE, 33.0, 0);
 | |
| 
 | |
|   // Tap and presstap gesture events
 | |
|   test_clicks("MozTapGesture", 1);
 | |
|   test_clicks("MozTapGesture", 2);
 | |
|   test_clicks("MozTapGesture", 3);
 | |
|   test_clicks("MozPressTapGesture", 1);
 | |
| 
 | |
|   // simple delivery test for edgeui gestures
 | |
|   e("MozEdgeUIStarted", 0, 0, 0);
 | |
|   e("MozEdgeUICanceled", 0, 0, 0);
 | |
|   e("MozEdgeUICompleted", 0, 0, 0);
 | |
| 
 | |
|   // event.shiftKey
 | |
|   let modifier = Event.SHIFT_MASK;
 | |
|   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
 | |
| 
 | |
|   // event.metaKey
 | |
|   modifier = Event.META_MASK;
 | |
|   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
 | |
| 
 | |
|   // event.altKey
 | |
|   modifier = Event.ALT_MASK;
 | |
|   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
 | |
| 
 | |
|   // event.ctrlKey
 | |
|   modifier = Event.CONTROL_MASK;
 | |
|   e("MozSwipeGesture", SimpleGestureEvent.DIRECTION_RIGHT, 0, modifier);
 | |
| }
 | |
| 
 | |
| function test_eventDispatchListener(evt) {
 | |
|   test_eventCount++;
 | |
|   evt.stopPropagation();
 | |
| }
 | |
| 
 | |
| function test_helper2(
 | |
|   type,
 | |
|   direction,
 | |
|   delta,
 | |
|   altKey,
 | |
|   ctrlKey,
 | |
|   shiftKey,
 | |
|   metaKey
 | |
| ) {
 | |
|   let event = null;
 | |
|   let successful;
 | |
| 
 | |
|   try {
 | |
|     event = document.createEvent("SimpleGestureEvent");
 | |
|     successful = true;
 | |
|   } catch (ex) {
 | |
|     successful = false;
 | |
|   }
 | |
|   ok(successful, "Unable to create SimpleGestureEvent");
 | |
| 
 | |
|   try {
 | |
|     event.initSimpleGestureEvent(
 | |
|       type,
 | |
|       true,
 | |
|       true,
 | |
|       window,
 | |
|       1,
 | |
|       10,
 | |
|       10,
 | |
|       10,
 | |
|       10,
 | |
|       ctrlKey,
 | |
|       altKey,
 | |
|       shiftKey,
 | |
|       metaKey,
 | |
|       1,
 | |
|       window,
 | |
|       0,
 | |
|       direction,
 | |
|       delta,
 | |
|       0
 | |
|     );
 | |
|     successful = true;
 | |
|   } catch (ex) {
 | |
|     successful = false;
 | |
|   }
 | |
|   ok(successful, "event.initSimpleGestureEvent should not fail");
 | |
| 
 | |
|   // Make sure the event fields match the expected values
 | |
|   is(event.type, type, "Mismatch on evt.type");
 | |
|   is(event.direction, direction, "Mismatch on evt.direction");
 | |
|   is(event.delta, delta, "Mismatch on evt.delta");
 | |
|   is(event.altKey, altKey, "Mismatch on evt.altKey");
 | |
|   is(event.ctrlKey, ctrlKey, "Mismatch on evt.ctrlKey");
 | |
|   is(event.shiftKey, shiftKey, "Mismatch on evt.shiftKey");
 | |
|   is(event.metaKey, metaKey, "Mismatch on evt.metaKey");
 | |
|   is(event.view, window, "Mismatch on evt.view");
 | |
|   is(event.detail, 1, "Mismatch on evt.detail");
 | |
|   is(event.clientX, 10, "Mismatch on evt.clientX");
 | |
|   is(event.clientY, 10, "Mismatch on evt.clientY");
 | |
|   is(event.screenX, 10, "Mismatch on evt.screenX");
 | |
|   is(event.screenY, 10, "Mismatch on evt.screenY");
 | |
|   is(event.button, 1, "Mismatch on evt.button");
 | |
|   is(event.relatedTarget, window, "Mismatch on evt.relatedTarget");
 | |
| 
 | |
|   // Test event dispatch
 | |
|   let expectedEventCount = test_eventCount + 1;
 | |
|   document.addEventListener(type, test_eventDispatchListener, true);
 | |
|   document.dispatchEvent(event);
 | |
|   document.removeEventListener(type, test_eventDispatchListener, true);
 | |
|   is(
 | |
|     expectedEventCount,
 | |
|     test_eventCount,
 | |
|     "Dispatched event was never received by listener"
 | |
|   );
 | |
| }
 | |
| 
 | |
| function test_TestEventCreation() {
 | |
|   // Event creation
 | |
|   test_helper2(
 | |
|     "MozMagnifyGesture",
 | |
|     SimpleGestureEvent.DIRECTION_RIGHT,
 | |
|     20.0,
 | |
|     true,
 | |
|     false,
 | |
|     true,
 | |
|     false
 | |
|   );
 | |
|   test_helper2(
 | |
|     "MozMagnifyGesture",
 | |
|     SimpleGestureEvent.DIRECTION_LEFT,
 | |
|     -20.0,
 | |
|     false,
 | |
|     true,
 | |
|     false,
 | |
|     true
 | |
|   );
 | |
| }
 | |
| 
 | |
| function test_EnsureConstantsAreDisjoint() {
 | |
|   let up = SimpleGestureEvent.DIRECTION_UP;
 | |
|   let down = SimpleGestureEvent.DIRECTION_DOWN;
 | |
|   let left = SimpleGestureEvent.DIRECTION_LEFT;
 | |
|   let right = SimpleGestureEvent.DIRECTION_RIGHT;
 | |
| 
 | |
|   let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE;
 | |
|   let cclockwise = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE;
 | |
| 
 | |
|   ok(up ^ down, "DIRECTION_UP and DIRECTION_DOWN are not bitwise disjoint");
 | |
|   ok(up ^ left, "DIRECTION_UP and DIRECTION_LEFT are not bitwise disjoint");
 | |
|   ok(up ^ right, "DIRECTION_UP and DIRECTION_RIGHT are not bitwise disjoint");
 | |
|   ok(down ^ left, "DIRECTION_DOWN and DIRECTION_LEFT are not bitwise disjoint");
 | |
|   ok(
 | |
|     down ^ right,
 | |
|     "DIRECTION_DOWN and DIRECTION_RIGHT are not bitwise disjoint"
 | |
|   );
 | |
|   ok(
 | |
|     left ^ right,
 | |
|     "DIRECTION_LEFT and DIRECTION_RIGHT are not bitwise disjoint"
 | |
|   );
 | |
|   ok(
 | |
|     clockwise ^ cclockwise,
 | |
|     "ROTATION_CLOCKWISE and ROTATION_COUNTERCLOCKWISE are not bitwise disjoint"
 | |
|   );
 | |
| }
 | |
| 
 | |
| // Helper for test of latched event processing. Emits the actual
 | |
| // gesture events to test whether the commands associated with the
 | |
| // gesture will only trigger once for each direction of movement.
 | |
| async function test_emitLatchedEvents(eventPrefix, initialDelta, cmd) {
 | |
|   let cumulativeDelta = 0;
 | |
|   let isIncreasing = initialDelta > 0;
 | |
| 
 | |
|   let expect = {};
 | |
|   // Reset the call counters and initialize expected values
 | |
|   for (let dir in cmd) {
 | |
|     cmd[dir].callCount = expect[dir] = 0;
 | |
|   }
 | |
| 
 | |
|   let check = (aDir, aMsg) =>
 | |
|     Assert.equal(cmd[aDir].callCount, expect[aDir], aMsg);
 | |
|   let checkBoth = function (aNum, aInc, aDec) {
 | |
|     let prefix = "Step " + aNum + ": ";
 | |
|     check("inc", prefix + aInc);
 | |
|     check("dec", prefix + aDec);
 | |
|   };
 | |
| 
 | |
|   // Send the "Start" event.
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix + "Start",
 | |
|     10,
 | |
|     10,
 | |
|     0,
 | |
|     initialDelta,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   cumulativeDelta += initialDelta;
 | |
|   if (isIncreasing) {
 | |
|     expect.inc++;
 | |
|     checkBoth(
 | |
|       1,
 | |
|       "Increasing command was not triggered",
 | |
|       "Decreasing command was triggered"
 | |
|     );
 | |
|   } else {
 | |
|     expect.dec++;
 | |
|     checkBoth(
 | |
|       1,
 | |
|       "Increasing command was triggered",
 | |
|       "Decreasing command was not triggered"
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // Send random values in the same direction and ensure neither
 | |
|   // command triggers.
 | |
|   for (let i = 0; i < 5; i++) {
 | |
|     let delta = Math.random() * (isIncreasing ? 100 : -100);
 | |
| 
 | |
|     await synthesizeSimpleGestureEvent(
 | |
|       test_normalTab.linkedBrowser,
 | |
|       eventPrefix + "Update",
 | |
|       10,
 | |
|       10,
 | |
|       0,
 | |
|       delta,
 | |
|       0,
 | |
|       0
 | |
|     );
 | |
|     cumulativeDelta += delta;
 | |
|     checkBoth(
 | |
|       2,
 | |
|       "Increasing command was triggered",
 | |
|       "Decreasing command was triggered"
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // Now go back in the opposite direction.
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix + "Update",
 | |
|     10,
 | |
|     10,
 | |
|     0,
 | |
|     -initialDelta,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   cumulativeDelta += -initialDelta;
 | |
|   if (isIncreasing) {
 | |
|     expect.dec++;
 | |
|     checkBoth(
 | |
|       3,
 | |
|       "Increasing command was triggered",
 | |
|       "Decreasing command was not triggered"
 | |
|     );
 | |
|   } else {
 | |
|     expect.inc++;
 | |
|     checkBoth(
 | |
|       3,
 | |
|       "Increasing command was not triggered",
 | |
|       "Decreasing command was triggered"
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // Send random values in the opposite direction and ensure neither
 | |
|   // command triggers.
 | |
|   for (let i = 0; i < 5; i++) {
 | |
|     let delta = Math.random() * (isIncreasing ? -100 : 100);
 | |
|     await synthesizeSimpleGestureEvent(
 | |
|       test_normalTab.linkedBrowser,
 | |
|       eventPrefix + "Update",
 | |
|       10,
 | |
|       10,
 | |
|       0,
 | |
|       delta,
 | |
|       0,
 | |
|       0
 | |
|     );
 | |
|     cumulativeDelta += delta;
 | |
|     checkBoth(
 | |
|       4,
 | |
|       "Increasing command was triggered",
 | |
|       "Decreasing command was triggered"
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // Go back to the original direction. The original command should trigger.
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix + "Update",
 | |
|     10,
 | |
|     10,
 | |
|     0,
 | |
|     initialDelta,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   cumulativeDelta += initialDelta;
 | |
|   if (isIncreasing) {
 | |
|     expect.inc++;
 | |
|     checkBoth(
 | |
|       5,
 | |
|       "Increasing command was not triggered",
 | |
|       "Decreasing command was triggered"
 | |
|     );
 | |
|   } else {
 | |
|     expect.dec++;
 | |
|     checkBoth(
 | |
|       5,
 | |
|       "Increasing command was triggered",
 | |
|       "Decreasing command was not triggered"
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // Send the wrap-up event. No commands should be triggered.
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix,
 | |
|     10,
 | |
|     10,
 | |
|     0,
 | |
|     cumulativeDelta,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   checkBoth(
 | |
|     6,
 | |
|     "Increasing command was triggered",
 | |
|     "Decreasing command was triggered"
 | |
|   );
 | |
| }
 | |
| 
 | |
| function test_addCommand(prefName, id) {
 | |
|   let cmd = test_commandset.appendChild(document.createXULElement("command"));
 | |
|   cmd.setAttribute("id", id);
 | |
|   cmd.setAttribute("oncommand", "this.callCount++;");
 | |
| 
 | |
|   cmd.origPrefName = prefName;
 | |
|   cmd.origPrefValue = Services.prefs.getCharPref(prefName);
 | |
|   Services.prefs.setCharPref(prefName, id);
 | |
| 
 | |
|   return cmd;
 | |
| }
 | |
| 
 | |
| function test_removeCommand(cmd) {
 | |
|   Services.prefs.setCharPref(cmd.origPrefName, cmd.origPrefValue);
 | |
|   test_commandset.removeChild(cmd);
 | |
| }
 | |
| 
 | |
| // Test whether latched events are only called once per direction of motion.
 | |
| async function test_latchedGesture(gesture, inc, dec, eventPrefix) {
 | |
|   let branch = test_prefBranch + gesture + ".";
 | |
| 
 | |
|   // Put the gesture into latched mode.
 | |
|   let oldLatchedValue = Services.prefs.getBoolPref(branch + "latched");
 | |
|   Services.prefs.setBoolPref(branch + "latched", true);
 | |
| 
 | |
|   // Install the test commands for increasing and decreasing motion.
 | |
|   let cmd = {
 | |
|     inc: test_addCommand(branch + inc, "test:incMotion"),
 | |
|     dec: test_addCommand(branch + dec, "test:decMotion"),
 | |
|   };
 | |
| 
 | |
|   // Test the gestures in each direction.
 | |
|   await test_emitLatchedEvents(eventPrefix, 500, cmd);
 | |
|   await test_emitLatchedEvents(eventPrefix, -500, cmd);
 | |
| 
 | |
|   // Restore the gesture to its original configuration.
 | |
|   Services.prefs.setBoolPref(branch + "latched", oldLatchedValue);
 | |
|   for (let dir in cmd) {
 | |
|     test_removeCommand(cmd[dir]);
 | |
|   }
 | |
| }
 | |
| 
 | |
| // Test whether non-latched events are triggered upon sufficient motion.
 | |
| async function test_thresholdGesture(gesture, inc, dec, eventPrefix) {
 | |
|   let branch = test_prefBranch + gesture + ".";
 | |
| 
 | |
|   // Disable latched mode for this gesture.
 | |
|   let oldLatchedValue = Services.prefs.getBoolPref(branch + "latched");
 | |
|   Services.prefs.setBoolPref(branch + "latched", false);
 | |
| 
 | |
|   // Set the triggering threshold value to 50.
 | |
|   let oldThresholdValue = Services.prefs.getIntPref(branch + "threshold");
 | |
|   Services.prefs.setIntPref(branch + "threshold", 50);
 | |
| 
 | |
|   // Install the test commands for increasing and decreasing motion.
 | |
|   let cmdInc = test_addCommand(branch + inc, "test:incMotion");
 | |
|   let cmdDec = test_addCommand(branch + dec, "test:decMotion");
 | |
| 
 | |
|   // Send the start event but stop short of triggering threshold.
 | |
|   cmdInc.callCount = cmdDec.callCount = 0;
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix + "Start",
 | |
|     10,
 | |
|     10,
 | |
|     0,
 | |
|     49.5,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdInc.callCount, 0, "Increasing command was triggered");
 | |
|   Assert.equal(cmdDec.callCount, 0, "Decreasing command was triggered");
 | |
| 
 | |
|   // Now trigger the threshold.
 | |
|   cmdInc.callCount = cmdDec.callCount = 0;
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix + "Update",
 | |
|     10,
 | |
|     10,
 | |
|     0,
 | |
|     1,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdInc.callCount, 1, "Increasing command was not triggered");
 | |
|   Assert.equal(cmdDec.callCount, 0, "Decreasing command was triggered");
 | |
| 
 | |
|   // The tracking counter should go to zero. Go back the other way and
 | |
|   // stop short of triggering the threshold.
 | |
|   cmdInc.callCount = cmdDec.callCount = 0;
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix + "Update",
 | |
|     10,
 | |
|     10,
 | |
|     0,
 | |
|     -49.5,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdInc.callCount, 0, "Increasing command was triggered");
 | |
|   Assert.equal(cmdDec.callCount, 0, "Decreasing command was triggered");
 | |
| 
 | |
|   // Now cross the threshold and trigger the decreasing command.
 | |
|   cmdInc.callCount = cmdDec.callCount = 0;
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix + "Update",
 | |
|     10,
 | |
|     10,
 | |
|     0,
 | |
|     -1.5,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdInc.callCount, 0, "Increasing command was triggered");
 | |
|   Assert.equal(cmdDec.callCount, 1, "Decreasing command was not triggered");
 | |
| 
 | |
|   // Send the wrap-up event. No commands should trigger.
 | |
|   cmdInc.callCount = cmdDec.callCount = 0;
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     eventPrefix,
 | |
|     0,
 | |
|     0,
 | |
|     0,
 | |
|     -0.5,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdInc.callCount, 0, "Increasing command was triggered");
 | |
|   Assert.equal(cmdDec.callCount, 0, "Decreasing command was triggered");
 | |
| 
 | |
|   // Restore the gesture to its original configuration.
 | |
|   Services.prefs.setBoolPref(branch + "latched", oldLatchedValue);
 | |
|   Services.prefs.setIntPref(branch + "threshold", oldThresholdValue);
 | |
|   test_removeCommand(cmdInc);
 | |
|   test_removeCommand(cmdDec);
 | |
| }
 | |
| 
 | |
| async function test_swipeGestures() {
 | |
|   // easier to type names for the direction constants
 | |
|   let up = SimpleGestureEvent.DIRECTION_UP;
 | |
|   let down = SimpleGestureEvent.DIRECTION_DOWN;
 | |
|   let left = SimpleGestureEvent.DIRECTION_LEFT;
 | |
|   let right = SimpleGestureEvent.DIRECTION_RIGHT;
 | |
| 
 | |
|   let branch = test_prefBranch + "swipe.";
 | |
| 
 | |
|   // Install the test commands for the swipe gestures.
 | |
|   let cmdUp = test_addCommand(branch + "up", "test:swipeUp");
 | |
|   let cmdDown = test_addCommand(branch + "down", "test:swipeDown");
 | |
|   let cmdLeft = test_addCommand(branch + "left", "test:swipeLeft");
 | |
|   let cmdRight = test_addCommand(branch + "right", "test:swipeRight");
 | |
| 
 | |
|   function resetCounts() {
 | |
|     cmdUp.callCount = 0;
 | |
|     cmdDown.callCount = 0;
 | |
|     cmdLeft.callCount = 0;
 | |
|     cmdRight.callCount = 0;
 | |
|   }
 | |
| 
 | |
|   // UP
 | |
|   resetCounts();
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     "MozSwipeGesture",
 | |
|     10,
 | |
|     10,
 | |
|     up,
 | |
|     0,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdUp.callCount, 1, "Step 1: Up command was not triggered");
 | |
|   Assert.equal(cmdDown.callCount, 0, "Step 1: Down command was triggered");
 | |
|   Assert.equal(cmdLeft.callCount, 0, "Step 1: Left command was triggered");
 | |
|   Assert.equal(cmdRight.callCount, 0, "Step 1: Right command was triggered");
 | |
| 
 | |
|   // DOWN
 | |
|   resetCounts();
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     "MozSwipeGesture",
 | |
|     10,
 | |
|     10,
 | |
|     down,
 | |
|     0,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdUp.callCount, 0, "Step 2: Up command was triggered");
 | |
|   Assert.equal(cmdDown.callCount, 1, "Step 2: Down command was not triggered");
 | |
|   Assert.equal(cmdLeft.callCount, 0, "Step 2: Left command was triggered");
 | |
|   Assert.equal(cmdRight.callCount, 0, "Step 2: Right command was triggered");
 | |
| 
 | |
|   // LEFT
 | |
|   resetCounts();
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     "MozSwipeGesture",
 | |
|     10,
 | |
|     10,
 | |
|     left,
 | |
|     0,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdUp.callCount, 0, "Step 3: Up command was triggered");
 | |
|   Assert.equal(cmdDown.callCount, 0, "Step 3: Down command was triggered");
 | |
|   Assert.equal(cmdLeft.callCount, 1, "Step 3: Left command was not triggered");
 | |
|   Assert.equal(cmdRight.callCount, 0, "Step 3: Right command was triggered");
 | |
| 
 | |
|   // RIGHT
 | |
|   resetCounts();
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_normalTab.linkedBrowser,
 | |
|     "MozSwipeGesture",
 | |
|     10,
 | |
|     10,
 | |
|     right,
 | |
|     0,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   Assert.equal(cmdUp.callCount, 0, "Step 4: Up command was triggered");
 | |
|   Assert.equal(cmdDown.callCount, 0, "Step 4: Down command was triggered");
 | |
|   Assert.equal(cmdLeft.callCount, 0, "Step 4: Left command was triggered");
 | |
|   Assert.equal(
 | |
|     cmdRight.callCount,
 | |
|     1,
 | |
|     "Step 4: Right command was not triggered"
 | |
|   );
 | |
| 
 | |
|   // Make sure combinations do not trigger events.
 | |
|   let combos = [up | left, up | right, down | left, down | right];
 | |
|   for (let i = 0; i < combos.length; i++) {
 | |
|     resetCounts();
 | |
|     await synthesizeSimpleGestureEvent(
 | |
|       test_normalTab.linkedBrowser,
 | |
|       "MozSwipeGesture",
 | |
|       10,
 | |
|       10,
 | |
|       combos[i],
 | |
|       0,
 | |
|       0,
 | |
|       0
 | |
|     );
 | |
|     Assert.equal(
 | |
|       cmdUp.callCount,
 | |
|       0,
 | |
|       "Step 5-" + i + ": Up command was triggered"
 | |
|     );
 | |
|     Assert.equal(
 | |
|       cmdDown.callCount,
 | |
|       0,
 | |
|       "Step 5-" + i + ": Down command was triggered"
 | |
|     );
 | |
|     Assert.equal(
 | |
|       cmdLeft.callCount,
 | |
|       0,
 | |
|       "Step 5-" + i + ": Left command was triggered"
 | |
|     );
 | |
|     Assert.equal(
 | |
|       cmdRight.callCount,
 | |
|       0,
 | |
|       "Step 5-" + i + ": Right command was triggered"
 | |
|     );
 | |
|   }
 | |
| 
 | |
|   // Remove the test commands.
 | |
|   test_removeCommand(cmdUp);
 | |
|   test_removeCommand(cmdDown);
 | |
|   test_removeCommand(cmdLeft);
 | |
|   test_removeCommand(cmdRight);
 | |
| }
 | |
| 
 | |
| function test_rotateHelperGetImageRotation(aImageElement) {
 | |
|   // Get the true image rotation from the transform matrix, bounded
 | |
|   // to 0 <= result < 360
 | |
|   let transformValue = content.window.getComputedStyle(aImageElement).transform;
 | |
|   if (transformValue == "none") {
 | |
|     return 0;
 | |
|   }
 | |
| 
 | |
|   transformValue = transformValue.split("(")[1].split(")")[0].split(",");
 | |
|   var rotation = Math.round(
 | |
|     Math.atan2(transformValue[1], transformValue[0]) * (180 / Math.PI)
 | |
|   );
 | |
|   return rotation < 0 ? rotation + 360 : rotation;
 | |
| }
 | |
| 
 | |
| async function test_rotateHelperOneGesture(
 | |
|   aImageElement,
 | |
|   aCurrentRotation,
 | |
|   aDirection,
 | |
|   aAmount,
 | |
|   aStop
 | |
| ) {
 | |
|   if (aAmount <= 0 || aAmount > 90) {
 | |
|     // Bound to 0 < aAmount <= 90
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // easier to type names for the direction constants
 | |
|   let clockwise = SimpleGestureEvent.ROTATION_CLOCKWISE;
 | |
| 
 | |
|   let delta = aAmount * (aDirection == clockwise ? 1 : -1);
 | |
| 
 | |
|   // Kill transition time on image so test isn't wrong and doesn't take 10 seconds
 | |
|   aImageElement.style.transitionDuration = "0s";
 | |
| 
 | |
|   // Start the gesture, perform an update, and force flush
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_imageTab.linkedBrowser,
 | |
|     "MozRotateGestureStart",
 | |
|     10,
 | |
|     10,
 | |
|     aDirection,
 | |
|     0.001,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_imageTab.linkedBrowser,
 | |
|     "MozRotateGestureUpdate",
 | |
|     10,
 | |
|     10,
 | |
|     aDirection,
 | |
|     delta,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   aImageElement.clientTop;
 | |
| 
 | |
|   // If stop, check intermediate
 | |
|   if (aStop) {
 | |
|     // Send near-zero-delta to stop, and force flush
 | |
|     await synthesizeSimpleGestureEvent(
 | |
|       test_imageTab.linkedBrowser,
 | |
|       "MozRotateGestureUpdate",
 | |
|       10,
 | |
|       10,
 | |
|       aDirection,
 | |
|       0.001,
 | |
|       0,
 | |
|       0
 | |
|     );
 | |
|     aImageElement.clientTop;
 | |
| 
 | |
|     let stopExpectedRotation = (aCurrentRotation + delta) % 360;
 | |
|     if (stopExpectedRotation < 0) {
 | |
|       stopExpectedRotation += 360;
 | |
|     }
 | |
| 
 | |
|     is(
 | |
|       stopExpectedRotation,
 | |
|       test_rotateHelperGetImageRotation(aImageElement),
 | |
|       "Image rotation at gesture stop/hold: expected=" +
 | |
|         stopExpectedRotation +
 | |
|         ", observed=" +
 | |
|         test_rotateHelperGetImageRotation(aImageElement) +
 | |
|         ", init=" +
 | |
|         aCurrentRotation +
 | |
|         ", amt=" +
 | |
|         aAmount +
 | |
|         ", dir=" +
 | |
|         (aDirection == clockwise ? "cl" : "ccl")
 | |
|     );
 | |
|   }
 | |
|   // End it and force flush
 | |
|   await synthesizeSimpleGestureEvent(
 | |
|     test_imageTab.linkedBrowser,
 | |
|     "MozRotateGesture",
 | |
|     10,
 | |
|     10,
 | |
|     aDirection,
 | |
|     0,
 | |
|     0,
 | |
|     0
 | |
|   );
 | |
|   aImageElement.clientTop;
 | |
| 
 | |
|   let finalExpectedRotation;
 | |
| 
 | |
|   if (aAmount < 45 && aStop) {
 | |
|     // Rotate a bit, then stop.  Expect no change at end of gesture.
 | |
|     finalExpectedRotation = aCurrentRotation;
 | |
|   } else {
 | |
|     // Either not stopping (expect 90 degree change in aDirection), OR
 | |
|     // stopping but after 45, (expect 90 degree change in aDirection)
 | |
|     finalExpectedRotation =
 | |
|       (aCurrentRotation + (aDirection == clockwise ? 1 : -1) * 90) % 360;
 | |
|     if (finalExpectedRotation < 0) {
 | |
|       finalExpectedRotation += 360;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   is(
 | |
|     finalExpectedRotation,
 | |
|     test_rotateHelperGetImageRotation(aImageElement),
 | |
|     "Image rotation gesture end: expected=" +
 | |
|       finalExpectedRotation +
 | |
|       ", observed=" +
 | |
|       test_rotateHelperGetImageRotation(aImageElement) +
 | |
|       ", init=" +
 | |
|       aCurrentRotation +
 | |
|       ", amt=" +
 | |
|       aAmount +
 | |
|       ", dir=" +
 | |
|       (aDirection == clockwise ? "cl" : "ccl")
 | |
|   );
 | |
| }
 | |
| 
 | |
| async function test_rotateGesturesOnTab() {
 | |
|   gBrowser.selectedBrowser.removeEventListener(
 | |
|     "load",
 | |
|     test_rotateGesturesOnTab,
 | |
|     true
 | |
|   );
 | |
| 
 | |
|   if (!ImageDocument.isInstance(content.document)) {
 | |
|     ok(false, "Image document failed to open for rotation testing");
 | |
|     gBrowser.removeTab(test_imageTab);
 | |
|     BrowserTestUtils.removeTab(test_normalTab);
 | |
|     test_imageTab = null;
 | |
|     test_normalTab = null;
 | |
|     finish();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // easier to type names for the direction constants
 | |
|   let cl = SimpleGestureEvent.ROTATION_CLOCKWISE;
 | |
|   let ccl = SimpleGestureEvent.ROTATION_COUNTERCLOCKWISE;
 | |
| 
 | |
|   let imgElem =
 | |
|     content.document.body && content.document.body.firstElementChild;
 | |
| 
 | |
|   if (!imgElem) {
 | |
|     ok(false, "Could not get image element on ImageDocument for rotation!");
 | |
|     gBrowser.removeTab(test_imageTab);
 | |
|     BrowserTestUtils.removeTab(test_normalTab);
 | |
|     test_imageTab = null;
 | |
|     test_normalTab = null;
 | |
|     finish();
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Quick function to normalize rotation to 0 <= r < 360
 | |
|   var normRot = function (rotation) {
 | |
|     rotation = rotation % 360;
 | |
|     if (rotation < 0) {
 | |
|       rotation += 360;
 | |
|     }
 | |
|     return rotation;
 | |
|   };
 | |
| 
 | |
|   for (var initRot = 0; initRot < 360; initRot += 90) {
 | |
|     // Test each case: at each 90 degree snap; cl/ccl;
 | |
|     // amount more or less than 45; stop and hold or don't (32 total tests)
 | |
|     // The amount added to the initRot is where it is expected to be
 | |
|     await test_rotateHelperOneGesture(
 | |
|       imgElem,
 | |
|       normRot(initRot + 0),
 | |
|       cl,
 | |
|       35,
 | |
|       true
 | |
|     );
 | |
|     await test_rotateHelperOneGesture(
 | |
|       imgElem,
 | |
|       normRot(initRot + 0),
 | |
|       cl,
 | |
|       35,
 | |
|       false
 | |
|     );
 | |
|     await test_rotateHelperOneGesture(
 | |
|       imgElem,
 | |
|       normRot(initRot + 90),
 | |
|       cl,
 | |
|       55,
 | |
|       true
 | |
|     );
 | |
|     await test_rotateHelperOneGesture(
 | |
|       imgElem,
 | |
|       normRot(initRot + 180),
 | |
|       cl,
 | |
|       55,
 | |
|       false
 | |
|     );
 | |
|     await test_rotateHelperOneGesture(
 | |
|       imgElem,
 | |
|       normRot(initRot + 270),
 | |
|       ccl,
 | |
|       35,
 | |
|       true
 | |
|     );
 | |
|     await test_rotateHelperOneGesture(
 | |
|       imgElem,
 | |
|       normRot(initRot + 270),
 | |
|       ccl,
 | |
|       35,
 | |
|       false
 | |
|     );
 | |
|     await test_rotateHelperOneGesture(
 | |
|       imgElem,
 | |
|       normRot(initRot + 180),
 | |
|       ccl,
 | |
|       55,
 | |
|       true
 | |
|     );
 | |
|     await test_rotateHelperOneGesture(
 | |
|       imgElem,
 | |
|       normRot(initRot + 90),
 | |
|       ccl,
 | |
|       55,
 | |
|       false
 | |
|     );
 | |
| 
 | |
|     // Manually rotate it 90 degrees clockwise to prepare for next iteration,
 | |
|     // and force flush
 | |
|     await synthesizeSimpleGestureEvent(
 | |
|       test_imageTab.linkedBrowser,
 | |
|       "MozRotateGestureStart",
 | |
|       10,
 | |
|       10,
 | |
|       cl,
 | |
|       0.001,
 | |
|       0,
 | |
|       0
 | |
|     );
 | |
|     await synthesizeSimpleGestureEvent(
 | |
|       test_imageTab.linkedBrowser,
 | |
|       "MozRotateGestureUpdate",
 | |
|       10,
 | |
|       10,
 | |
|       cl,
 | |
|       90,
 | |
|       0,
 | |
|       0
 | |
|     );
 | |
|     await synthesizeSimpleGestureEvent(
 | |
|       test_imageTab.linkedBrowser,
 | |
|       "MozRotateGestureUpdate",
 | |
|       10,
 | |
|       10,
 | |
|       cl,
 | |
|       0.001,
 | |
|       0,
 | |
|       0
 | |
|     );
 | |
|     await synthesizeSimpleGestureEvent(
 | |
|       test_imageTab.linkedBrowser,
 | |
|       "MozRotateGesture",
 | |
|       10,
 | |
|       10,
 | |
|       cl,
 | |
|       0,
 | |
|       0,
 | |
|       0
 | |
|     );
 | |
|     imgElem.clientTop;
 | |
|   }
 | |
| 
 | |
|   gBrowser.removeTab(test_imageTab);
 | |
|   BrowserTestUtils.removeTab(test_normalTab);
 | |
|   test_imageTab = null;
 | |
|   test_normalTab = null;
 | |
|   finish();
 | |
| }
 | |
| 
 | |
| function test_rotateGestures() {
 | |
|   test_imageTab = BrowserTestUtils.addTab(
 | |
|     gBrowser,
 | |
|     "chrome://branding/content/about-logo.png"
 | |
|   );
 | |
|   gBrowser.selectedTab = test_imageTab;
 | |
| 
 | |
|   gBrowser.selectedBrowser.addEventListener(
 | |
|     "load",
 | |
|     test_rotateGesturesOnTab,
 | |
|     true
 | |
|   );
 | |
| }
 | 
