Bug 885294 - Immediate script selection from debugger search box is really janky and loses selection if you don't find anything, r=past
authorVictor Porof <vporof@mozilla.com>
Wed, 08 Jan 2014 10:48:32 +0200
changeset 162448 7f48035ecdb486544b4ba672429725a67ee5e1e6
parent 162447 96e869c388d70ba356c21706f2ceb6be8f7bfff7
child 162449 b524fc6b21b9da837c0ee6f0c91ae3f0b86e37bb
push id4229
push uservporof@mozilla.com
push dateWed, 08 Jan 2014 08:49:33 +0000
treeherderfx-team@7f48035ecdb4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspast
bugs885294
milestone29.0a1
Bug 885294 - Immediate script selection from debugger search box is really janky and loses selection if you don't find anything, r=past
browser/devtools/debugger/debugger-toolbar.js
browser/devtools/debugger/debugger-view.js
browser/devtools/debugger/test/browser.ini
browser/devtools/debugger/test/browser_dbg_search-popup-jank.js
browser/devtools/debugger/test/head.js
--- a/browser/devtools/debugger/debugger-toolbar.js
+++ b/browser/devtools/debugger/debugger-toolbar.js
@@ -863,17 +863,16 @@ FilterView.prototype = {
    * @param string aToken
    *        The source token to find.
    */
   _performTokenSearch: function(aToken) {
     // Make sure we're actually searching for a valid token.
     if (!aToken) {
       return;
     }
-
     DebuggerView.editor.find(aToken);
   },
 
   /**
    * The click listener for the search container.
    */
   _onClick: function() {
     // If there's some text in the searchbox, displaying a panel would
@@ -995,16 +994,19 @@ FilterView.prototype = {
     // a new function search immediately, or clear it.
     if (isFunctionSearch) {
       let targetView = DebuggerView.FilteredFunctions;
       if (!isReturnKey) {
         targetView[actionToPerform]();
       } else if (targetView.hidden) {
         targetView.scheduleSearch(args[0], 0);
       } else {
+        if (!targetView.selectedItem) {
+          targetView.selectedIndex = 0;
+        }
         this.clearSearch();
       }
       return;
     }
 
     // Perform a new variable search immediately.
     if (isVariableSearch) {
       let targetView = DebuggerView.Variables;
@@ -1018,16 +1020,19 @@ FilterView.prototype = {
     // a new file search immediately, or clear it.
     if (isFileOnlySearch) {
       let targetView = DebuggerView.FilteredSources;
       if (!isReturnKey) {
         targetView[actionToPerform]();
       } else if (targetView.hidden) {
         targetView.scheduleSearch(args[0], 0);
       } else {
+        if (!targetView.selectedItem) {
+          targetView.selectedIndex = 0;
+        }
         this.clearSearch();
       }
       return;
     }
 
     // Jump to the next/previous instance of the currently searched token.
     if (isTokenSearch) {
       let methods = { selectNext: "findNext", selectPrev: "findPrev" };
@@ -1253,18 +1258,21 @@ FilteredSourcesView.prototype = Heritage
       this.push([itemView], {
         index: -1, /* specifies on which position should the item be appended */
         attachment: {
           url: item.value
         }
       });
     }
 
-    // Select the first entry in this container.
-    this.selectedIndex = 0;
+    // There's at least one item displayed in this container. Don't select it
+    // automatically if not forced (by tests) or in tandem with an operator.
+    if (this._autoSelectFirstItem || DebuggerView.Filtering.searchOperator) {
+      this.selectedIndex = 0;
+    }
     this.hidden = false;
 
     // Signal that file search matches were found and displayed.
     window.emit(EVENTS.FILE_SEARCH_MATCH_FOUND);
   },
 
   /**
    * The click listener for this container.
@@ -1454,18 +1462,21 @@ FilteredFunctionsView.prototype = Herita
 
       // Append a function item to this container for each match.
       this.push([itemView], {
         index: -1, /* specifies on which position should the item be appended */
         attachment: item
       });
     }
 
-    // Select the first entry in this container.
-    this.selectedIndex = 0;
+    // There's at least one item displayed in this container. Don't select it
+    // automatically if not forced (by tests).
+    if (this._autoSelectFirstItem) {
+      this.selectedIndex = 0;
+    }
     this.hidden = false;
 
     // Signal that function search matches were found and displayed.
     window.emit(EVENTS.FUNCTION_SEARCH_MATCH_FOUND);
   },
 
   /**
    * The click listener for this container.
--- a/browser/devtools/debugger/debugger-view.js
+++ b/browser/devtools/debugger/debugger-view.js
@@ -685,16 +685,18 @@ ResultsPanelContainer.prototype = Herita
         this._panel.className = "results-panel";
         this._panel.setAttribute("level", "top");
         this._panel.setAttribute("noautofocus", "true");
         this._panel.setAttribute("consumeoutsideclicks", "false");
         document.documentElement.appendChild(this._panel);
       }
       if (!this.widget) {
         this.widget = new SimpleListWidget(this._panel);
+        this.autoFocusOnFirstItem = false;
+        this.autoFocusOnSelection = false;
         this.maintainSelectionVisible = false;
       }
     }
     // Cleanup the anchor and remove the previously created panel.
     else {
       this._panel.remove();
       this._panel = null;
       this.widget = null;
--- a/browser/devtools/debugger/test/browser.ini
+++ b/browser/devtools/debugger/test/browser.ini
@@ -170,16 +170,17 @@ support-files =
 [browser_dbg_search-basic-03.js]
 [browser_dbg_search-basic-04.js]
 [browser_dbg_search-global-01.js]
 [browser_dbg_search-global-02.js]
 [browser_dbg_search-global-03.js]
 [browser_dbg_search-global-04.js]
 [browser_dbg_search-global-05.js]
 [browser_dbg_search-global-06.js]
+[browser_dbg_search-popup-jank.js]
 [browser_dbg_search-sources-01.js]
 [browser_dbg_search-sources-02.js]
 [browser_dbg_search-sources-03.js]
 [browser_dbg_search-symbols.js]
 [browser_dbg_searchbox-help-popup-01.js]
 [browser_dbg_searchbox-help-popup-02.js]
 [browser_dbg_searchbox-parse.js]
 [browser_dbg_source-maps-01.js]
new file mode 100644
--- /dev/null
+++ b/browser/devtools/debugger/test/browser_dbg_search-popup-jank.js
@@ -0,0 +1,118 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+/**
+ * Tests that sources aren't selected by default when finding a match.
+ */
+
+const TAB_URL = EXAMPLE_URL + "doc_editor-mode.html";
+
+let gTab, gDebuggee, gPanel, gDebugger;
+let gSearchBox;
+
+function test() {
+  initDebugger(TAB_URL).then(([aTab, aDebuggee, aPanel]) => {
+    gTab = aTab;
+    gDebuggee = aDebuggee;
+    gPanel = aPanel;
+    gDebugger = gPanel.panelWin;
+    gSearchBox = gDebugger.DebuggerView.Filtering._searchbox;
+
+    gDebugger.DebuggerView.FilteredSources._autoSelectFirstItem = false;
+    gDebugger.DebuggerView.FilteredFunctions._autoSelectFirstItem = false;
+
+    waitForSourceShown(gPanel, "-01.js")
+      .then(superGenericFileSearch)
+      .then(() => ensureSourceIs(aPanel, "-01.js"))
+      .then(() => ensureCaretAt(aPanel, 1))
+
+      .then(superAccurateFileSearch)
+      .then(() => ensureSourceIs(aPanel, "-01.js"))
+      .then(() => ensureCaretAt(aPanel, 1))
+      .then(() => pressKeyToHide("RETURN"))
+      .then(() => ensureSourceIs(aPanel, "code_test-editor-mode", true))
+      .then(() => ensureCaretAt(aPanel, 1))
+
+      .then(superGenericFileSearch)
+      .then(() => ensureSourceIs(aPanel, "code_test-editor-mode"))
+      .then(() => ensureCaretAt(aPanel, 1))
+      .then(() => pressKey("UP"))
+      .then(() => ensureSourceIs(aPanel, "doc_editor-mode", true))
+      .then(() => ensureCaretAt(aPanel, 1))
+      .then(() => pressKeyToHide("RETURN"))
+      .then(() => ensureSourceIs(aPanel, "doc_editor-mode"))
+      .then(() => ensureCaretAt(aPanel, 1))
+
+      .then(superAccurateFileSearch)
+      .then(() => ensureSourceIs(aPanel, "doc_editor-mode"))
+      .then(() => ensureCaretAt(aPanel, 1))
+      .then(() => typeText(gSearchBox, ":"))
+      .then(() => ensureSourceIs(aPanel, "code_test-editor-mode", true))
+      .then(() => ensureCaretAt(aPanel, 1))
+      .then(() => typeText(gSearchBox, "5"))
+      .then(() => ensureSourceIs(aPanel, "code_test-editor-mode"))
+      .then(() => ensureCaretAt(aPanel, 5))
+      .then(() => pressKey("DOWN"))
+      .then(() => ensureSourceIs(aPanel, "code_test-editor-mode"))
+      .then(() => ensureCaretAt(aPanel, 6))
+
+      .then(superGenericFunctionSearch)
+      .then(() => ensureSourceIs(aPanel, "code_test-editor-mode"))
+      .then(() => ensureCaretAt(aPanel, 6))
+      .then(() => pressKey("RETURN"))
+      .then(() => ensureSourceIs(aPanel, "code_test-editor-mode"))
+      .then(() => ensureCaretAt(aPanel, 4, 10))
+
+      .then(() => closeDebuggerAndFinish(gPanel))
+      .then(null, aError => {
+        ok(false, "Got an error: " + aError.message + "\n" + aError.stack);
+      });
+  });
+}
+
+function waitForMatchFoundAndResultsShown(aName) {
+  return promise.all([
+    once(gDebugger, "popupshown"),
+    waitForDebuggerEvents(gPanel, gDebugger.EVENTS[aName])
+  ]);
+}
+
+function waitForResultsHidden() {
+  return once(gDebugger, "popuphidden");
+}
+
+function superGenericFunctionSearch() {
+  let finished = waitForMatchFoundAndResultsShown("FUNCTION_SEARCH_MATCH_FOUND");
+  setText(gSearchBox, "@");
+  return finished;
+}
+
+function superGenericFileSearch() {
+  let finished = waitForMatchFoundAndResultsShown("FILE_SEARCH_MATCH_FOUND");
+  setText(gSearchBox, ".");
+  return finished;
+}
+
+function superAccurateFileSearch() {
+  let finished = waitForMatchFoundAndResultsShown("FILE_SEARCH_MATCH_FOUND");
+  setText(gSearchBox, "editor");
+  return finished;
+}
+
+function pressKey(aKey) {
+  EventUtils.sendKey(aKey, gDebugger);
+}
+
+function pressKeyToHide(aKey) {
+  let finished = waitForResultsHidden();
+  EventUtils.sendKey(aKey, gDebugger);
+  return finished;
+}
+
+registerCleanupFunction(function() {
+  gTab = null;
+  gDebuggee = null;
+  gPanel = null;
+  gDebugger = null;
+  gSearchBox = null;
+});
--- a/browser/devtools/debugger/test/head.js
+++ b/browser/devtools/debugger/test/head.js
@@ -501,19 +501,21 @@ function initChromeDebugger(aOnClose) {
     deferred.resolve(aProcess);
   });
 
   return deferred.promise;
 }
 
 function prepareDebugger(aDebugger) {
   if ("target" in aDebugger) {
-    let variables = aDebugger.panelWin.DebuggerView.Variables;
-    variables.lazyEmpty = false;
-    variables.lazySearch = false;
+    let view = aDebugger.panelWin.DebuggerView;
+    view.Variables.lazyEmpty = false;
+    view.Variables.lazySearch = false;
+    view.FilteredSources._autoSelectFirstItem = true;
+    view.FilteredFunctions._autoSelectFirstItem = true;
   } else {
     // Nothing to do here yet.
   }
 }
 
 function teardown(aPanel, aFlags = {}) {
   info("Destroying the specified debugger.");