Bug 1239992 - Focus input field if text is not selected in webconsole output;r=linclark draft
authorBrian Grinstead <bgrinstead@mozilla.com>
Mon, 28 Mar 2016 16:54:38 -0700
changeset 345354 7a36923b88f623a556c345fbe96f233e715215c2
parent 345350 2572bf0929df26a694f58cc8765da73abea0f655
child 517164 a5e9bca1792404397e1101dc1784d29b0f14e534
push id14058
push userbgrinstead@mozilla.com
push dateMon, 28 Mar 2016 23:54:48 +0000
reviewerslinclark
bugs1239992
milestone48.0a1
Bug 1239992 - Focus input field if text is not selected in webconsole output;r=linclark MozReview-Commit-ID: DdXflTqtGko
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),
     });
@@ -2629,49 +2641,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.