--- a/mobile/chrome/content/input.js
+++ b/mobile/chrome/content/input.js
@@ -181,20 +181,21 @@ MouseModule.prototype = {
this._cleanClickBuffer();
},
/** Begin possible pan and send tap down event. */
_onMouseDown: function _onMouseDown(aEvent) {
let dragData = this._dragData;
if (dragData.dragging) {
// Somehow a mouse up was missed.
- let [sX, sY] = dragData.panPosition();
this._doDragStop();
}
dragData.reset();
+ this.dX = 0;
+ this.dY = 0;
// walk up the DOM tree in search of nearest scrollable ancestor. nulls are
// returned if none found.
let [targetScrollbox, targetScrollInterface, dragger]
= ScrollUtils.getScrollboxFromElement(aEvent.target);
// stop kinetic panning if targetScrollbox has changed
if (this._kinetic.isActive() && this._dragger != dragger)
@@ -241,16 +242,19 @@ MouseModule.prototype = {
/** Send tap up event and any necessary full taps. */
_onMouseUp: function _onMouseUp(aEvent) {
if (this._suppressNextMouseUp) {
this._suppressNextMouseUp = false;
aEvent.stopPropagation();
aEvent.preventDefault();
}
+ // onMouseMove will not record the delta change if we are waiting for a
+ // paint. Since this is the last input for this drag, we override the flag.
+ this._waitingForPaint = false;
this._onMouseMove(aEvent);
let dragData = this._dragData;
this._doDragStop();
// Do tap
if (this._target) {
let event = document.createEvent("Events");
@@ -295,23 +299,41 @@ MouseModule.prototype = {
},
/**
* If we're in a drag, do what we have to do to drag on.
*/
_onMouseMove: function _onMouseMove(aEvent) {
let dragData = this._dragData;
- if (dragData.dragging && !this._waitingForPaint) {
+ if (dragData.dragging) {
let oldIsPan = dragData.isPan();
dragData.setDragPosition(aEvent.screenX, aEvent.screenY);
+
+ // Kinetic panning is sensitive to time. It is more stable if it receives
+ // the mousemove events as they come. For dragging though, we only want
+ // to call _dragBy if we aren't waiting for a paint (so we don't spam the
+ // main browser loop with a bunch of redundant paints).
+ //
+ // Here, we feed kinetic panning drag differences for mouse events as
+ // come; for dragging, we build up a drag buffer in this.dX/this.dY and
+ // release it when we are ready to paint.
+ //
+ let [sX, sY] = dragData.panPosition();
+ this.dX += dragData.prevPanX - sX;
+ this.dY += dragData.prevPanY - sY;
+
if (dragData.isPan()) {
// Only pan when mouse event isn't part of a click. Prevent jittering on tap.
- let [sX, sY] = dragData.panPosition();
- this._doDragMove();
+ this._kinetic.addData(sX - dragData.prevPanX, sY - dragData.prevPanY);
+ if (!this._waitingForPaint) {
+ this._dragBy(this.dX, this.dY);
+ this.dX = 0;
+ this.dY = 0;
+ }
// Let everyone know when mousemove begins a pan
if (!oldIsPan && dragData.isPan()) {
this._mouseOverTimeout.clear();
this._longClickTimeout.clear();
let event = document.createEvent("Events");
event.initEvent("PanBegin", true, false);
@@ -352,39 +374,23 @@ MouseModule.prototype = {
// 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()) {
// Start kinetic pan.
- let [sX, sY] = dragData.panPosition();
- let dX = dragData.prevPanX - sX;
- let dY = dragData.prevPanY - sY;
- this._kinetic.addData(-dX, -dY);
this._kinetic.start();
}
},
/**
- * Update kinetic with new data and drag.
- */
- _doDragMove: function _doDragMove() {
- let dragData = this._dragData;
- let [sX, sY] = dragData.panPosition();
- let dX = dragData.prevPanX - sX;
- let dY = dragData.prevPanY - sY;
- this._kinetic.addData(-dX, -dY);
- this._dragBy(dX, dY);
- },
-
- /**
- * Used by _doDragMove() above and by KineticController's timer to do the
- * actual dragMove signalling to the dragger. We'd put this in _doDragMove()
+ * Used by _onMouseMove() above and by KineticController's timer to do the
+ * actual dragMove signalling to the dragger. We'd put this in _onMouseMove()
* but then KineticController would be adding to its own data as it signals
* the dragger of dragMove()s.
*/
_dragBy: function _dragBy(dX, dY) {
let dragData = this._dragData;
let dragged = this._dragger.dragMove(dX, dY, this._targetScrollInterface);
if (dragged && !this._waitingForPaint) {
this._waitingForPaint = true;
@@ -706,23 +712,23 @@ DragData.prototype = {
if (absX > 2.5 * absY)
this.lockedY = sY;
else if (absY > absX)
this.lockedX = sX;
this.locked = true;
}
+ }
- // After pan lock, figure out previous panning position. Base it on last drag
- // position so there isn't a jump in panning.
- let [prevX, prevY] = this._lockAxis(this.sX, this.sY);
- this.prevPanX = prevX;
- this.prevPanY = prevY;
- }
+ // After pan lock, figure out previous panning position. Base it on last drag
+ // position so there isn't a jump in panning.
+ let [prevX, prevY] = this._lockAxis(this.sX, this.sY);
+ this.prevPanX = prevX;
+ this.prevPanY = prevY;
this.sX = sX;
this.sY = sY;
},
setDragStart: function setDragStart(screenX, screenY, aDraggable) {
this.sX = this._originX = screenX;
this.sY = this._originY = screenY;