Bug 639179 Part 3: Tapping during kinetic panning stops panning r=mbrubeck

This commit is contained in:
Benjamin Stover 2011-04-11 13:52:43 -07:00
parent 928b5a771c
commit f43911e5f5

View File

@ -60,6 +60,13 @@ const kAxisLockRevertThreshold = 0.8;
// Same as NS_EVENT_STATE_ACTIVE from nsIEventStateManager.h
const kStateActive = 0x00000001;
// After a drag begins, kinetic panning is stopped if the drag doesn't become
// a pan in 300 milliseconds.
const kStopKineticPanOnDragTimeout = 300;
// Max velocity of a pan. This is in pixels/millisecond.
const kMaxVelocity = 6;
/**
* MouseModule
*
@ -205,19 +212,21 @@ MouseModule.prototype = {
this._targetScrollInterface = targetScrollInterface;
// Do tap
let event = document.createEvent("Events");
event.initEvent("TapDown", true, true);
event.clientX = aEvent.clientX;
event.clientY = aEvent.clientY;
let success = aEvent.target.dispatchEvent(event);
if (success) {
this._recordEvent(aEvent);
this._target = aEvent.target;
this._mouseOverTimeout.once(kOverTapWait);
this._longClickTimeout.once(kLongTapWait);
} else {
// cancel all pending content clicks
this._cleanClickBuffer();
if (!this._kinetic.isActive()) {
let event = document.createEvent("Events");
event.initEvent("TapDown", true, true);
event.clientX = aEvent.clientX;
event.clientY = aEvent.clientY;
let success = aEvent.target.dispatchEvent(event);
if (success) {
this._recordEvent(aEvent);
this._target = aEvent.target;
this._mouseOverTimeout.once(kOverTapWait);
this._longClickTimeout.once(kLongTapWait);
} else {
// cancel all pending content clicks
this._cleanClickBuffer();
}
}
// Do pan
@ -358,6 +367,7 @@ MouseModule.prototype = {
let dragData = this._dragData;
dragData.setDragStart(aEvent.screenX, aEvent.screenY, aDraggable);
this._kinetic.addData(0, 0);
this._dragStartTime = Date.now();
if (!this._kinetic.isActive())
this._dragger.dragStart(aEvent.clientX, aEvent.clientY, aEvent.target, this._targetScrollInterface);
},
@ -374,13 +384,15 @@ MouseModule.prototype = {
// mousedown/mouseup event previous to this one. In this case, we
// want the kinetic panner to tell our drag interface to stop.
if (!dragData.isPan() && !this._kinetic.isActive()) {
// There was no pan and no kinetic scrolling, so just stop dragger.
this._dragger.dragStop(0, 0, this._targetScrollInterface);
this._dragger = null;
} else if (dragData.isPan()) {
if (dragData.isPan()) {
if (Date.now() - this._dragStartTime > kStopKineticPanOnDragTimeout)
this._kinetic._velocity.set(0, 0);
// Start kinetic pan.
this._kinetic.start();
} else {
this._kinetic.end();
this._dragger.dragStop(0, 0, this._targetScrollInterface);
this._dragger = null;
}
},
@ -392,6 +404,7 @@ MouseModule.prototype = {
*/
_dragBy: function _dragBy(dX, dY, aIsKinetic) {
let dragged = true;
let dragData = this._dragData;
if (!this._waitingForPaint || aIsKinetic) {
let dragData = this._dragData;
dragged = this._dragger.dragMove(dX, dY, this._targetScrollInterface, aIsKinetic);
@ -402,6 +415,9 @@ MouseModule.prototype = {
this.dX = 0;
this.dY = 0;
}
if (!dragData.isPan())
this._kinetic.pause();
return dragged;
},
@ -831,6 +847,7 @@ function KineticController(aPanBy, aEndCallback) {
KineticController.prototype = {
_reset: function _reset() {
this._active = false;
this._paused = false;
this.momentumBuffer = [];
this._velocity.set(0, 0);
},
@ -872,7 +889,9 @@ KineticController.prototype = {
let callback = {
onBeforePaint: function kineticHandleEvent(timeStamp) {
if (!self.isActive()) // someone called end() on us between timer intervals
// Someone called end() on us between timer intervals
// or we are paused.
if (!self.isActive() || self._paused)
return;
// To make animation end fast enough but to keep smoothness, average the ideal
@ -923,6 +942,7 @@ KineticController.prototype = {
};
this._active = true;
this._paused = false;
mozRequestAnimationFrame(callback);
},
@ -949,9 +969,22 @@ KineticController.prototype = {
}
}
// Only allow kinetic scrolling to speed up if kinetic scrolling is active.
this._velocity.x = (distanceX < 0 ? Math.min : Math.max)((distanceX / swipeLength) * this._speedSensitivity, this._velocity.x);
this._velocity.y = (distanceY < 0 ? Math.min : Math.max)((distanceY / swipeLength) * this._speedSensitivity, this._velocity.y);
let currentVelocityX = 0;
let currentVelocityY = 0;
if (this.isActive()) {
let currentTime = Date.now() - this._initialTime;
currentVelocityX = Util.clamp(this._velocity.x + this._acceleration.x * currentTime, -kMaxVelocity, kMaxVelocity);
currentVelocityY = Util.clamp(this._velocity.y + this._acceleration.y * currentTime, -kMaxVelocity, kMaxVelocity);
}
if (currentVelocityX * this._velocity.x <= 0)
currentVelocityX = 0;
if (currentVelocityY * this._velocity.y <= 0)
currentVelocityY = 0;
this._velocity.x = clampFromZero((distanceX / swipeLength) + currentVelocityX, Math.abs(currentVelocityX), kMaxVelocity);
this._velocity.y = clampFromZero((distanceY / swipeLength) + currentVelocityY, Math.abs(currentVelocityY), kMaxVelocity);
// Set acceleration vector to opposite signs of velocity
this._acceleration.set(this._velocity.clone().map(sign).scale(-this._decelerationRate));
@ -961,12 +994,16 @@ KineticController.prototype = {
this._time = 0;
this.momentumBuffer = [];
if (!this.isActive())
if (!this.isActive() || this._paused)
this._startTimer();
return true;
},
pause: function pause() {
this._paused = true;
},
end: function end() {
if (this.isActive()) {
if (this._beforeEnd)