Bug 675920 - Difficult to select text if you don't tap directly on text [r=wjohnston, a=legneato]
authorMark Finkle <mfinkle@mozilla.com>
Wed, 03 Aug 2011 00:23:40 -0400
changeset 72754 029a0c4af93573ce38c969affc3c17b23b419c2c
parent 72753 751b55a876f61b3a2b9b7a7b224d08f3e4bcb1aa
child 72755 bd419b4cdaeab30b8584fa49dcb6a799f92f0624
push id288
push usermfinkle@mozilla.com
push dateFri, 05 Aug 2011 03:05:53 +0000
treeherdermozilla-aurora@029a0c4af935 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswjohnston, legneato
bugs675920
milestone7.0a2
Bug 675920 - Difficult to select text if you don't tap directly on text [r=wjohnston, a=legneato]
mobile/chrome/content/content.js
--- a/mobile/chrome/content/content.js
+++ b/mobile/chrome/content/content.js
@@ -1342,16 +1342,17 @@ var SelectionHandler = {
 
   receiveMessage: function sh_receiveMessage(aMessage) {
     let scrollOffset = ContentScroll.getScrollOffset(content);
     let utils = Util.getWindowUtils(content);
     let json = aMessage.json;
 
     switch (aMessage.name) {
       case "Browser:SelectionStart": {
+        // Clear out the text cache
         this.selectedText = "";
 
         // if this is an iframe, dig down to find the document that was clicked
         let x = json.x;
         let y = json.y;
         let offset = scrollOffset;
         let elem = utils.elementFromPoint(x, y, true, false);
         while (elem && (elem instanceof HTMLIFrameElement || elem instanceof HTMLFrameElement)) {
@@ -1361,35 +1362,42 @@ var SelectionHandler = {
           offset.x += rect.left;
           x -= rect.left;
 
           offset.y += rect.top + scrollOffset.y;
           y -= rect.top + scrollOffset.y;
           utils = elem.contentDocument.defaultView.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
           elem = utils.elementFromPoint(x, y, true, false);
         }
+        if (!elem)
+          return;
+
         let contentWindow = elem.ownerDocument.defaultView;
         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 - scrollOffset.x, y - scrollOffset.y, 0, 1, 0, true);
         utils.sendMouseEventToWindow("mouseup", x - scrollOffset.x, y - scrollOffset.y, 0, 1, 0, true);
 
         // Select the word nearest the caret
         try {
           let selcon = currentDocShell.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsISelectionDisplay).QueryInterface(Ci.nsISelectionController);
           selcon.wordMove(false, false);
           selcon.wordMove(true, true);
         } catch(e) {
           // If we couldn't select the word at the given point, bail
           return;
         }
 
         // Find the selected text rect and send it back so the handles can position correctly
-        let selection = contentWindow.getSelection();
         if (selection.rangeCount == 0)
           return;
 
         let range = selection.getRangeAt(0).QueryInterface(Ci.nsIDOMNSRange);
         if (!range)
           return;
 
         // Cache the selected text since the selection might be gone by the time we get the "end" message
@@ -1397,24 +1405,16 @@ var SelectionHandler = {
 
         // If the range didn't have any text, let's bail
         if (!this.selectedText.length) {
           selection.collapseToStart();
           return;
         }
 
         this.cache = this._extractFromRange(range, offset);
-
-        let tap = { x: json.x - this.cache.offset.x, y: json.y - this.cache.offset.y };
-        pointInSelection = (tap.x > this.cache.rect.left && tap.x < this.cache.rect.right) && (tap.y > this.cache.rect.top && tap.y < this.cache.rect.bottom);
-        if (!pointInSelection) {
-          selection.collapseToStart();
-          return;
-        }
-
         this.contentWindow = contentWindow;
 
         sendAsyncMessage("Browser:SelectionRange", this.cache);
         break;
       }
 
       case "Browser:SelectionEnd": {
         let tap = { x: json.x - this.cache.offset.x, y: json.y - this.cache.offset.y };