Bug 667243 - [backout] use caretPositionFromPoint for controlling text selection r=mbrubeck
authorMark Finkle <mfinkle@mozilla.com>
Wed, 07 Sep 2011 10:48:13 -0400
changeset 77982 ac5813b1196e5ec0d04152894a1fc4dab046cb31
parent 77981 1ddde977131ab1245e0d6e209cf75b3bc4b70553
child 77983 e3ce5dcd24831cbc8c271046abc4c9a93f12e747
push id78
push userclegnitto@mozilla.com
push dateFri, 16 Dec 2011 17:32:24 +0000
treeherdermozilla-release@79d24e644fdd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmbrubeck
bugs667243
milestone9.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 667243 - [backout] use caretPositionFromPoint for controlling text selection r=mbrubeck
mobile/chrome/content/content.js
--- a/mobile/chrome/content/content.js
+++ b/mobile/chrome/content/content.js
@@ -1396,21 +1396,22 @@ var SelectionHandler = {
 
         let currentDocShell = contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell);
 
         // Remove any previous selected or created ranges. Tapping anywhere on a
         // page will create an empty range.
         let selection = contentWindow.getSelection();
         selection.removeAllRanges();
 
+          // Position the caret using a fake mouse click
+          utils.sendMouseEventToWindow("mousedown", x, y, 0, 1, 0, true);
+          utils.sendMouseEventToWindow("mouseup", x, y, 0, 1, 0, true);
+
         try {
-          let caretPos = contentWindow.document.caretPositionFromPoint(json.x - scrollOffset.x, json.y - scrollOffset.y);
           let selcon = currentDocShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsISelectionDisplay).QueryInterface(Ci.nsISelectionController);
-          let sel = selcon.getSelection(1);
-          sel.collapse(caretPos.offsetNode, caretPos.offset);
 
           // Select the word nearest the caret
           selcon.wordMove(false, false);
           selcon.wordMove(true, true);
         } catch(e) {
           // If we couldn't select the word at the given point, bail
           return;
         }
@@ -1461,47 +1462,42 @@ var SelectionHandler = {
         }
         break;
       }
 
       case "Browser:SelectionMove":
         if (!this.contentWindow)
           return;
 
-        let x = json.x - scrollOffset.x;
-        let y = json.y - scrollOffset.y;
-
-        try {
-          let caretPos = this.contentWindow.document.caretPositionFromPoint(x, y);
-          if (caretPos.offsetNode == null ||
-              caretPos.offsetNode instanceof Ci.nsIDOMHTMLInputElement || 
-              caretPos.offsetNode instanceof Ci.nsIDOMHTMLTextAreaElement ||
-              caretPos.offsetNode.ownerDocument.defaultView != this.contentWindow)
-            return;
+        // Hack to avoid setting focus in a textbox [Bugs 654352 & 667243]
+        let elemUnder = elementFromPoint(json.x - scrollOffset.x, json.y - scrollOffset.y);
+        if (elemUnder && elemUnder instanceof Ci.nsIDOMHTMLInputElement || elemUnder instanceof Ci.nsIDOMHTMLTextAreaElement)
 
-          // Keep the cache in "client" coordinates
-          if (json.type == "end")
-            this.cache.end = { x: json.x, y: json.y };
-          else
-            this.cache.start = { x: json.x, y: json.y };
-
-          let currentDocShell = this.contentWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIWebNavigation).QueryInterface(Ci.nsIDocShell);
-          let selcon = currentDocShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsISelectionDisplay).QueryInterface(Ci.nsISelectionController);
-          let sel = selcon.getSelection(1);
-          if (json.type != "end") {
-            let focusOffset = sel.focusOffset;
-            let focusNode = sel.focusNode;
-            sel.collapse(caretPos.offsetNode, caretPos.offset);
-            sel.extend(focusNode, focusOffset);
-          } else {
-            sel.extend(caretPos.offsetNode, caretPos.offset);
-          }
-        } catch(e) {
-          Cu.reportError(e);
+        // Limit the selection to the initial content window (don't leave or enter iframes)
+        if (elemUnder && elemUnder.ownerDocument.defaultView != this.contentWindow)
           return;
+        
+        // Use fake mouse events to update the selection
+        if (json.type == "end") {
+          // Keep the cache in "client" coordinates, but translate for the mouse event
+          this.cache.end = { x: json.x, y: json.y };
+          let end = { x: this.cache.end.x - scrollOffset.x, y: this.cache.end.y - scrollOffset.y };
+          utils.sendMouseEventToWindow("mousedown", end.x, end.y, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
+          utils.sendMouseEventToWindow("mouseup", end.x, end.y, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
+        } else {
+          // Keep the cache in "client" coordinates, but translate for the mouse event
+          this.cache.start = { x: json.x, y: json.y };
+          let start = { x: this.cache.start.x - scrollOffset.x, y: this.cache.start.y - scrollOffset.y };
+          let end = { x: this.cache.end.x - scrollOffset.x, y: this.cache.end.y - scrollOffset.y };
+        
+          utils.sendMouseEventToWindow("mousedown", start.x, start.y, 0, 0, 0, true);
+          utils.sendMouseEventToWindow("mouseup", start.x, start.y, 0, 0, 0, true);
+        
+          utils.sendMouseEventToWindow("mousedown", end.x, end.y, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
+          utils.sendMouseEventToWindow("mouseup", end.x, end.y, 0, 1, Ci.nsIDOMNSEvent.SHIFT_MASK, true);
         }
 
         // Cache the selected text since the selection might be gone by the time we get the "end" message
         let selection = this.contentWindow.getSelection()
         this.selectedText = selection.toString().trim();
 
         // Update the rect we use to test when finishing the clipboard operation
         let range = selection.getRangeAt(0).QueryInterface(Ci.nsIDOMNSRange);