Bug 891805 - Cache caret position at the start of a drag in text edits, and use that when initiating selection. r=rsilveira
authorJim Mathies <jmathies@mozilla.com>
Thu, 11 Jul 2013 04:29:27 -0500
changeset 138097 80f127b3950fa4736b0134bd59e72e35545a25e2
parent 138096 aeab42c594231c6aab336a74f33a336041a9a2f6
child 138120 30e1aa72fc7b06c6feeba24d81da65d72b87a764
push id30826
push userjmathies@mozilla.com
push dateThu, 11 Jul 2013 09:30:01 +0000
treeherdermozilla-inbound@80f127b3950f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrsilveira
bugs891805
milestone25.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 891805 - Cache caret position at the start of a drag in text edits, and use that when initiating selection. r=rsilveira
browser/metro/base/content/helperui/SelectionHelperUI.js
browser/metro/base/tests/mochitest/browser_selection_contenteditable.js
--- a/browser/metro/base/content/helperui/SelectionHelperUI.js
+++ b/browser/metro/base/content/helperui/SelectionHelperUI.js
@@ -605,25 +605,35 @@ var SelectionHelperUI = {
       targetMark = this.startMark;
     else
       targetMark = this.endMark;
 
     // Position both in the same starting location.
     this.startMark.position(targetMark.xPos, targetMark.yPos);
     this.endMark.position(targetMark.xPos, targetMark.yPos);
 
+    // We delay transitioning until we know which direction the user is dragging
+    // based on a hysteresis value in the drag marker code. Down in our caller, we
+    // cache the first drag position in _cachedCaretPos so we can select from the
+    // initial caret drag position. Use those values if we have them. (Note
+    // _cachedCaretPos has already been translated in _getMarkerBaseMessage.)
+    let xpos = this._cachedCaretPos ? this._cachedCaretPos.xPos :
+      this._msgTarget.ctobx(targetMark.xPos, true);
+    let ypos = this._cachedCaretPos ? this._cachedCaretPos.yPos :
+      this._msgTarget.ctoby(targetMark.yPos, true);
+
     // Start the selection monocle drag. SelectionHandler relies on this
     // for getting initialized. This will also trigger a message back for
     // monocle positioning. Note, markerDragMove is still on the stack in
     // this call!
     this._sendAsyncMessage("Browser:SelectionSwitchMode", {
       newMode: "selection",
       change: targetMark.tag,
-      xPos: this._msgTarget.ctobx(targetMark.xPos, true),
-      yPos: this._msgTarget.ctoby(targetMark.yPos, true),
+      xPos: xpos,
+      yPos: ypos,
     });
   },
 
   /*
    * _transitionFromSelectionToCaret
    *
    * Transitions from text selection mode to caret mode.
    *
@@ -1092,16 +1102,17 @@ var SelectionHelperUI = {
         yPos: this._msgTarget.ctoby(this.caretMark.yPos, true)
       },
     };
   },
 
   markerDragStart: function markerDragStart(aMarker) {
     let json = this._getMarkerBaseMessage(aMarker.tag);
     if (aMarker.tag == "caret") {
+      this._cachedCaretPos = null;
       this._sendAsyncMessage("Browser:CaretMove", json);
       return;
     }
     this._sendAsyncMessage("Browser:SelectionMoveStart", json);
   },
 
   markerDragStop: function markerDragStop(aMarker) {
     let json = this._getMarkerBaseMessage(aMarker.tag);
@@ -1118,18 +1129,23 @@ var SelectionHelperUI = {
       // direction the user is dragging.
       if (aDirection != "tbd") {
         // We are going to transition from caret browsing mode to selection
         // mode on drag. So swap the caret monocle for a start or end monocle
         // depending on the direction of the drag, and start selecting text.
         this._transitionFromCaretToSelection(aDirection);
         return false;
       }
+      // Cache for when we start the drag in _transitionFromCaretToSelection.
+      if (!this._cachedCaretPos) {
+        this._cachedCaretPos = this._getMarkerBaseMessage(aMarker.tag).caret;
+      }
       return true;
     }
+    this._cachedCaretPos = null;
 
     // We'll re-display these after the drag is complete.
     this._hideMonocles();
 
     let json = this._getMarkerBaseMessage(aMarker.tag);
     this._sendAsyncMessage("Browser:SelectionMove", json);
     return true;
   },
--- a/browser/metro/base/tests/mochitest/browser_selection_contenteditable.js
+++ b/browser/metro/base/tests/mochitest/browser_selection_contenteditable.js
@@ -33,17 +33,17 @@ gTests.push({
 });
 
 gTests.push({
   desc: "simple test to make sure content editable selection works",
   run: function test() {
     let div = gWindow.document.getElementById("testdiv");
     ok(div, "have the div");
 
-    sendElementTap(gWindow, div, 295); // end of 'outlook.com'
+    sendElementTap(gWindow, div, 287); // end of 'outlook.com'
 
     yield waitForCondition(function () {
         return SelectionHelperUI.isCaretUIVisible;
       }, kCommonWaitMs, kCommonPollMs);
 
     let xpos = SelectionHelperUI.caretMark.xPos;
     let ypos = SelectionHelperUI.caretMark.yPos + 10;
     var touchdrag = new TouchDragAndHold();