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