Bug 484271: ContentPanningHandler gets out of sync when dragging out of window, r=mfinkle
authorBen Combee <combee@mozilla.com>
Thu, 19 Mar 2009 17:32:50 -0400
changeset 65140 f33eca6fa1d03eee19aa5a0f16b240e2e9741ce5
parent 65139 55259dbebebfedd664e9f60f35acab349f696127
child 65141 ed493d9428251bddc0c654be41292a176b89a3eb
push idunknown
push userunknown
push dateunknown
reviewersmfinkle
bugs484271
Bug 484271: ContentPanningHandler gets out of sync when dragging out of window, r=mfinkle
mobile/chrome/content/InputHandler.js
--- a/mobile/chrome/content/InputHandler.js
+++ b/mobile/chrome/content/InputHandler.js
@@ -179,20 +179,24 @@ ChromeInputModule.prototype = {
     sY: 0,
     dragStartTimeout: -1,
     targetScrollbox: null,
 
     reset: function reset() {
       this.dragging = false;
       this.sX = 0;
       this.sY = 0;
+      this.clearDragStartTimeout();
+      this.targetScrollbox = null;
+    },
+
+    clearDragStartTimeout: function clearDragStartTimeout() {
       if (this.dragStartTimeout != -1)
         clearTimeout(this.dragStartTimeout);
       this.dragStartTimeout = -1;
-      this.targetScrollbox = null;
     }
   },
 
   _clickData: {
     _events : [],
     reset: function reset() {
       this._events = [];
     }
@@ -331,17 +335,17 @@ ChromeInputModule.prototype = {
     aEvent.stopPropagation();
     aEvent.preventDefault();
 
     let dx = dragData.sX - aEvent.screenX;
     let dy = dragData.sY - aEvent.screenY;
 
     if (!dragData.dragging && dragData.dragStartTimeout != -1) {
       if (dx*dx + dy*dy > 100) {
-        clearTimeout(dragData.dragStartTimeout);
+        dragData.clearDragStartTimeout();
         this._dragStart(aEvent.screenX, aEvent.screenY);
       }
     }
     if (!dragData.dragging)
       return;
 
     this._dragMove(aEvent.screenX, aEvent.screenY);
 
@@ -400,16 +404,20 @@ ContentPanningModule.prototype = {
     sY: 0,
     useKinetic: true,
     dragStartTimeout: -1,
 
     reset: function reset() {
       this.dragging = false;
       this.sX = 0;
       this.sY = 0;
+      this.clearDragStartTimeout();
+    },
+
+    clearDragStartTimeout: function clearDragStartTimeout() {
       if (this.dragStartTimeout != -1)
         clearTimeout(this.dragStartTimeout);
       this.dragStartTimeout = -1;
     }
   },
 
   _kineticData: {
     // const
@@ -465,18 +473,20 @@ ContentPanningModule.prototype = {
         break;
     }
   },
 
   /* If someone else grabs events ahead of us, cancel any pending
    * timeouts we may have.
    */
   cancelPending: function cancelPending() {
-    this._dragData.reset();
-    // XXX we should cancel kinetic here as well
+    let dragData = this._dragData;
+    // stop scrolling, pass last coordinate we used
+    this._endKinetic(dragData.sX, dragData.sY);
+    dragData.reset();
   },
 
   _dragStart: function _dragStart(sX, sY) {
     let dragData = this._dragData;
     dragData.dragging = true;
     dragData.dragStartTimeout = -1;
 
     // grab all events until we stop the drag
@@ -495,17 +505,17 @@ ContentPanningModule.prototype = {
     this._owner.ungrab(this);
 
     if (dragData.useKinetic) {
       // start kinetic scrolling here for canvas only
       if (!this._startKinetic(sX, sY))
         this._endKinetic(sX, sY);
     }
     else {
-      ws.dragStop(sX, sY);
+      ws.dragStop();
     }
 
     // flush any paints that might be left so that our next pan will be fast
     Browser.canvasBrowser.endPanning();
   },
 
   _dragMove: function _dragMove(sX, sY) {
     let dragData = this._dragData;
@@ -542,17 +552,17 @@ ContentPanningModule.prototype = {
 
     let dragData = this._dragData;
 
     let dx = dragData.sX - aEvent.screenX;
     let dy = dragData.sY - aEvent.screenY;
 
     if (!dragData.dragging && dragData.dragStartTimeout != -1) {
       if (dx*dx + dy*dy > 100) {
-        clearTimeout(dragData.dragStartTimeout);
+        dragData.clearDragStartTimeout();
         this._dragStart(aEvent.screenX, aEvent.screenY);
       }
     }
     if (!dragData.dragging)
       return;
 
     this._dragMove(aEvent.screenX, aEvent.screenY);
 
@@ -574,17 +584,17 @@ ContentPanningModule.prototype = {
   },
 
   _startKinetic: function _startKinetic(sX, sY) {
     let kineticData = this._kineticData;
 
     let dx = 0;
     let dy = 0;
     let dt = 0;
-    if (kineticData.kineticInitialVel)
+    if (kineticData.kineticInitialVel != 0)
       return true;
 
     if (!kineticData.momentumBuffer)
       return false;
 
     for (let i = 0; i < kineticData.momentumBufferSize; i++) {
       let me = kineticData.momentumBuffer[(kineticData.momentumBufferIndex + i) % kineticData.momentumBufferSize];
       if (!me)
@@ -644,20 +654,22 @@ ContentPanningModule.prototype = {
 
     self._dragMove(newX, newY);
 
     if(t >= kineticData.kineticDuration)
       self._endKinetic(newX, newY);
   },
 
   _endKinetic: function _endKinetic(sX, sY) {
-    ws.dragStop(sX, sY);
+    let kineticData = this._kineticData;
+
+    ws.dragStop();
     this._owner.ungrab(this);
     this._dragData.reset();
-    this._kineticData.reset();
+    kineticData.reset();
 
     // Make sure that sidebars don't stay partially open
     // XXX this should live somewhere else
     let [leftVis,] = ws.getWidgetVisibility("tabs-container", false);
     let [rightVis,] = ws.getWidgetVisibility("browser-controls", false);
     if (leftVis != 0 && leftVis != 1) {
       let w = document.getElementById("tabs-container").getBoundingClientRect().width;
       if (leftVis >= 0.6666)
@@ -715,16 +727,17 @@ ContentClickingModule.prototype = {
 
         this._events.push({event: aEvent, time: Date.now()});
 
         if (this._clickTimeout == -1) {
           this._clickTimeout = setTimeout(function(self) { self._sendSingleClick(); }, 400, this);
         }
         else {
           clearTimeout(this._clickTimeout);
+          this.clickTimeout = -1;
           this._sendDoubleClick();
         }
         break;
     }
   },
 
   /* If someone else grabs events ahead of us, cancel any pending
    * timeouts we may have.