Bug 1239992 - Focus input field if text is not selected in webconsole output;r=linclark
authorBrian Grinstead <bgrinstead@mozilla.com>
Wed, 30 Mar 2016 10:10:22 -0700
changeset 290900 e14db462d31d566570e3bece66d5380f7b1ad400
parent 290899 1b9a489995479fb498c61857cc9311d81a88257e
child 290901 09f42355aa061bada9ab92056215d9cdae86a220
push id19656
push usergwagner@mozilla.com
push dateMon, 04 Apr 2016 13:43:23 +0000
treeherderb2g-inbound@e99061fde28a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslinclark
bugs1239992
milestone48.0a1
Bug 1239992 - Focus input field if text is not selected in webconsole output;r=linclark MozReview-Commit-ID: 2MsIap7Rj4P
devtools/client/webconsole/test/browser_console_click_focus.js
devtools/client/webconsole/webconsole.js
--- a/devtools/client/webconsole/test/browser_console_click_focus.js
+++ b/devtools/client/webconsole/test/browser_console_click_focus.js
@@ -25,32 +25,34 @@ add_task(function*() {
 
   let msg = [...result.matched][0];
   let outputItem = msg.querySelector(".message-body");
   ok(outputItem, "found a logged message");
 
   let inputNode = hud.jsterm.inputNode;
   ok(inputNode.getAttribute("focused"), "input node is focused, first");
 
-  let lostFocus = () => {
-    inputNode.removeEventListener("blur", lostFocus);
-    info("input node lost focus");
-  };
+  yield waitForBlurredInput(inputNode);
+
+  EventUtils.sendMouseEvent({type: "click"}, hud.outputNode);
+  ok(inputNode.getAttribute("focused"), "input node is focused, second time");
 
-  inputNode.addEventListener("blur", lostFocus);
+  yield waitForBlurredInput(inputNode);
 
-  document.getElementById("urlbar").click();
-
-  ok(!inputNode.getAttribute("focused"), "input node is not focused");
+  info("Setting a text selection and making sure a click does not re-focus")
+  let selection = hud.iframeWindow.getSelection();
+  selection.selectAllChildren(outputItem);
 
   EventUtils.sendMouseEvent({type: "click"}, hud.outputNode);
-
-  ok(inputNode.getAttribute("focused"), "input node is focused, second time");
-
-  // test click-drags are not focusing the input element.
-  EventUtils.sendMouseEvent({type: "mousedown", clientX: 3, clientY: 4},
-    outputItem);
-  EventUtils.sendMouseEvent({type: "click", clientX: 15, clientY: 5},
-    outputItem);
-
-  todo(!inputNode.getAttribute("focused"), "input node is not focused after drag");
+  ok(!inputNode.getAttribute("focused"), "input node is not focused after drag");
 });
 
+function waitForBlurredInput(inputNode) {
+  return new Promise(resolve => {
+    let lostFocus = () => {
+      inputNode.removeEventListener("blur", lostFocus);
+      ok(!inputNode.getAttribute("focused"), "input node is not focused");
+      resolve();
+    };
+    inputNode.addEventListener("blur", lostFocus);
+    document.getElementById("urlbar").click();
+  });
+}
--- a/devtools/client/webconsole/webconsole.js
+++ b/devtools/client/webconsole/webconsole.js
@@ -569,25 +569,37 @@ WebConsoleFrame.prototype = {
     this.jsterm.on("sidebar-closed", this.resize);
 
     let toolbox = gDevTools.getToolbox(this.owner.target);
     if (toolbox) {
       toolbox.on("webconsole-selected", this._onPanelSelected);
     }
 
     /*
-     * Focus input line whenever the output area is clicked.
-     * Reusing _addMEssageLinkCallback since it correctly filters
-     * drag and select events.
+     * Focus the input line whenever the output area is clicked.
      */
-    this._addFocusCallback(this.outputNode, (evt) => {
-      if ((evt.target.nodeName.toLowerCase() != "a") &&
-          (evt.target.parentNode.nodeName.toLowerCase() != "a")) {
-        this.jsterm.focus();
+    this.outputWrapper.addEventListener("click", (event) => {
+      // Do not focus on middle/right-click or 2+ clicks.
+      if (event.detail !== 1 || event.button !== 0) {
+        return;
       }
+
+      // Do not focus if something is selected
+      let selection = this.window.getSelection();
+      if (selection && !selection.isCollapsed) {
+        return;
+      }
+
+      // Do not focus if a link was clicked
+      if (event.target.nodeName.toLowerCase() === "a" ||
+          event.target.parentNode.nodeName.toLowerCase() === "a") {
+        return;
+      }
+
+      this.jsterm.focus();
     });
 
     // Toggle the timestamp on preference change
     gDevTools.on("pref-changed", this._onToolboxPrefChanged);
     this._onToolboxPrefChanged("pref-changed", {
       pref: PREF_MESSAGE_TIMESTAMP,
       newValue: Services.prefs.getBoolPref(PREF_MESSAGE_TIMESTAMP),
     });
@@ -2631,49 +2643,16 @@ WebConsoleFrame.prototype = {
       }
 
       this._startX = this._startY = undefined;
 
       callback.call(this, event);
     }, false);
   },
 
-  _addFocusCallback: function(node, callback) {
-    node.addEventListener("mousedown", (event) => {
-      this._mousedown = true;
-      this._startX = event.clientX;
-      this._startY = event.clientY;
-    }, false);
-
-    node.addEventListener("click", (event) => {
-      let mousedown = this._mousedown;
-      this._mousedown = false;
-
-      // Do not allow middle/right-click or 2+ clicks.
-      if (event.detail != 1 || event.button != 0) {
-        return;
-      }
-
-      // If this event started with a mousedown event and it ends at a different
-      // location, we consider this text selection.
-      // Add a fuzz modifier of two pixels in any direction to account for
-      // sloppy clicking.
-      if (mousedown &&
-          (Math.abs(event.clientX - this._startX) >= 2) &&
-          (Math.abs(event.clientY - this._startY) >= 1)) {
-        this._startX = this._startY = undefined;
-        return;
-      }
-
-      this._startX = this._startY = undefined;
-
-      callback.call(this, event);
-    }, false);
-  },
-
   /**
    * Handler for the pref-changed event coming from the toolbox.
    * Currently this function only handles the timestamps preferences.
    *
    * @private
    * @param object event
    *        This parameter is a string that holds the event name
    *        pref-changed in this case.