diff --git a/browser/components/search/test/browser_searchbar_openpopup.js b/browser/components/search/test/browser_searchbar_openpopup.js
index 8287f0a7bb19..ddbf37238ed2 100644
--- a/browser/components/search/test/browser_searchbar_openpopup.js
+++ b/browser/components/search/test/browser_searchbar_openpopup.js
@@ -14,14 +14,25 @@ const utils = window.QueryInterface(Ci.nsIInterfaceRequestor)
.getInterface(Ci.nsIDOMWindowUtils);
const scale = utils.screenPixelsPerCSSPixel;
-function synthesizeNativeMouseClick(aElement) {
+function* synthesizeNativeMouseClick(aElement) {
let rect = aElement.getBoundingClientRect();
let win = aElement.ownerDocument.defaultView;
let x = win.mozInnerScreenX + (rect.left + rect.right) / 2;
let y = win.mozInnerScreenY + (rect.top + rect.bottom) / 2;
+
+ // Wait for the mouseup event to occur before continuing.
+ return new Promise((resolve, reject) => {
+ function eventOccurred(e)
+ {
+ aElement.removeEventListener("mouseup", eventOccurred, true);
+ resolve();
+ }
- utils.sendNativeMouseEvent(x * scale, y * scale, mouseDown, 0, null);
- utils.sendNativeMouseEvent(x * scale, y * scale, mouseUp, 0, null);
+ aElement.addEventListener("mouseup", eventOccurred, true);
+
+ utils.sendNativeMouseEvent(x * scale, y * scale, mouseDown, 0, null);
+ utils.sendNativeMouseEvent(x * scale, y * scale, mouseUp, 0, null);
+ });
}
function promiseNewEngine(basename) {
@@ -113,7 +124,7 @@ add_task(function* open_empty() {
let clickPromise = promiseEvent(searchIcon, "click");
info("Hiding popup");
- synthesizeNativeMouseClick(searchIcon);
+ yield synthesizeNativeMouseClick(searchIcon);
yield promise;
is(textbox.mController.searchString, "", "Should not have started to search for the new text");
@@ -362,10 +373,49 @@ add_task(function* dont_consume_clicks() {
is(textbox.selectionEnd, 3, "Should have selected all of the text");
promise = promiseEvent(searchPopup, "popuphidden");
- synthesizeNativeMouseClick(gURLBar);
+ yield synthesizeNativeMouseClick(gURLBar);
yield promise;
is(Services.focus.focusedElement, gURLBar.inputField, "Should have focused the URL bar");
textbox.value = "";
});
+
+// Moving the caret using the cursor keys should not close the popup.
+add_task(function* dont_rollup_oncaretmove() {
+ gURLBar.focus();
+ textbox.value = "long text";
+
+ let promise = promiseEvent(searchPopup, "popupshown");
+ EventUtils.synthesizeMouseAtCenter(textbox, {});
+ yield promise;
+
+ // Deselect the text
+ EventUtils.synthesizeKey("VK_RIGHT", {});
+ is(textbox.selectionStart, 9, "Should have moved the caret (selectionStart after deselect right)");
+ is(textbox.selectionEnd, 9, "Should have moved the caret (selectionEnd after deselect right)");
+ is(searchPopup.state, "open", "Popup should still be open");
+
+ EventUtils.synthesizeKey("VK_LEFT", {});
+ is(textbox.selectionStart, 8, "Should have moved the caret (selectionStart after left)");
+ is(textbox.selectionEnd, 8, "Should have moved the caret (selectionEnd after left)");
+ is(searchPopup.state, "open", "Popup should still be open");
+
+ EventUtils.synthesizeKey("VK_RIGHT", {});
+ is(textbox.selectionStart, 9, "Should have moved the caret (selectionStart after right)");
+ is(textbox.selectionEnd, 9, "Should have moved the caret (selectionEnd after right)");
+ is(searchPopup.state, "open", "Popup should still be open");
+
+ if (navigator.platform.indexOf("Mac") == -1) {
+ EventUtils.synthesizeKey("VK_HOME", {});
+ is(textbox.selectionStart, 0, "Should have moved the caret (selectionStart after home)");
+ is(textbox.selectionEnd, 0, "Should have moved the caret (selectionEnd after home)");
+ is(searchPopup.state, "open", "Popup should still be open");
+ }
+
+ // Close the popup again
+ promise = promiseEvent(searchPopup, "popuphidden");
+ EventUtils.synthesizeKey("VK_ESCAPE", {});
+ yield promise;
+});
+
diff --git a/toolkit/components/autocomplete/nsAutoCompleteController.cpp b/toolkit/components/autocomplete/nsAutoCompleteController.cpp
index a86ef114eea7..12f9718d1650 100644
--- a/toolkit/components/autocomplete/nsAutoCompleteController.cpp
+++ b/toolkit/components/autocomplete/nsAutoCompleteController.cpp
@@ -529,9 +529,14 @@ nsAutoCompleteController::HandleKeyNavigation(uint32_t aKey, bool *_retval)
}
}
}
- // Close the pop-up even if nothing was selected
- ClearSearchTimer();
- ClosePopup();
+
+ bool noRollup;
+ input->GetNoRollupOnCaretMove(&noRollup);
+ if (!noRollup) {
+ // Close the pop-up even if nothing was selected
+ ClearSearchTimer();
+ ClosePopup();
+ }
}
// Update last-searched string to the current input, since the input may
// have changed. Without this, subsequent backspaces look like text
diff --git a/toolkit/components/autocomplete/nsIAutoCompleteInput.idl b/toolkit/components/autocomplete/nsIAutoCompleteInput.idl
index 487760c48ac3..0cd5cdc3cee5 100644
--- a/toolkit/components/autocomplete/nsIAutoCompleteInput.idl
+++ b/toolkit/components/autocomplete/nsIAutoCompleteInput.idl
@@ -7,7 +7,7 @@
interface nsIAutoCompletePopup;
-[scriptable, uuid(fadb2bb9-3e2e-4ca0-b0e0-0982b8dda9dc)]
+[scriptable, uuid(B068E70F-F82C-4C12-AD87-82E271C5C180)]
interface nsIAutoCompleteInput : nsISupports
{
/*
@@ -147,4 +147,9 @@ interface nsIAutoCompleteInput : nsISupports
* (such as a history database).
*/
readonly attribute boolean inPrivateContext;
+
+ /*
+ * Don't rollup the popup when the caret is moved.
+ */
+ readonly attribute boolean noRollupOnCaretMove;
};
diff --git a/toolkit/components/satchel/nsFormFillController.cpp b/toolkit/components/satchel/nsFormFillController.cpp
index 38224e8e0409..43b529eaec13 100644
--- a/toolkit/components/satchel/nsFormFillController.cpp
+++ b/toolkit/components/satchel/nsFormFillController.cpp
@@ -619,6 +619,12 @@ nsFormFillController::GetInPrivateContext(bool *aInPrivateContext)
return NS_OK;
}
+NS_IMETHODIMP
+nsFormFillController::GetNoRollupOnCaretMove(bool *aNoRollupOnCaretMove)
+{
+ *aNoRollupOnCaretMove = false;
+ return NS_OK;
+}
////////////////////////////////////////////////////////////////////////
//// nsIAutoCompleteSearch
diff --git a/toolkit/content/widgets/autocomplete.xml b/toolkit/content/widgets/autocomplete.xml
index 4a7e71091ad8..fe8f6176673f 100644
--- a/toolkit/content/widgets/autocomplete.xml
+++ b/toolkit/content/widgets/autocomplete.xml
@@ -157,6 +157,9 @@
+
+
14