Bug 1427350 - Part 1 - Use "autocomplete-rich-result-popup" instead of "autocomplete-result-popup" for the search bar. r=mak
MozReview-Commit-ID: AO926Wmhkbm
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -138,17 +138,20 @@
id="PopupAutoComplete"
noautofocus="true"
hidden="true"
overflowpadding="4"
norolluponanchor="true"
nomaxresults="true" />
<!-- for search with one-off buttons -->
- <panel type="autocomplete" id="PopupSearchAutoComplete" noautofocus="true" hidden="true"/>
+ <panel type="autocomplete-richlistbox"
+ id="PopupSearchAutoComplete"
+ noautofocus="true"
+ hidden="true" />
<!-- for url bar autocomplete -->
<panel type="autocomplete-richlistbox"
id="PopupAutoCompleteRichResult"
noautofocus="true"
hidden="true"
flip="none"
level="parent"
--- a/browser/components/search/content/search.xml
+++ b/browser/components/search/content/search.xml
@@ -737,33 +737,36 @@
popup.hidden = false;
// Don't roll up on mouse click in the anchor for the search UI.
if (popup.id == "PopupSearchAutoComplete") {
popup.setAttribute("norolluponanchor", "true");
}
popup.mInput = this;
- popup.view = this.controller.QueryInterface(Ci.nsITreeView);
- popup.invalidate();
+ // clear any previous selection, see bugs 400671 and 488357
+ popup.selectedIndex = -1;
popup.showCommentColumn = this.showCommentColumn;
popup.showImageColumn = this.showImageColumn;
document.popupNode = null;
const isRTL = getComputedStyle(this, "").direction == "rtl";
var outerRect = this.getBoundingClientRect();
var innerRect = this.inputField.getBoundingClientRect();
let width = isRTL ?
innerRect.right - outerRect.left :
outerRect.right - innerRect.left;
popup.setAttribute("width", width > 100 ? width : 100);
+ // invalidate() depends on the width attribute
+ popup._invalidate();
+
var yOffset = outerRect.bottom - innerRect.bottom;
popup.openPopup(this.inputField, "after_start", 0, yOffset, false, false);
}
]]></body>
</method>
<method name="openSearch">
<body>
@@ -834,18 +837,18 @@
return;
// accel + up/down changes the default engine and shouldn't affect
// the selection on the one-off buttons.
if (aEvent.getModifierState("Accel"))
return;
let suggestionsHidden =
- popup.tree.getAttribute("collapsed") == "true";
- let numItems = suggestionsHidden ? 0 : this.popup.view.rowCount;
+ popup.richlistbox.getAttribute("collapsed") == "true";
+ let numItems = suggestionsHidden ? 0 : this.popup._matchCount;
this.popup.oneOffButtons.handleKeyPress(aEvent, numItems, true);
]]></body>
</method>
<!-- nsIController -->
<field name="searchbarController" readonly="true"><![CDATA[({
_self: this,
supportsCommand(aCommand) {
@@ -922,36 +925,29 @@
document.getBindingParent(this).openSuggestionsPanel();
}
]]>
</handler>
</handlers>
</binding>
- <binding id="browser-search-autocomplete-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-result-popup">
+ <binding id="browser-search-autocomplete-result-popup" extends="chrome://global/content/bindings/autocomplete.xml#autocomplete-rich-result-popup">
<resources>
<stylesheet src="chrome://browser/content/search/searchbarBindings.css"/>
<stylesheet src="chrome://browser/skin/searchbar.css"/>
</resources>
<content ignorekeys="true" level="top" consumeoutsideclicks="never">
<xul:hbox anonid="searchbar-engine" xbl:inherits="showonlysettings"
class="search-panel-header search-panel-current-engine">
<xul:image class="searchbar-engine-image" xbl:inherits="src"/>
<xul:label anonid="searchbar-engine-name" flex="1" crop="end"
role="presentation"/>
</xul:hbox>
- <xul:tree anonid="tree" flex="1"
- class="autocomplete-tree plain search-panel-tree"
- hidecolumnpicker="true" seltype="single">
- <xul:treecols anonid="treecols">
- <xul:treecol id="treecolAutoCompleteValue" class="autocomplete-treecol" flex="1" overflow="true"/>
- </xul:treecols>
- <xul:treechildren class="autocomplete-treebody searchbar-treebody" noSelectOnMouseMove="true"/>
- </xul:tree>
+ <xul:richlistbox anonid="richlistbox" class="autocomplete-richlistbox search-panel-tree" flex="1"/>
<xul:vbox anonid="search-one-off-buttons" class="search-one-offs"/>
</content>
<implementation>
<method name="openAutocompletePopup">
<parameter name="aInput"/>
<parameter name="aElement"/>
<body><![CDATA[
// initially the panel is hidden
@@ -971,17 +967,17 @@
return;
var controller = this.view.QueryInterface(Components.interfaces.nsIAutoCompleteController);
var searchBar = BrowserSearch.searchBar;
var popupForSearchBar = searchBar && searchBar.textbox == this.mInput;
if (popupForSearchBar) {
searchBar.telemetrySearchDetails = {
- index: controller.selection.currentIndex,
+ index: this.selectedIndex,
kind: "mouse"
};
}
// Check for unmodified left-click, and use default behavior
if (aEvent.button == 0 && !aEvent.shiftKey && !aEvent.ctrlKey &&
!aEvent.altKey && !aEvent.metaKey) {
controller.handleEnter(true, aEvent);
@@ -1109,24 +1105,24 @@
// glass icon has been clicked if the text field is empty.
let searchbar = document.getElementById("searchbar");
if (searchbar.hasAttribute("showonlysettings")) {
searchbar.removeAttribute("showonlysettings");
this.setAttribute("showonlysettings", "true");
// Setting this with an xbl-inherited attribute gets overridden the
// second time the user clicks the glass icon for some reason...
- this.tree.collapsed = true;
+ this.richlistbox.collapsed = true;
} else {
this.removeAttribute("showonlysettings");
- // Uncollapse as long as we have a tree with a view which has >= 1 row.
+ // Uncollapse as long as we have a view which has >= 1 row.
// The autocomplete binding itself will take care of uncollapsing later,
// if we currently have no rows but end up having some in the future
// when the search string changes
- this.tree.collapsed = !this.tree.view || !this.tree.view.rowCount;
+ this.richlistbox.collapsed = (this._matchCount == 0);
}
// Show the current default engine in the top header of the panel.
this.updateHeader();
]]></handler>
<handler event="popuphiding"><![CDATA[
this._isHiding = true;
--- a/browser/components/search/test/browser_426329.js
+++ b/browser/components/search/test/browser_426329.js
@@ -28,26 +28,20 @@ function simulateClick(aEvent, aTarget)
function checkMenuEntries(expectedValues) {
var actualValues = getMenuEntries();
is(actualValues.length, expectedValues.length, "Checking length of expected menu");
for (var i = 0; i < expectedValues.length; i++)
is(actualValues[i], expectedValues[i], "Checking menu entry #" + i);
}
function getMenuEntries() {
- var entries = [];
- var autocompleteMenu = searchBar.textbox.popup;
// Could perhaps pull values directly from the controller, but it seems
- // more reliable to test the values that are actually in the tree?
- var column = autocompleteMenu.tree.columns[0];
- var numRows = autocompleteMenu.tree.view.rowCount;
- for (var i = 0; i < numRows; i++) {
- entries.push(autocompleteMenu.tree.view.getValueAt(i, column));
- }
- return entries;
+ // more reliable to test the values that are actually in the richlistbox?
+ return Array.map(searchBar.textbox.popup.richlistbox.children,
+ item => item.getAttribute("ac-value"));
}
function countEntries(name, value) {
return new Promise(resolve => {
let count = 0;
let obj = name && value ? {fieldname: name, value} : {};
FormHistory.count(obj,
{ handleResult(result) { count = result; },
--- a/browser/components/search/test/browser_private_search_perwindowpb.js
+++ b/browser/components/search/test/browser_private_search_perwindowpb.js
@@ -58,19 +58,13 @@ add_task(async function() {
searchBar.value = "";
windowsToClose.forEach(function(win) {
win.close();
});
});
function getMenuEntries(searchBar) {
- let entries = [];
- let autocompleteMenu = searchBar.textbox.popup;
// Could perhaps pull values directly from the controller, but it seems
- // more reliable to test the values that are actually in the tree?
- let column = autocompleteMenu.tree.columns[0];
- let numRows = autocompleteMenu.tree.view.rowCount;
- for (let i = 0; i < numRows; i++) {
- entries.push(autocompleteMenu.tree.view.getValueAt(i, column));
- }
- return entries;
+ // more reliable to test the values that are actually in the richlistbox?
+ return Array.map(searchBar.textbox.popup.richlistbox.children,
+ item => item.getAttribute("ac-value"));
}
--- a/browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
+++ b/browser/modules/test/browser/browser_UsageTelemetry_searchbar.js
@@ -35,37 +35,23 @@ let searchInSearchbar = async function(i
/**
* Click one of the entries in the search suggestion popup.
*
* @param {String} entryName
* The name of the elemet to click on.
*/
function clickSearchbarSuggestion(entryName) {
- let popup = BrowserSearch.searchBar.textbox.popup;
- let column = popup.tree.columns[0];
-
- for (let rowID = 0; rowID < popup.tree.view.rowCount; rowID++) {
- const suggestion = popup.tree.view.getValueAt(rowID, column);
- if (suggestion !== entryName) {
- continue;
- }
+ let richlistbox = BrowserSearch.searchBar.textbox.popup.richlistbox;
+ let richlistitem = Array.prototype.find.call(richlistbox.children,
+ item => item.getAttribute("ac-value") == entryName);
- // Make sure the suggestion is visible, just in case.
- let tbo = popup.tree.treeBoxObject;
- tbo.ensureRowIsVisible(rowID);
- // Calculate the click coordinates.
- let rect = tbo.getCoordsForCellItem(rowID, column, "text");
- let x = rect.x + rect.width / 2;
- let y = rect.y + rect.height / 2;
- // Simulate the click.
- EventUtils.synthesizeMouse(popup.tree.body, x, y, {},
- popup.tree.ownerGlobal);
- break;
- }
+ // Make sure the suggestion is visible and simulate the click.
+ richlistbox.ensureElementIsVisible(richlistitem);
+ EventUtils.synthesizeMouseAtCenter(richlistitem, {});
}
add_task(async function setup() {
await SpecialPowers.pushPrefEnv({ set: [
["browser.search.widget.inNavBar", true],
]});
// Create two new search engines. Mark one as the default engine, so
--- a/browser/themes/linux/browser.css
+++ b/browser/themes/linux/browser.css
@@ -454,30 +454,16 @@ html|span.ac-emphasize-text-url {
fill: #b2b2b2;
}
.ac-type-icon[type=switchtab][selected],
.ac-type-icon[type=remotetab][selected] {
fill: white;
}
-.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
- color: GrayText;
-}
-
-.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
-.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment) {
- color: GrayText;
- font-size: smaller;
-}
-
-.autocomplete-treebody::-moz-tree-cell(suggesthint) {
- border-top: 1px solid GrayText;
-}
-
/* Bookmarking panel */
#editBookmarkPanelStarIcon {
list-style-image: url("chrome://browser/skin/places/starred48.png");
width: 48px;
height: 48px;
}
#editBookmarkPanelTitle {
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -414,31 +414,16 @@ html|span.ac-emphasize-text-url {
fill: #b2b2b2;
}
.ac-type-icon[type=switchtab][selected],
.ac-type-icon[type=remotetab][selected] {
fill: white;
}
-.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
- color: GrayText;
-}
-
-.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
-.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment)
-{
- color: GrayText;
- font-size: smaller;
-}
-
-.autocomplete-treebody::-moz-tree-cell(suggesthint) {
- border-top: 1px solid GrayText;
-}
-
#BMB_bookmarksPopup[side="top"],
#BMB_bookmarksPopup[side="bottom"] {
margin-left: -26px;
margin-right: -26px;
}
#BMB_bookmarksPopup[side="left"],
#BMB_bookmarksPopup[side="right"] {
--- a/browser/themes/shared/autocomplete.inc.css
+++ b/browser/themes/shared/autocomplete.inc.css
@@ -25,23 +25,21 @@
}
#PopupAutoComplete > richlistbox {
padding: 0;
}
/* Popup states */
-.autocomplete-richlistitem:hover,
-treechildren.searchbar-treebody::-moz-tree-row(hover) {
+.autocomplete-richlistitem:hover {
background-color: var(--arrowpanel-dimmed);
}
-.autocomplete-richlistitem[selected],
-treechildren.searchbar-treebody::-moz-tree-row(selected) {
+.autocomplete-richlistitem[selected] {
background-color: Highlight;
color: HighlightText;
}
/* Login form autocompletion */
#PopupAutoComplete > richlistbox > richlistitem[originaltype="login"] > .ac-site-icon {
display: initial;
list-style-image: url(chrome://browser/skin/notification-icons/login.svg);
--- a/browser/themes/shared/searchbar.inc.css
+++ b/browser/themes/shared/searchbar.inc.css
@@ -193,37 +193,41 @@
}
.addengine-item[type=menu] > .toolbarbutton-menu-dropmarker {
display: -moz-box;
-moz-appearance: menuarrow !important;
list-style-image: none;
}
-.search-panel-tree > .autocomplete-treebody::-moz-tree-cell {
- border-top: none !important;
+.search-panel-tree > .autocomplete-richlistitem {
+ padding: 1px;
}
-.search-panel-tree > .autocomplete-treebody::-moz-tree-image {
- padding-inline-start: 2px;
- padding-inline-end: 2px;
+.search-panel-tree > .autocomplete-richlistitem > .ac-type-icon {
width: 14px;
height: 14px;
}
-.search-panel-tree > .autocomplete-treebody::-moz-tree-image(fromhistory) {
+.search-panel-tree > .autocomplete-richlistitem[originaltype="fromhistory"] > .ac-type-icon {
list-style-image: url("chrome://browser/skin/history.svg");
-moz-context-properties: fill;
fill: graytext;
}
-.search-panel-tree > .autocomplete-treebody::-moz-tree-image(fromhistory, selected) {
+.search-panel-tree > .autocomplete-richlistitem[originaltype="fromhistory"][selected] > .ac-type-icon {
fill: HighlightText;
}
+.search-panel-tree > .autocomplete-richlistitem > .ac-site-icon,
+.search-panel-tree > .autocomplete-richlistitem > .ac-separator,
+.search-panel-tree > .autocomplete-richlistitem > .ac-url {
+ display: none;
+}
+
.search-setting-button {
-moz-appearance: none;
margin: 0;
min-height: 32px;
}
.search-setting-button:hover,
.search-setting-button[selected] {
--- a/browser/themes/shared/urlbar-autocomplete.inc.css
+++ b/browser/themes/shared/urlbar-autocomplete.inc.css
@@ -1,18 +1,14 @@
%if 0
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
%endif
-#treecolAutoCompleteImage {
- max-width: 36px;
-}
-
#PopupAutoCompleteRichResult .autocomplete-richlistbox {
padding: 4px 3px;
}
#PopupAutoCompleteRichResult .autocomplete-richlistitem {
min-height: 30px;
font: message-box;
border-radius: 2px;
--- a/browser/themes/windows/browser.css
+++ b/browser/themes/windows/browser.css
@@ -702,31 +702,16 @@ html|span.ac-emphasize-text-url {
fill: #b2b2b2;
}
.ac-type-icon[type=switchtab][selected],
.ac-type-icon[type=remotetab][selected] {
fill: white;
}
-.autocomplete-treebody::-moz-tree-cell-text(treecolAutoCompleteComment) {
- color: GrayText;
-}
-
-.autocomplete-treebody::-moz-tree-cell-text(suggesthint, treecolAutoCompleteComment),
-.autocomplete-treebody::-moz-tree-cell-text(suggestfirst, treecolAutoCompleteComment)
-{
- color: GrayText;
- font-size: smaller;
-}
-
-.autocomplete-treebody::-moz-tree-cell(suggesthint) {
- border-top: 1px solid GrayText;
-}
-
/* bookmarking panel */
#editBookmarkPanelStarIcon {
list-style-image: url("chrome://browser/skin/places/starred48.png");
width: 48px;
height: 48px;
}
--- a/toolkit/components/places/nsTaggingService.js
+++ b/toolkit/components/places/nsTaggingService.js
@@ -536,23 +536,17 @@ TagAutoCompleteResult.prototype = {
getCommentAt: function PTACR_getCommentAt(index) {
return this._comments[index];
},
/**
* Get the style hint for the result at the given index
*/
getStyleAt: function PTACR_getStyleAt(index) {
- if (!this._comments[index])
- return null; // not a category label, so no special styling
-
- if (index == 0)
- return "suggestfirst"; // category label on first line of results
-
- return "suggesthint"; // category label on any other line of results
+ return null;
},
/**
* Get the image for the result at the given index
*/
getImageAt: function PTACR_getImageAt(index) {
return null;
},