--- a/accessible/jsat/Gestures.jsm
+++ b/accessible/jsat/Gestures.jsm
@@ -8,20 +8,18 @@
/******************************************************************************
All gestures have the following pathways when being resolved(v)/rejected(x):
Tap -> DoubleTap (x)
-> Dwell (x)
-> Swipe (x)
DoubleTap -> TripleTap (x)
-> TapHold (x)
- -> Explore (x)
TripleTap -> DoubleTapHold (x)
- -> Explore (x)
Dwell -> DwellEnd (v)
Swipe -> Explore (x)
TapHold -> TapHoldEnd (v)
DoubleTapHold -> DoubleTapHoldEnd (v)
@@ -34,33 +32,30 @@
ExploreEnd -> Explore (x)
Explore -> ExploreEnd (v)
******************************************************************************/
'use strict';
-const Ci = Components.interfaces;
const Cu = Components.utils;
-this.EXPORTED_SYMBOLS = ['GestureSettings', 'GestureTracker']; // jshint ignore:line
+this.EXPORTED_SYMBOLS = ['GestureSettings', 'GestureTracker'];
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Utils', // jshint ignore:line
+XPCOMUtils.defineLazyModuleGetter(this, 'Utils',
'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Logger', // jshint ignore:line
+XPCOMUtils.defineLazyModuleGetter(this, 'Logger',
'resource://gre/modules/accessibility/Utils.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout', // jshint ignore:line
+XPCOMUtils.defineLazyModuleGetter(this, 'setTimeout',
'resource://gre/modules/Timer.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'clearTimeout', // jshint ignore:line
+XPCOMUtils.defineLazyModuleGetter(this, 'clearTimeout',
'resource://gre/modules/Timer.jsm');
-XPCOMUtils.defineLazyModuleGetter(this, 'Promise', // jshint ignore:line
- 'resource://gre/modules/Promise.jsm');
// Default maximum duration of swipe
const SWIPE_MAX_DURATION = 200;
// Default maximum amount of time allowed for a gesture to be considered a
// multitouch
const MAX_MULTITOUCH = 125;
// Default maximum consecutive pointer event timeout
const MAX_CONSECUTIVE_GESTURE_DELAY = 200;
@@ -68,84 +63,81 @@ const MAX_CONSECUTIVE_GESTURE_DELAY = 20
const DWELL_THRESHOLD = 250;
// Minimal swipe distance in inches
const SWIPE_MIN_DISTANCE = 0.4;
// Maximum distance the pointer could move during a tap in inches
const TAP_MAX_RADIUS = 0.2;
// Directness coefficient. It is based on the maximum 15 degree angle between
// consequent pointer move lines.
const DIRECTNESS_COEFF = 1.44;
-// The virtual touch ID generated by a mouse event.
-const MOUSE_ID = 'mouse';
// Amount in inches from the edges of the screen for it to be an edge swipe
const EDGE = 0.1;
// Multiply timeouts by this constant, x2 works great too for slower users.
const TIMEOUT_MULTIPLIER = 1;
// A single pointer down/up sequence periodically precedes the tripple swipe
// gesture on Android. This delay acounts for that.
const IS_ANDROID = Utils.MozBuildApp === 'mobile/android' &&
Utils.AndroidSdkVersion >= 14;
/**
- * A point object containing distance travelled data.
+ * A point class containing distance travelled data.
* @param {Object} aPoint A point object that looks like: {
* x: x coordinate in pixels,
* y: y coordinate in pixels
* }
*/
-function Point(aPoint) {
- this.startX = this.x = aPoint.x;
- this.startY = this.y = aPoint.y;
- this.distanceTraveled = 0;
- this.totalDistanceTraveled = 0;
-}
-
-Point.prototype = {
+class Point {
+ constructor(aPoint) {
+ this.startX = this.x = aPoint.x;
+ this.startY = this.y = aPoint.y;
+ this.distanceTraveled = 0;
+ this.totalDistanceTraveled = 0;
+ }
/**
* Update the current point coordiates.
* @param {Object} aPoint A new point coordinates.
*/
- update: function Point_update(aPoint) {
+ update(aPoint) {
let lastX = this.x;
let lastY = this.y;
this.x = aPoint.x;
this.y = aPoint.y;
this.distanceTraveled = this.getDistanceToCoord(lastX, lastY);
this.totalDistanceTraveled += this.distanceTraveled;
- },
+ }
- reset: function Point_reset() {
+ reset() {
this.distanceTraveled = 0;
this.totalDistanceTraveled = 0;
- },
+ }
/**
* Get distance between the current point coordinates and the given ones.
* @param {Number} aX A pixel value for the x coordinate.
* @param {Number} aY A pixel value for the y coordinate.
* @return {Number} A distance between point's current and the given
* coordinates.
*/
- getDistanceToCoord: function Point_getDistanceToCoord(aX, aY) {
+ getDistanceToCoord(aX, aY) {
return Math.hypot(this.x - aX, this.y - aY);
- },
+ }
/**
* Get the direct distance travelled by the point so far.
*/
get directDistanceTraveled() {
return this.getDistanceToCoord(this.startX, this.startY);
}
-};
+}
/**
* An externally accessible collection of settings used in gesture resolition.
* @type {Object}
*/
-this.GestureSettings = { // jshint ignore:line
+this.GestureSettings = {
/**
* Maximum duration of swipe
* @type {Number}
*/
swipeMaxDuration: SWIPE_MAX_DURATION * TIMEOUT_MULTIPLIER,
/**
* Maximum amount of time allowed for a gesture to be considered a multitouch.
@@ -182,17 +174,17 @@ this.GestureSettings = { // jshint ignor
travelThreshold: 0.025
};
/**
* An interface that handles the pointer events and calculates the appropriate
* gestures.
* @type {Object}
*/
-this.GestureTracker = { // jshint ignore:line
+this.GestureTracker = {
/**
* Reset GestureTracker to its initial state.
* @return {[type]} [description]
*/
reset: function GestureTracker_reset() {
if (this.current) {
this.current.clearTimer();
}
@@ -206,45 +198,43 @@ this.GestureTracker = { // jshint ignore
* @param {Number} aTimeStamp A new pointer event timeStamp.
* @param {Function} aGesture A gesture constructor (default: Tap).
*/
_init: function GestureTracker__init(aDetail, aTimeStamp, aGesture) {
// Only create a new gesture on |pointerdown| event.
if (aDetail.type !== 'pointerdown') {
return;
}
- let points = aDetail.points;
let GestureConstructor = aGesture || (IS_ANDROID ? DoubleTap : Tap);
this._create(GestureConstructor);
this._update(aDetail, aTimeStamp);
},
/**
* Handle the incoming pointer event with the existing gesture object(if
* present) or with the newly created one.
* @param {Object} aDetail A new pointer event detail.
* @param {Number} aTimeStamp A new pointer event timeStamp.
*/
handle: function GestureTracker_handle(aDetail, aTimeStamp) {
- Logger.gesture(() => {
- return ['Pointer event', Utils.dpi, 'at:', aTimeStamp, JSON.stringify(aDetail)];
- });
+ Logger.gesture(() =>
+ ['Pointer event', Utils.dpi, 'at:', aTimeStamp, JSON.stringify(aDetail)]);
this[this.current ? '_update' : '_init'](aDetail, aTimeStamp);
},
/**
* Create a new gesture object and attach resolution handler to it.
* @param {Function} aGesture A gesture constructor.
* @param {Number} aTimeStamp An original pointer event timeStamp.
* @param {Array} aPoints All changed points associated with the new pointer
* event.
* @param {?String} aLastEvent Last pointer event type.
*/
_create: function GestureTracker__create(aGesture, aTimeStamp, aPoints, aLastEvent) {
- this.current = new aGesture(aTimeStamp, aPoints, aLastEvent); /* A constructor name should start with an uppercase letter. */ // jshint ignore:line
+ this.current = new aGesture(aTimeStamp, aPoints, aLastEvent); /* A constructor name should start with an uppercase letter. */
this.current.then(this._onFulfill.bind(this));
},
/**
* Handle the incoming pointer event with the existing gesture object.
* @param {Object} aDetail A new pointer event detail.
* @param {Number} aTimeStamp A new pointer event timeStamp.
*/
@@ -265,16 +255,17 @@ this.GestureTracker = { // jshint ignore
if (!current || current.id !== id) {
return;
}
// Only create a gesture if we got a constructor.
if (gestureType) {
this._create(gestureType, current.startTime, current.points,
current.lastEvent);
} else {
+ this.current.clearTimer();
delete this.current;
}
}
};
/**
* Compile a mozAccessFuGesture detail structure.
* @param {String} aType A gesture type.
@@ -313,645 +304,615 @@ function compileDetail(aType, aPoints, k
type: aType,
touches: touches,
deltaX: maxDeltaX,
deltaY: maxDeltaY
};
}
/**
- * A general gesture object.
+ * A general gesture class.
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* Default is an empty object.
* @param {?String} aLastEvent Last pointer event type.
*/
-function Gesture(aTimeStamp, aPoints = {}, aLastEvent = undefined) {
- this.startTime = Date.now();
- Logger.gesture('Creating', this.id, 'gesture.');
- this.points = aPoints;
- this.lastEvent = aLastEvent;
- this._deferred = Promise.defer();
- // Call this._handleResolve or this._handleReject when the promise is
- // fulfilled with either resolve or reject.
- this.promise = this._deferred.promise.then(this._handleResolve.bind(this),
- this._handleReject.bind(this));
- this.startTimer(aTimeStamp);
-}
-
-Gesture.prototype = {
+class Gesture {
+ constructor(aTimeStamp, aPoints = {}, aLastEvent = undefined) {
+ this.startTime = Date.now();
+ Logger.gesture('Creating', this.id, 'gesture.');
+ this.points = aPoints;
+ this.lastEvent = aLastEvent;
+ let promise = new Promise((resolve, reject) => {
+ this.resolve = resolve;
+ this.reject = reject;
+ });
+ // Call this._handleResolve or this._handleReject when the promise is
+ // fulfilled with either resolve or reject.
+ this.promise = promise.then(this._handleResolve.bind(this),
+ this._handleReject.bind(this));
+ this.startTimer(aTimeStamp);
+ }
/**
* Get the gesture timeout delay.
* @return {Number}
*/
- _getDelay: function Gesture__getDelay() {
+ _getDelay() {
// If nothing happens withing the
// GestureSettings.maxConsecutiveGestureDelay, we should not wait for any
// more pointer events and consider them the part of the same gesture -
// reject this gesture promise.
return GestureSettings.maxConsecutiveGestureDelay;
- },
+ }
+ get _inProgress() {
+ return this.__inProgress;
+ }
+ set _inProgress(aVal) {
+ this.__inProgress = aVal;
+ }
/**
* Clear the existing timer.
*/
- clearTimer: function Gesture_clearTimer() {
+ clearTimer() {
Logger.gesture('clearTimeout', this.type);
clearTimeout(this._timer);
delete this._timer;
- },
-
+ }
/**
* Start the timer for gesture timeout.
* @param {Number} aTimeStamp An original pointer event's timeStamp that
* started the gesture resolution sequence.
*/
- startTimer: function Gesture_startTimer(aTimeStamp) {
+ startTimer(aTimeStamp) {
Logger.gesture('startTimer', this.type);
this.clearTimer();
let delay = this._getDelay(aTimeStamp);
let handler = () => {
Logger.gesture('timer handler');
this.clearTimer();
if (!this._inProgress) {
- this._deferred.reject();
+ this.reject();
} else if (this._rejectToOnWait) {
- this._deferred.reject(this._rejectToOnWait);
+ this.reject(this._rejectToOnWait);
}
};
if (delay <= 0) {
handler();
} else {
this._timer = setTimeout(handler, delay);
}
- },
-
+ }
/**
* Add a gesture promise resolution callback.
* @param {Function} aCallback
*/
- then: function Gesture_then(aCallback) {
+ then(aCallback) {
this.promise.then(aCallback);
- },
-
+ }
/**
* Update gesture's points. Test the points set with the optional gesture test
* function.
* @param {Array} aPoints An array with the changed points from the new
* pointer event.
* @param {String} aType Pointer event type.
* @param {Boolean} aCanCreate A flag that enables including the new points.
* Default is false.
* @param {Boolean} aNeedComplete A flag that indicates that the gesture is
* completing. Default is false.
* @return {Boolean} Indicates whether the gesture can be complete (it is
* set to true iff the aNeedComplete is true and there was a change to at
* least one point that belongs to the gesture).
*/
- _update: function Gesture__update(aPoints, aType, aCanCreate = false, aNeedComplete = false) {
- let complete;
+ _update(aPoints, aType, aCanCreate = false, aNeedComplete = false) {
let lastEvent;
for (let point of aPoints) {
let identifier = point.identifier;
let gesturePoint = this.points[identifier];
if (gesturePoint) {
if (aType === 'pointerdown' && aCanCreate) {
// scratch the previous pointer with that id.
this.points[identifier] = new Point(point);
} else {
gesturePoint.update(point);
}
- if (aNeedComplete) {
- // Since the gesture is completing and at least one of the gesture
- // points is updated, set the return value to true.
- complete = true;
- }
lastEvent = lastEvent || aType;
} else if (aCanCreate) {
// Only create a new point if aCanCreate is true.
- this.points[identifier] =
- new Point(point);
+ this.points[identifier] = new Point(point);
lastEvent = lastEvent || aType;
}
}
this.lastEvent = lastEvent || this.lastEvent;
// If test function is defined test the points.
if (this.test) {
- this.test(complete);
+ this.test(aNeedComplete);
}
- return complete;
- },
-
+ }
/**
* Emit a mozAccessFuGesture (when the gesture is resolved).
* @param {Object} aDetail a compiled mozAccessFuGesture detail structure.
*/
- _emit: function Gesture__emit(aDetail) {
+ _emit(aDetail) {
let evt = new Utils.win.CustomEvent('mozAccessFuGesture', {
bubbles: true,
cancelable: true,
detail: aDetail
});
Utils.win.dispatchEvent(evt);
- },
-
+ }
/**
* Handle the pointer down event.
* @param {Array} aPoints A new pointer down points.
* @param {Number} aTimeStamp A new pointer down timeStamp.
*/
- pointerdown: function Gesture_pointerdown(aPoints, aTimeStamp) {
+ pointerdown(aPoints, aTimeStamp) {
this._inProgress = true;
this._update(aPoints, 'pointerdown',
aTimeStamp - this.startTime < GestureSettings.maxMultitouch);
- },
-
+ }
/**
* Handle the pointer move event.
* @param {Array} aPoints A new pointer move points.
*/
- pointermove: function Gesture_pointermove(aPoints) {
+ pointermove(aPoints) {
this._update(aPoints, 'pointermove');
- },
-
+ }
/**
* Handle the pointer up event.
* @param {Array} aPoints A new pointer up points.
*/
- pointerup: function Gesture_pointerup(aPoints) {
- let complete = this._update(aPoints, 'pointerup', false, true);
- if (complete) {
- this._deferred.resolve();
- }
- },
-
+ pointerup(aPoints) {
+ this._update(aPoints, 'pointerup', false, true);
+ this.resolve();
+ }
/**
* A subsequent gesture constructor to resolve the current one to. E.g.
* tap->doubletap, dwell->dwellend, etc.
* @type {Function}
*/
- resolveTo: null,
-
+ get resolveTo() {
+ return null;
+ }
/**
* A unique id for the gesture. Composed of the type + timeStamp.
*/
get id() {
delete this._id;
this._id = this.type + this.startTime;
return this._id;
- },
-
+ }
/**
* A gesture promise resolve callback. Compile and emit the gesture.
* @return {Object} Returns a structure to the gesture handler that looks like
* this: {
* id: current gesture id,
* gestureType: an optional subsequent gesture constructor.
* }
*/
- _handleResolve: function Gesture__handleResolve() {
+ _handleResolve() {
if (this.isComplete) {
return;
}
Logger.gesture('Resolving', this.id, 'gesture.');
this.isComplete = true;
this.clearTimer();
let detail = this.compile();
if (detail) {
this._emit(detail);
}
return {
id: this.id,
gestureType: this.resolveTo
};
- },
-
+ }
/**
* A gesture promise reject callback.
* @return {Object} Returns a structure to the gesture handler that looks like
* this: {
* id: current gesture id,
* gestureType: an optional subsequent gesture constructor.
* }
*/
- _handleReject: function Gesture__handleReject(aRejectTo) {
+ _handleReject(aRejectTo) {
if (this.isComplete) {
return;
}
Logger.gesture('Rejecting', this.id, 'gesture.');
this.isComplete = true;
this.clearTimer();
return {
id: this.id,
gestureType: aRejectTo
};
- },
-
+ }
/**
* A default compilation function used to build the mozAccessFuGesture event
* detail. The detail always includes the type and the touches associated
* with the gesture.
* @return {Object} Gesture event detail.
*/
- compile: function Gesture_compile() {
+ compile() {
return compileDetail(this.type, this.points);
}
-};
+}
/**
* A mixin for an explore related object.
*/
-function ExploreGesture() {
- this.compile = () => {
+let ExploreGesture = Base => class extends Base {
+ compile() {
// Unlike most of other gestures explore based gestures compile using the
// current point position and not the start one.
return compileDetail(this.type, this.points, {x: 'x', y: 'y'});
- };
-}
+ }
+};
/**
* Check the in progress gesture for completion.
*/
function checkProgressGesture(aGesture) {
- aGesture._inProgress = true;
if (aGesture.lastEvent === 'pointerup') {
if (aGesture.test) {
aGesture.test(true);
}
- aGesture._deferred.resolve();
+ aGesture.resolve();
}
}
/**
+ * Common base object for gestures that are created as resolved.
+ * @param {Number} aTimeStamp An original pointer event's timeStamp that started
+ * the gesture resolution sequence.
+ * @param {Object} aPoints An existing set of points (from previous events).
+ * @param {?String} aLastEvent Last pointer event type.
+ */
+class ResolvedGesture extends Gesture {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ super(aTimeStamp, aPoints, aLastEvent);
+ // Resolve the guesture right away.
+ this.resolve();
+ }
+}
+
+/**
+ * Explore gesture
+ * @param {Number} aTimeStamp An original pointer event's timeStamp that started
+ * the gesture resolution sequence.
+ * @param {Object} aPoints An existing set of points (from previous events).
+ * @param {?String} aLastEvent Last pointer event type.
+ */
+class Explore extends ExploreGesture(ResolvedGesture) {
+ get type() { return 'explore'; }
+ get resolveTo() { return ExploreEnd; }
+}
+
+/**
* A common travel gesture. When the travel gesture is created, all subsequent
* pointer events' points are tested for their total distance traveled. If that
* distance exceeds the _threshold distance, the gesture will be rejected to a
* _travelTo gesture.
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
* @param {Function} aTravelTo A contructor for the gesture to reject to when
* travelling (default: Explore).
* @param {Number} aThreshold Travel threshold (default:
* GestureSettings.travelThreshold).
*/
-function TravelGesture(aTimeStamp, aPoints, aLastEvent, aTravelTo = Explore, aThreshold = GestureSettings.travelThreshold) {
- Gesture.call(this, aTimeStamp, aPoints, aLastEvent);
- this._travelTo = aTravelTo;
- this._threshold = aThreshold;
+class TravelGesture extends Gesture {
+ constructor(aTimeStamp, aPoints, aLastEvent, aTravelTo = Explore, aThreshold = GestureSettings.travelThreshold) {
+ super(aTimeStamp, aPoints, aLastEvent);
+ this._travelTo = aTravelTo;
+ this._threshold = aThreshold;
+ }
+ /**
+ * Test the gesture points for travel. The gesture will be rejected to
+ * this._travelTo gesture iff at least one point crosses this._threshold.
+ */
+ test() {
+ if (!this._travelTo) {
+ return;
+ }
+ for (let identifier in this.points) {
+ let point = this.points[identifier];
+ if (point.totalDistanceTraveled / Utils.dpi > this._threshold) {
+ this.reject(this._travelTo);
+ return;
+ }
+ }
+ }
}
-TravelGesture.prototype = Object.create(Gesture.prototype);
-
/**
- * Test the gesture points for travel. The gesture will be rejected to
- * this._travelTo gesture iff at least one point crosses this._threshold.
+ * ExploreEnd gesture.
+ * @param {Number} aTimeStamp An original pointer event's timeStamp that started
+ * the gesture resolution sequence.
+ * @param {Object} aPoints An existing set of points (from previous events).
+ * @param {?String} aLastEvent Last pointer event type.
*/
-TravelGesture.prototype.test = function TravelGesture_test() {
- for (let identifier in this.points) {
- let point = this.points[identifier];
- if (point.totalDistanceTraveled / Utils.dpi > this._threshold) {
- this._deferred.reject(this._travelTo);
- return;
- }
+class ExploreEnd extends ExploreGesture(TravelGesture) {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ super(aTimeStamp, aPoints, aLastEvent);
+ checkProgressGesture(this);
}
-};
+ get type() { return 'exploreend'; }
+ get _inProgress() { return true; }
+ set _inProgress(aVal) { return; }
+}
/**
* DwellEnd gesture.
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
*/
-function DwellEnd(aTimeStamp, aPoints, aLastEvent) {
- this._inProgress = true;
- // If the pointer travels, reject to Explore.
- TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent);
- checkProgressGesture(this);
+class DwellEnd extends TravelGesture {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ // If the pointer travels, reject to Explore.
+ super(aTimeStamp, aPoints, aLastEvent);
+ checkProgressGesture(this);
+ }
+ get _inProgress() { return true; }
+ set _inProgress(aVal) { return; }
+ get type() { return 'dwellend'; }
}
-DwellEnd.prototype = Object.create(TravelGesture.prototype);
-DwellEnd.prototype.type = 'dwellend';
-
/**
* TapHoldEnd gesture. This gesture can be represented as the following diagram:
* pointerdown-pointerup-pointerdown-*wait*-pointerup.
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
*/
-function TapHoldEnd(aTimeStamp, aPoints, aLastEvent) {
- this._inProgress = true;
- // If the pointer travels, reject to Explore.
- TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent);
- checkProgressGesture(this);
+class TapHoldEnd extends TravelGesture {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ // If the pointer travels, reject to Explore.
+ super(aTimeStamp, aPoints, aLastEvent);
+ checkProgressGesture(this);
+ }
+ get _inProgress() { return true; }
+ set _inProgress(aVal) { return; }
+ get type() { return 'tapholdend'; }
}
-TapHoldEnd.prototype = Object.create(TravelGesture.prototype);
-TapHoldEnd.prototype.type = 'tapholdend';
-
/**
* DoubleTapHoldEnd gesture. This gesture can be represented as the following
* diagram:
* pointerdown-pointerup-pointerdown-pointerup-pointerdown-*wait*-pointerup.
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
*/
-function DoubleTapHoldEnd(aTimeStamp, aPoints, aLastEvent) {
- this._inProgress = true;
- // If the pointer travels, reject to Explore.
- TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent);
- checkProgressGesture(this);
+class DoubleTapHoldEnd extends TravelGesture {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ // If the pointer travels, reject to Explore.
+ super(aTimeStamp, aPoints, aLastEvent);
+ checkProgressGesture(this);
+ }
+ get _inProgress() { return true; }
+ set _inProgress(aVal) { return; }
+ get type() { return 'doubletapholdend'; }
}
-DoubleTapHoldEnd.prototype = Object.create(TravelGesture.prototype);
-DoubleTapHoldEnd.prototype.type = 'doubletapholdend';
-
/**
* A common tap gesture object.
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
- * @param {Function} aRejectToOnWait A constructor for the next gesture to
- * reject to in case no pointermove or pointerup happens within the
- * GestureSettings.dwellThreshold.
- * @param {Function} aRejectToOnPointerDown A constructor for the gesture to
- * reject to if a finger comes down immediately after the tap.
* @param {Function} aTravelTo An optional constuctor for the next gesture to
* reject to in case the the TravelGesture test fails.
*/
-function TapGesture(aTimeStamp, aPoints, aLastEvent, aRejectToOnWait, aTravelTo, aRejectToOnPointerDown) {
- this._rejectToOnWait = aRejectToOnWait;
- this._rejectToOnPointerDown = aRejectToOnPointerDown;
- // If the pointer travels, reject to aTravelTo.
- TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent, aTravelTo,
- TAP_MAX_RADIUS);
+class TapGesture extends TravelGesture {
+ constructor(aTimeStamp, aPoints, aLastEvent, aTravelTo) {
+ // If the pointer travels, reject to aTravelTo.
+ super(aTimeStamp, aPoints, aLastEvent, aTravelTo, TAP_MAX_RADIUS);
+ }
+ _getDelay() {
+ // If, for TapGesture, no pointermove or pointerup happens within the
+ // GestureSettings.dwellThreshold, reject.
+ // Note: the original pointer event's timeStamp is irrelevant here.
+ return GestureSettings.dwellThreshold;
+ }
+
+ pointerup(aPoints) {
+ if (this._rejectToOnPointerDown) {
+ this._update(aPoints, 'pointerup', false, true);
+ this.clearTimer();
+ if (GestureSettings.maxGestureResolveTimeout) {
+ this._pointerUpTimer = setTimeout(() => {
+ clearTimeout(this._pointerUpTimer);
+ delete this._pointerUpTimer;
+ this.resolve();
+ }, GestureSettings.maxGestureResolveTimeout);
+ } else {
+ this.resolve();
+ }
+ } else {
+ super.pointerup(aPoints);
+ }
+ }
+
+ pointerdown(aPoints, aTimeStamp) {
+ super.pointerdown(aPoints, aTimeStamp);
+ if (this._pointerUpTimer) {
+ clearTimeout(this._pointerUpTimer);
+ delete this._pointerUpTimer;
+ this.reject(this._rejectToOnPointerDown);
+ }
+ }
}
-TapGesture.prototype = Object.create(TravelGesture.prototype);
-TapGesture.prototype._getDelay = function TapGesture__getDelay() {
- // If, for TapGesture, no pointermove or pointerup happens within the
- // GestureSettings.dwellThreshold, reject.
- // Note: the original pointer event's timeStamp is irrelevant here.
- return GestureSettings.dwellThreshold;
-};
+/**
+ * Triple Tap gesture.
+ * @param {Number} aTimeStamp An original pointer event's timeStamp that started
+ * the gesture resolution sequence.
+ * @param {Object} aPoints An existing set of points (from previous events).
+ * @param {?String} aLastEvent Last pointer event type.
+ */
+class TripleTap extends TapGesture {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ // If the pointer travels, do not reject.
+ super(aTimeStamp, aPoints, aLastEvent, null);
+ }
+ get _rejectToOnWait() { return DoubleTapHold; }
+ get _inProgress() { return true; }
+ set _inProgress(aVal) { return; }
+ get type() { return 'tripletap'; }
+}
-TapGesture.prototype.pointerup = function TapGesture_pointerup(aPoints) {
- if (this._rejectToOnPointerDown) {
- let complete = this._update(aPoints, 'pointerup', false, true);
- if (complete) {
- this.clearTimer();
- if (GestureSettings.maxGestureResolveTimeout) {
- this._pointerUpTimer = setTimeout(() => {
- clearTimeout(this._pointerUpTimer);
- delete this._pointerUpTimer;
- this._deferred.resolve();
- }, GestureSettings.maxGestureResolveTimeout);
- } else {
- this._deferred.resolve();
- }
- }
- } else {
- TravelGesture.prototype.pointerup.call(this, aPoints);
- }
-};
-
-TapGesture.prototype.pointerdown = function TapGesture_pointerdown(aPoints, aTimeStamp) {
- TravelGesture.prototype.pointerdown.call(this, aPoints, aTimeStamp);
- if (this._pointerUpTimer) {
- clearTimeout(this._pointerUpTimer);
- delete this._pointerUpTimer;
- this._deferred.reject(this._rejectToOnPointerDown);
+/**
+ * Double Tap gesture.
+ * @param {Number} aTimeStamp An original pointer event's timeStamp that started
+ * the gesture resolution sequence.
+ * @param {Object} aPoints An existing set of points (from previous events).
+ * @param {?String} aLastEvent Last pointer event type.
+ */
+class DoubleTap extends TapGesture {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ // If the pointer travels, do not reject.
+ super(aTimeStamp, aPoints, aLastEvent, null);
}
-};
-
+ get _rejectToOnWait() { return TapHold; }
+ get _rejectToOnPointerDown() { return TripleTap; }
+ get _inProgress() { return true; }
+ set _inProgress(aVal) { return; }
+ get type() { return 'doubletap'; }
+}
/**
* Tap gesture.
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
*/
-function Tap(aTimeStamp, aPoints, aLastEvent) {
- // If the pointer travels, reject to Swipe.
- TapGesture.call(this, aTimeStamp, aPoints, aLastEvent, Dwell, Swipe, DoubleTap);
-}
-
-Tap.prototype = Object.create(TapGesture.prototype);
-Tap.prototype.type = 'tap';
-
-
-/**
- * Double Tap gesture.
- * @param {Number} aTimeStamp An original pointer event's timeStamp that started
- * the gesture resolution sequence.
- * @param {Object} aPoints An existing set of points (from previous events).
- * @param {?String} aLastEvent Last pointer event type.
- */
-function DoubleTap(aTimeStamp, aPoints, aLastEvent) {
- this._inProgress = true;
- TapGesture.call(this, aTimeStamp, aPoints, aLastEvent, TapHold, null, TripleTap);
+class Tap extends TapGesture {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ // If the pointer travels, reject to Swipe.
+ super(aTimeStamp, aPoints, aLastEvent, Swipe);
+ }
+ get _rejectToOnWait() { return Dwell; }
+ get _rejectToOnPointerDown() { return DoubleTap; }
+ get type() { return 'tap'; }
}
-DoubleTap.prototype = Object.create(TapGesture.prototype);
-DoubleTap.prototype.type = 'doubletap';
-
-/**
- * Triple Tap gesture.
- * @param {Number} aTimeStamp An original pointer event's timeStamp that started
- * the gesture resolution sequence.
- * @param {Object} aPoints An existing set of points (from previous events).
- * @param {?String} aLastEvent Last pointer event type.
- */
-function TripleTap(aTimeStamp, aPoints, aLastEvent) {
- this._inProgress = true;
- TapGesture.call(this, aTimeStamp, aPoints, aLastEvent, DoubleTapHold);
-}
-
-TripleTap.prototype = Object.create(TapGesture.prototype);
-TripleTap.prototype.type = 'tripletap';
-
-/**
- * Common base object for gestures that are created as resolved.
- * @param {Number} aTimeStamp An original pointer event's timeStamp that started
- * the gesture resolution sequence.
- * @param {Object} aPoints An existing set of points (from previous events).
- * @param {?String} aLastEvent Last pointer event type.
- */
-function ResolvedGesture(aTimeStamp, aPoints, aLastEvent) {
- Gesture.call(this, aTimeStamp, aPoints, aLastEvent);
- // Resolve the guesture right away.
- this._deferred.resolve();
-}
-
-ResolvedGesture.prototype = Object.create(Gesture.prototype);
-
/**
* Dwell gesture
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
*/
-function Dwell(aTimeStamp, aPoints, aLastEvent) {
- ResolvedGesture.call(this, aTimeStamp, aPoints, aLastEvent);
+class Dwell extends ResolvedGesture {
+ get type() { return 'dwell'; }
+ get resolveTo() { return DwellEnd; }
}
-Dwell.prototype = Object.create(ResolvedGesture.prototype);
-Dwell.prototype.type = 'dwell';
-Dwell.prototype.resolveTo = DwellEnd;
-
/**
* TapHold gesture
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
*/
-function TapHold(aTimeStamp, aPoints, aLastEvent) {
- ResolvedGesture.call(this, aTimeStamp, aPoints, aLastEvent);
+class TapHold extends ResolvedGesture {
+ get type() { return 'taphold'; }
+ get resolveTo() { return TapHoldEnd; }
}
-TapHold.prototype = Object.create(ResolvedGesture.prototype);
-TapHold.prototype.type = 'taphold';
-TapHold.prototype.resolveTo = TapHoldEnd;
-
/**
* DoubleTapHold gesture
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
*/
-function DoubleTapHold(aTimeStamp, aPoints, aLastEvent) {
- ResolvedGesture.call(this, aTimeStamp, aPoints, aLastEvent);
-}
-
-DoubleTapHold.prototype = Object.create(ResolvedGesture.prototype);
-DoubleTapHold.prototype.type = 'doubletaphold';
-DoubleTapHold.prototype.resolveTo = DoubleTapHoldEnd;
-
-/**
- * Explore gesture
- * @param {Number} aTimeStamp An original pointer event's timeStamp that started
- * the gesture resolution sequence.
- * @param {Object} aPoints An existing set of points (from previous events).
- * @param {?String} aLastEvent Last pointer event type.
- */
-function Explore(aTimeStamp, aPoints, aLastEvent) {
- ExploreGesture.call(this);
- ResolvedGesture.call(this, aTimeStamp, aPoints, aLastEvent);
+class DoubleTapHold extends ResolvedGesture {
+ get type() { return 'doubletaphold'; }
+ get resolveTo() { return DoubleTapHoldEnd; }
}
-Explore.prototype = Object.create(ResolvedGesture.prototype);
-Explore.prototype.type = 'explore';
-Explore.prototype.resolveTo = ExploreEnd;
-
-/**
- * ExploreEnd gesture.
- * @param {Number} aTimeStamp An original pointer event's timeStamp that started
- * the gesture resolution sequence.
- * @param {Object} aPoints An existing set of points (from previous events).
- * @param {?String} aLastEvent Last pointer event type.
- */
-function ExploreEnd(aTimeStamp, aPoints, aLastEvent) {
- this._inProgress = true;
- ExploreGesture.call(this);
- // If the pointer travels, reject to Explore.
- TravelGesture.call(this, aTimeStamp, aPoints, aLastEvent);
- checkProgressGesture(this);
-}
-
-ExploreEnd.prototype = Object.create(TravelGesture.prototype);
-ExploreEnd.prototype.type = 'exploreend';
-
/**
* Swipe gesture.
* @param {Number} aTimeStamp An original pointer event's timeStamp that started
* the gesture resolution sequence.
* @param {Object} aPoints An existing set of points (from previous events).
* @param {?String} aLastEvent Last pointer event type.
*/
-function Swipe(aTimeStamp, aPoints, aLastEvent) {
- this._inProgress = true;
- this._rejectToOnWait = Explore;
- Gesture.call(this, aTimeStamp, aPoints, aLastEvent);
- checkProgressGesture(this);
-}
-
-Swipe.prototype = Object.create(Gesture.prototype);
-Swipe.prototype.type = 'swipe';
-Swipe.prototype._getDelay = function Swipe__getDelay(aTimeStamp) {
- // Swipe should be completed within the GestureSettings.swipeMaxDuration from
- // the initial pointer down event.
- return GestureSettings.swipeMaxDuration - this.startTime + aTimeStamp;
-};
+class Swipe extends Gesture {
+ constructor(aTimeStamp, aPoints, aLastEvent) {
+ super(aTimeStamp, aPoints, aLastEvent);
+ checkProgressGesture(this);
+ }
+ get type() { return 'swipe'; }
+ get _inProgress() { return true; }
+ set _inProgress(aVal) { return; }
+ get _rejectToOnWait() { return Explore; }
+ _getDelay(aTimeStamp) {
+ // Swipe should be completed within the GestureSettings.swipeMaxDuration
+ // from the initial pointer down event.
+ return GestureSettings.swipeMaxDuration - this.startTime + aTimeStamp;
+ }
-/**
- * Determine wither the gesture was Swipe or Explore.
- * @param {Booler} aComplete A flag that indicates whether the gesture is and
- * will be complete after the test.
- */
-Swipe.prototype.test = function Swipe_test(aComplete) {
- if (!aComplete) {
- // No need to test if the gesture is not completing or can't be complete.
- return;
- }
- let reject = true;
- // If at least one point travelled for more than SWIPE_MIN_DISTANCE and it was
- // direct enough, consider it a Swipe.
- for (let identifier in this.points) {
- let point = this.points[identifier];
- let directDistance = point.directDistanceTraveled;
- if (directDistance / Utils.dpi >= SWIPE_MIN_DISTANCE ||
- directDistance * DIRECTNESS_COEFF >= point.totalDistanceTraveled) {
- reject = false;
+ test(aComplete) {
+ if (!aComplete) {
+ // No need to test if the gesture is not completing or can't be complete.
+ return;
+ }
+ let reject = true;
+ // If at least one point travelled for more than SWIPE_MIN_DISTANCE and it was
+ // direct enough, consider it a Swipe.
+ for (let identifier in this.points) {
+ let point = this.points[identifier];
+ let directDistance = point.directDistanceTraveled;
+ if (directDistance / Utils.dpi >= SWIPE_MIN_DISTANCE ||
+ directDistance * DIRECTNESS_COEFF >= point.totalDistanceTraveled) {
+ reject = false;
+ }
+ }
+ if (reject) {
+ this.reject(Explore);
}
}
- if (reject) {
- this._deferred.reject(Explore);
+ /**
+ * Compile a swipe related mozAccessFuGesture event detail.
+ * @return {Object} A mozAccessFuGesture detail object.
+ */
+ compile() {
+ let type = this.type;
+ let detail = compileDetail(type, this.points,
+ {x1: 'startX', y1: 'startY', x2: 'x', y2: 'y'});
+ let deltaX = detail.deltaX;
+ let deltaY = detail.deltaY;
+ let edge = EDGE * Utils.dpi;
+ if (Math.abs(deltaX) > Math.abs(deltaY)) {
+ // Horizontal swipe.
+ let startPoints = detail.touches.map(touch => touch.x1);
+ if (deltaX > 0) {
+ detail.type = type + 'right';
+ detail.edge = Math.min.apply(null, startPoints) <= edge;
+ } else {
+ detail.type = type + 'left';
+ detail.edge =
+ Utils.win.screen.width - Math.max.apply(null, startPoints) <= edge;
+ }
+ } else {
+ // Vertical swipe.
+ let startPoints = detail.touches.map(touch => touch.y1);
+ if (deltaY > 0) {
+ detail.type = type + 'down';
+ detail.edge = Math.min.apply(null, startPoints) <= edge;
+ } else {
+ detail.type = type + 'up';
+ detail.edge =
+ Utils.win.screen.height - Math.max.apply(null, startPoints) <= edge;
+ }
+ }
+ return detail;
}
-};
-
-/**
- * Compile a swipe related mozAccessFuGesture event detail.
- * @return {Object} A mozAccessFuGesture detail object.
- */
-Swipe.prototype.compile = function Swipe_compile() {
- let type = this.type;
- let detail = compileDetail(type, this.points,
- {x1: 'startX', y1: 'startY', x2: 'x', y2: 'y'});
- let deltaX = detail.deltaX;
- let deltaY = detail.deltaY;
- let edge = EDGE * Utils.dpi;
- if (Math.abs(deltaX) > Math.abs(deltaY)) {
- // Horizontal swipe.
- let startPoints = detail.touches.map(touch => touch.x1);
- if (deltaX > 0) {
- detail.type = type + 'right';
- detail.edge = Math.min.apply(null, startPoints) <= edge;
- } else {
- detail.type = type + 'left';
- detail.edge =
- Utils.win.screen.width - Math.max.apply(null, startPoints) <= edge;
- }
- } else {
- // Vertical swipe.
- let startPoints = detail.touches.map(touch => touch.y1);
- if (deltaY > 0) {
- detail.type = type + 'down';
- detail.edge = Math.min.apply(null, startPoints) <= edge;
- } else {
- detail.type = type + 'up';
- detail.edge =
- Utils.win.screen.height - Math.max.apply(null, startPoints) <= edge;
- }
- }
- return detail;
-};
+}