Desc: Clicking in focused textbox should open autocomplete results (as in IE) URL: http://bugzilla.mozilla.org/show_bug.cgi?id=173569#c22 Index: toolkit/components/autocomplete/public/nsIAutoCompleteController.idl =================================================================== RCS file: /cvsroot/mozilla/toolkit/components/autocomplete/public/nsIAutoCompleteController.idl,v retrieving revision 1.5 diff -u -r1.5 nsIAutoCompleteController.idl --- toolkit/components/autocomplete/public/nsIAutoCompleteController.idl 18 Mar 2004 01:52:50 -0000 1.5 +++ toolkit/components/autocomplete/public/nsIAutoCompleteController.idl 24 Apr 2004 20:38:50 -0000 @@ -19,7 +19,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Joe Hewitt (Original Author) + * Joe Hewitt (Original Author) + * Dean Tessman * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -87,7 +88,7 @@ * means of changing the text value, including typing a character, backspacing, deleting, or * pasting in an entirely new value. */ - void handleText(); + void handleText(in boolean aIgnoreSelection); /* * Notify the controller that the user wishes to enter the current text @@ -136,4 +137,9 @@ * Get a the style hint for the result at a given index in the last completed search */ AString getStyleAt(in long index); + + /* + * Set the current search string, but don't start searching + */ + void setSearchString(in AString aSearchString); }; Index: toolkit/components/autocomplete/src/nsAutoCompleteController.cpp =================================================================== RCS file: /cvsroot/mozilla/toolkit/components/autocomplete/src/nsAutoCompleteController.cpp,v retrieving revision 1.16 diff -u -r1.16 nsAutoCompleteController.cpp --- toolkit/components/autocomplete/src/nsAutoCompleteController.cpp 17 Apr 2004 05:53:33 -0000 1.16 +++ toolkit/components/autocomplete/src/nsAutoCompleteController.cpp 24 Apr 2004 20:38:50 -0000 @@ -121,7 +121,7 @@ mInput->GetTextValue(newValue); // Reset all search state members to default values - mSearchString = newValue; + SetSearchString(newValue); mEnterAfterSearch = PR_FALSE; mDefaultIndexCompleted = PR_FALSE; mBackspaced = PR_FALSE; @@ -157,14 +157,14 @@ NS_IMETHODIMP nsAutoCompleteController::StartSearch(const nsAString &aSearchString) { - mSearchString = aSearchString; + SetSearchString(aSearchString); StartSearchTimer(); return NS_OK; } NS_IMETHODIMP -nsAutoCompleteController::HandleText() +nsAutoCompleteController::HandleText(const PRBool aIgnoreSelection) { // Stop current search in case it's async. StopSearch(); @@ -198,7 +198,7 @@ // way when you get a chance. -dwh ClearResults(); - mSearchString = newValue; + SetSearchString(newValue); // Don't search if the value is empty if (newValue.Length() == 0) { @@ -206,14 +206,18 @@ return NS_OK; } - // Kick off the search, but only if the cursor is at the end of the textbox - PRInt32 selectionStart; - mInput->GetSelectionStart(&selectionStart); - PRInt32 selectionEnd; - mInput->GetSelectionEnd(&selectionEnd); - - if (selectionStart == selectionEnd && selectionStart == (PRInt32) mSearchString.Length()) + if (aIgnoreSelection) { StartSearchTimer(); + } else { + // Kick off the search only if the cursor is at the end of the textbox + PRInt32 selectionStart; + mInput->GetSelectionStart(&selectionStart); + PRInt32 selectionEnd; + mInput->GetSelectionEnd(&selectionEnd); + + if (selectionStart == selectionEnd && selectionStart == (PRInt32) mSearchString.Length()) + StartSearchTimer(); + } return NS_OK; } @@ -331,7 +335,7 @@ mInput->GetPopupOpen(&isOpen); if (!isOpen || mRowCount <= 0) { // Nothing left to delete, proceed as normal - HandleText(); + HandleText(PR_FALSE); return NS_OK; } @@ -439,6 +443,14 @@ return NS_OK; } +NS_IMETHODIMP +nsAutoCompleteController::SetSearchString(const nsAString &aSearchString) +{ + mSearchString = aSearchString; + + return NS_OK; +} + //////////////////////////////////////////////////////////////////////// //// nsIAutoCompleteObserver @@ -811,7 +823,7 @@ mInput->GetTimeout(&timeout); mTimer = do_CreateInstance("@mozilla.org/timer;1"); - mTimer->InitWithCallback(this, 0, timeout); + mTimer->InitWithCallback(this, timeout, nsITimer::TYPE_ONE_SHOT); return NS_OK; } @@ -877,7 +889,7 @@ if (!value.IsEmpty()) { mInput->SetTextValue(value); mInput->SelectTextRange(value.Length(), value.Length()); - mSearchString = value; + SetSearchString(value); } ClosePopup(); Index: toolkit/components/satchel/src/nsFormFillController.cpp =================================================================== RCS file: /cvsroot/mozilla/toolkit/components/satchel/src/nsFormFillController.cpp,v retrieving revision 1.26 diff -u -r1.26 nsFormFillController.cpp --- toolkit/components/satchel/src/nsFormFillController.cpp 18 Mar 2004 01:52:51 -0000 1.26 +++ toolkit/components/satchel/src/nsFormFillController.cpp 24 Apr 2004 20:38:50 -0000 @@ -20,7 +20,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Joe Hewitt (Original Author) + * Joe Hewitt (Original Author) + * Dean Tessman * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -66,6 +67,7 @@ #include "nsIDOMDocumentEvent.h" #include "nsIDOMHTMLFormElement.h" #include "nsPasswordManager.h" +#include "nsIDOMMouseEvent.h" NS_INTERFACE_MAP_BEGIN(nsFormFillController) NS_INTERFACE_MAP_ENTRY(nsIFormFillController) @@ -74,6 +76,7 @@ NS_INTERFACE_MAP_ENTRY(nsIDOMFocusListener) NS_INTERFACE_MAP_ENTRY(nsIDOMKeyListener) NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener) + NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFormFillController) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFocusListener) NS_INTERFACE_MAP_END @@ -105,7 +108,7 @@ nsCOMPtr docShell; mDocShells->GetElementAt(i, getter_AddRefs(docShell)); nsCOMPtr domWindow = GetWindowForDocShell(docShell); - RemoveFocusListener(domWindow); + RemoveWindowListeners(domWindow); } } @@ -174,7 +177,7 @@ // Listen for focus events on the domWindow of the docShell nsCOMPtr domWindow = GetWindowForDocShell(aDocShell); - AddFocusListener(domWindow); + AddWindowListeners(domWindow); return NS_OK; } @@ -189,7 +192,7 @@ nsCOMPtr docShell; mDocShells->GetElementAt(index, getter_AddRefs(docShell)); nsCOMPtr domWindow = GetWindowForDocShell(docShell); - RemoveFocusListener(domWindow); + RemoveWindowListeners(domWindow); mDocShells->RemoveElementAt(index); mPopups->RemoveElementAt(index); @@ -576,7 +579,7 @@ // fall through } case nsIDOMKeyEvent::DOM_VK_BACK_SPACE: - mController->HandleText(); + mController->HandleText(PR_FALSE); break; case nsIDOMKeyEvent::DOM_VK_UP: mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_UP, &cancel); @@ -649,15 +652,108 @@ if (mSuppressOnInput) return NS_OK; - return mController->HandleText(); + return mController->HandleText(PR_FALSE); } +//////////////////////////////////////////////////////////////////////// +//// nsIDOMMouseListener + +NS_IMETHODIMP +nsFormFillController::MouseDown(nsIDOMEvent* aMouseEvent) +{ + mIgnoreClick = PR_FALSE; + + nsCOMPtr target; + aMouseEvent->GetTarget(getter_AddRefs(target)); + if (!target) + return NS_OK; + + nsCOMPtr targetInput = do_QueryInterface(target); + if (targetInput && targetInput != mFocusedInput) { + // A new input will be taking focus. Ignore the first click + // so that the popup is not shown. + mIgnoreClick = PR_TRUE; + return NS_OK; + } + + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::MouseUp(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::MouseClick(nsIDOMEvent* aMouseEvent) +{ + if (mIgnoreClick) { + mIgnoreClick = PR_FALSE; + return NS_OK; + } + + if (!mFocusedInput) + return NS_OK; + + nsCOMPtr mouseEvent(do_QueryInterface(aMouseEvent)); + if (!mouseEvent) + return NS_OK; + + PRUint16 button; + mouseEvent->GetButton(&button); + if (button != 0) + return NS_OK; + + PRBool isOpen = PR_FALSE; + GetPopupOpen(&isOpen); + if (isOpen) + return NS_OK; + + nsCOMPtr input; + mController->GetInput(getter_AddRefs(input)); + if (!input) + return NS_OK; + + nsAutoString value; + input->GetTextValue(value); + if (value.Length() > 0) { + // Show the popup with a filtered result set + mController->SetSearchString(NS_LITERAL_STRING("")); + mController->HandleText(PR_TRUE); + } else { + // Show the popup with the complete result set. Can't use HandleText() + // because it doesn't display the popup if the input is blank. + PRBool cancel = PR_FALSE; + mController->HandleKeyNavigation(nsIAutoCompleteController::KEY_DOWN, &cancel); + } + + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::MouseDblClick(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::MouseOver(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} + +NS_IMETHODIMP +nsFormFillController::MouseOut(nsIDOMEvent* aMouseEvent) +{ + return NS_OK; +} //////////////////////////////////////////////////////////////////////// //// nsFormFillController void -nsFormFillController::AddFocusListener(nsIDOMWindow *aWindow) +nsFormFillController::AddWindowListeners(nsIDOMWindow *aWindow) { if (!aWindow) return; @@ -668,14 +764,23 @@ privateDOMWindow->GetChromeEventHandler(getter_AddRefs(chromeEventHandler)); nsCOMPtr target(do_QueryInterface(chromeEventHandler)); - if (target) - target->AddEventListener(NS_LITERAL_STRING("focus"), - NS_STATIC_CAST(nsIDOMFocusListener *, this), - PR_TRUE); + if (!target) + return; + target->AddEventListener(NS_LITERAL_STRING("focus"), + NS_STATIC_CAST(nsIDOMFocusListener *, this), + PR_TRUE); + + target->AddEventListener(NS_LITERAL_STRING("mousedown"), + NS_STATIC_CAST(nsIDOMMouseListener *, this), + PR_TRUE); + + target->AddEventListener(NS_LITERAL_STRING("click"), + NS_STATIC_CAST(nsIDOMMouseListener *, this), + PR_TRUE); } void -nsFormFillController::RemoveFocusListener(nsIDOMWindow *aWindow) +nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow) { if (!aWindow) return; @@ -688,46 +793,54 @@ privateDOMWindow->GetChromeEventHandler(getter_AddRefs(chromeEventHandler)); nsCOMPtr target(do_QueryInterface(chromeEventHandler)); + if (!target) + return; + target->RemoveEventListener(NS_LITERAL_STRING("focus"), - NS_STATIC_CAST(nsIDOMFocusListener *, this), - PR_TRUE); + NS_STATIC_CAST(nsIDOMFocusListener *, this), + PR_TRUE); + + target->RemoveEventListener(NS_LITERAL_STRING("mousedown"), + NS_STATIC_CAST(nsIDOMMouseListener *, this), + PR_TRUE); + + target->RemoveEventListener(NS_LITERAL_STRING("click"), + NS_STATIC_CAST(nsIDOMMouseListener *, this), + PR_TRUE); } void -nsFormFillController::AddKeyListener(nsIDOMHTMLInputElement *aInput) +nsFormFillController::AddInputListeners(nsIDOMHTMLInputElement *aInput) { - if (aInput) { - mFocusedInput = aInput; - - nsCOMPtr target = do_QueryInterface(aInput); + if (!aInput) + return; - target->AddEventListener(NS_LITERAL_STRING("input"), - NS_STATIC_CAST(nsIDOMFormListener *, this), - PR_TRUE); - - target->AddEventListener(NS_LITERAL_STRING("keypress"), - NS_STATIC_CAST(nsIDOMKeyListener *, this), - PR_TRUE); - } + nsCOMPtr target = do_QueryInterface(aInput); + + target->AddEventListener(NS_LITERAL_STRING("input"), + NS_STATIC_CAST(nsIDOMFormListener *, this), + PR_TRUE); + + target->AddEventListener(NS_LITERAL_STRING("keypress"), + NS_STATIC_CAST(nsIDOMKeyListener *, this), + PR_TRUE); } void -nsFormFillController::RemoveKeyListener() +nsFormFillController::RemoveInputListeners() { - if (mFocusedInput) { - - nsCOMPtr target = do_QueryInterface(mFocusedInput); - - target->RemoveEventListener(NS_LITERAL_STRING("input"), - NS_STATIC_CAST(nsIDOMFormListener *, this), - PR_TRUE); + if (!mFocusedInput) + return; - target->RemoveEventListener(NS_LITERAL_STRING("keypress"), - NS_STATIC_CAST(nsIDOMKeyListener *, this), - PR_TRUE); + nsCOMPtr target = do_QueryInterface(mFocusedInput); - mFocusedInput = nsnull; - } + target->RemoveEventListener(NS_LITERAL_STRING("input"), + NS_STATIC_CAST(nsIDOMFormListener *, this), + PR_TRUE); + + target->RemoveEventListener(NS_LITERAL_STRING("keypress"), + NS_STATIC_CAST(nsIDOMKeyListener *, this), + PR_TRUE); } void @@ -745,8 +858,9 @@ // Cache the popup for the focused docShell mPopups->GetElementAt(index, getter_AddRefs(mFocusedPopup)); - // Start listening for key events - AddKeyListener(aInput); + // start listening for events + AddInputListeners(aInput); + mFocusedInput = aInput; // Now we are the autocomplete controller's bitch mController->SetInput(this); @@ -755,7 +869,7 @@ void nsFormFillController::StopControllingInput() { - RemoveKeyListener(); + RemoveInputListeners(); // Reset the controller's input, but not if it has been switched // to another input already, which might happen if the user switches Index: toolkit/components/satchel/src/nsFormFillController.h =================================================================== RCS file: /cvsroot/mozilla/toolkit/components/satchel/src/nsFormFillController.h,v retrieving revision 1.4 diff -u -r1.4 nsFormFillController.h --- toolkit/components/satchel/src/nsFormFillController.h 26 Jul 2003 02:55:24 -0000 1.4 +++ toolkit/components/satchel/src/nsFormFillController.h 24 Apr 2004 20:38:50 -0000 @@ -20,7 +20,8 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Joe Hewitt (Original Author) + * Joe Hewitt (Original Author) + * Dean Tessman * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -47,6 +48,7 @@ #include "nsIDOMFocusListener.h" #include "nsIDOMKeyListener.h" #include "nsIDOMFormListener.h" +#include "nsIDOMMouseListener.h" #include "nsCOMPtr.h" #include "nsISupportsArray.h" #include "nsIDocShell.h" @@ -59,16 +61,15 @@ public nsIAutoCompleteSearch, public nsIDOMFocusListener, public nsIDOMKeyListener, - public nsIDOMFormListener + public nsIDOMFormListener, + public nsIDOMMouseListener { public: NS_DECL_ISUPPORTS NS_DECL_NSIFORMFILLCONTROLLER NS_DECL_NSIAUTOCOMPLETESEARCH NS_DECL_NSIAUTOCOMPLETEINPUT - - // nsIDOMEventListener - NS_IMETHOD HandleEvent(nsIDOMEvent* aEvent); + NS_DECL_NSIDOMEVENTLISTENER // nsIDOMFocusListener NS_IMETHOD Focus(nsIDOMEvent* aEvent); @@ -86,15 +87,23 @@ NS_IMETHOD Select(nsIDOMEvent* aEvent); NS_IMETHOD Input(nsIDOMEvent* aEvent); + // nsIDOMMouseListener + NS_IMETHOD MouseDown(nsIDOMEvent* aMouseEvent); + NS_IMETHOD MouseUp(nsIDOMEvent* aMouseEvent); + NS_IMETHOD MouseClick(nsIDOMEvent* aMouseEvent); + NS_IMETHOD MouseDblClick(nsIDOMEvent* aMouseEvent); + NS_IMETHOD MouseOver(nsIDOMEvent* aMouseEvent); + NS_IMETHOD MouseOut(nsIDOMEvent* aMouseEvent); + nsFormFillController(); virtual ~nsFormFillController(); protected: - void AddFocusListener(nsIDOMWindow *aWindow); - void RemoveFocusListener(nsIDOMWindow *aWindow); - - void AddKeyListener(nsIDOMHTMLInputElement *aInput); - void RemoveKeyListener(); + void AddWindowListeners(nsIDOMWindow *aWindow); + void RemoveWindowListeners(nsIDOMWindow *aWindow); + + void AddInputListeners(nsIDOMHTMLInputElement *aInput); + void RemoveInputListeners(); void StartControllingInput(nsIDOMHTMLInputElement *aInput); void StopControllingInput(); @@ -121,6 +130,7 @@ PRPackedBool mCompleteDefaultIndex; PRPackedBool mForceComplete; PRPackedBool mSuppressOnInput; + PRPackedBool mIgnoreClick; }; #endif // __nsFormFillController__ Index: toolkit/content/widgets/autocomplete.xml =================================================================== RCS file: /cvsroot/mozilla/toolkit/content/widgets/autocomplete.xml,v retrieving revision 1.24 diff -u -r1.24 autocomplete.xml --- toolkit/content/widgets/autocomplete.xml 17 Apr 2004 05:53:34 -0000 1.24 +++ toolkit/content/widgets/autocomplete.xml 24 Apr 2004 20:38:51 -0000 @@ -21,6 +21,7 @@ # # Contributor(s): # Pierre Chanial (p_ch@verizon.net) +# Dean Tessman (dean_tessman@hotmail.com) # # Alternatively, the contents of this file may be used under the # terms of the GNU General Public License Version 2 or later (the @@ -414,7 +415,7 @@ + action="if (!this.mIgnoreInput) this.mController.handleText(false);"/>