зеркало из https://github.com/mozilla/gecko-dev.git
Clicking in a focused input should open autocomplete results popup (bug 173569). Patch by dean_tessman@hotmail.com, r=me.
This commit is contained in:
Родитель
7f304859c1
Коммит
b5ff05df21
|
@ -20,6 +20,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Joe Hewitt <hewitt@netscape.com> (Original Author)
|
||||
* Dean Tessman <dean_tessman@hotmail.com>
|
||||
*
|
||||
* 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 @@ interface nsIAutoCompleteController : nsISupports
|
|||
* 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 @@ interface nsIAutoCompleteController : nsISupports
|
|||
* 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);
|
||||
};
|
||||
|
|
|
@ -164,7 +164,7 @@ nsAutoCompleteController::StartSearch(const nsAString &aSearchString)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAutoCompleteController::HandleText()
|
||||
nsAutoCompleteController::HandleText(PRBool aIgnoreSelection)
|
||||
{
|
||||
// Stop current search in case it's async.
|
||||
StopSearch();
|
||||
|
@ -208,7 +208,10 @@ nsAutoCompleteController::HandleText()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// Kick off the search, but only if the cursor is at the end of the textbox
|
||||
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;
|
||||
|
@ -216,6 +219,7 @@ nsAutoCompleteController::HandleText()
|
|||
|
||||
if (selectionStart == selectionEnd && selectionStart == (PRInt32) mSearchString.Length())
|
||||
StartSearchTimer();
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -337,7 +341,7 @@ nsAutoCompleteController::HandleDelete(PRBool *_retval)
|
|||
mInput->GetPopupOpen(&isOpen);
|
||||
if (!isOpen || mRowCount <= 0) {
|
||||
// Nothing left to delete, proceed as normal
|
||||
HandleText();
|
||||
HandleText(PR_FALSE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -438,6 +442,14 @@ nsAutoCompleteController::GetStyleAt(PRInt32 aIndex, nsAString & _retval)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsAutoCompleteController::SetSearchString(const nsAString &aSearchString)
|
||||
{
|
||||
mSearchString = aSearchString;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//// nsIAutoCompleteObserver
|
||||
|
||||
|
@ -810,7 +822,7 @@ nsAutoCompleteController::StartSearchTimer()
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Joe Hewitt <hewitt@netscape.com> (Original Author)
|
||||
* Dean Tessman <dean_tessman@hotmail.com>
|
||||
*
|
||||
* 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
|
||||
|
@ -67,6 +68,7 @@
|
|||
#include "nsIDOMDocumentEvent.h"
|
||||
#include "nsIDOMHTMLFormElement.h"
|
||||
#include "nsPasswordManager.h"
|
||||
#include "nsIDOMMouseEvent.h"
|
||||
|
||||
NS_INTERFACE_MAP_BEGIN(nsFormFillController)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIFormFillController)
|
||||
|
@ -75,6 +77,7 @@ NS_INTERFACE_MAP_BEGIN(nsFormFillController)
|
|||
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
|
||||
|
@ -106,7 +109,7 @@ nsFormFillController::~nsFormFillController()
|
|||
nsCOMPtr<nsIDocShell> docShell;
|
||||
mDocShells->GetElementAt(i, getter_AddRefs(docShell));
|
||||
nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(docShell);
|
||||
RemoveFocusListener(domWindow);
|
||||
RemoveWindowListeners(domWindow);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,7 +178,7 @@ nsFormFillController::AttachToBrowser(nsIDocShell *aDocShell, nsIAutoCompletePop
|
|||
|
||||
// Listen for focus events on the domWindow of the docShell
|
||||
nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(aDocShell);
|
||||
AddFocusListener(domWindow);
|
||||
AddWindowListeners(domWindow);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -190,7 +193,7 @@ nsFormFillController::DetachFromBrowser(nsIDocShell *aDocShell)
|
|||
nsCOMPtr<nsIDocShell> docShell;
|
||||
mDocShells->GetElementAt(index, getter_AddRefs(docShell));
|
||||
nsCOMPtr<nsIDOMWindow> domWindow = GetWindowForDocShell(docShell);
|
||||
RemoveFocusListener(domWindow);
|
||||
RemoveWindowListeners(domWindow);
|
||||
|
||||
mDocShells->RemoveElementAt(index);
|
||||
mPopups->RemoveElementAt(index);
|
||||
|
@ -507,7 +510,9 @@ nsFormFillController::Focus(nsIDOMEvent* aEvent)
|
|||
aEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> input = do_QueryInterface(target);
|
||||
if (input) {
|
||||
if (!input)
|
||||
return NS_OK;
|
||||
|
||||
nsAutoString type;
|
||||
input->GetType(type);
|
||||
|
||||
|
@ -524,7 +529,6 @@ nsFormFillController::Focus(nsIDOMEvent* aEvent)
|
|||
if (!form || !autocomplete.LowerCaseEqualsLiteral("off"))
|
||||
StartControllingInput(input);
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -556,7 +560,13 @@ nsFormFillController::KeyUp(nsIDOMEvent* aEvent)
|
|||
NS_IMETHODIMP
|
||||
nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
|
||||
{
|
||||
NS_ASSERTION(mController, "should have a controller!");
|
||||
if (!mFocusedInput || !mController)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIDOMKeyEvent> keyEvent = do_QueryInterface(aEvent);
|
||||
if (!keyEvent)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRBool cancel = PR_FALSE;
|
||||
|
||||
|
@ -577,7 +587,7 @@ nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
|
|||
// 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);
|
||||
|
@ -623,6 +633,9 @@ nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
|
|||
NS_IMETHODIMP
|
||||
nsFormFillController::Submit(nsIDOMEvent* aEvent)
|
||||
{
|
||||
if (mFocusedInput)
|
||||
StopControllingInput();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -647,18 +660,109 @@ nsFormFillController::Select(nsIDOMEvent* aEvent)
|
|||
NS_IMETHODIMP
|
||||
nsFormFillController::Input(nsIDOMEvent* aEvent)
|
||||
{
|
||||
if (mSuppressOnInput)
|
||||
if (mSuppressOnInput || !mController)
|
||||
return NS_OK;
|
||||
|
||||
return mController->HandleText();
|
||||
return mController->HandleText(PR_FALSE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
//// nsIDOMMouseListener
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsFormFillController::MouseDown(nsIDOMEvent* aMouseEvent)
|
||||
{
|
||||
mIgnoreClick = PR_FALSE;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target;
|
||||
aMouseEvent->GetTarget(getter_AddRefs(target));
|
||||
|
||||
nsCOMPtr<nsIDOMHTMLInputElement> 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<nsIDOMMouseEvent> mouseEvent(do_QueryInterface(aMouseEvent));
|
||||
if (!mouseEvent)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
PRUint16 button;
|
||||
mouseEvent->GetButton(&button);
|
||||
if (button != 0)
|
||||
return NS_OK;
|
||||
|
||||
PRBool isOpen = PR_FALSE;
|
||||
GetPopupOpen(&isOpen);
|
||||
if (isOpen)
|
||||
return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIAutoCompleteInput> 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;
|
||||
|
@ -670,14 +774,32 @@ nsFormFillController::AddFocusListener(nsIDOMWindow *aWindow)
|
|||
|
||||
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(chromeEventHandler));
|
||||
|
||||
if (target)
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("focus"),
|
||||
NS_STATIC_CAST(nsIDOMFocusListener *, this),
|
||||
PR_TRUE);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("blur"),
|
||||
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);
|
||||
|
||||
target->AddEventListener(NS_LITERAL_STRING("input"),
|
||||
NS_STATIC_CAST(nsIDOMFormListener *, this),
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
nsFormFillController::RemoveFocusListener(nsIDOMWindow *aWindow)
|
||||
nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow)
|
||||
{
|
||||
if (!aWindow)
|
||||
return;
|
||||
|
@ -691,46 +813,54 @@ nsFormFillController::RemoveFocusListener(nsIDOMWindow *aWindow)
|
|||
|
||||
nsCOMPtr<nsIDOMEventTarget> target(do_QueryInterface(chromeEventHandler));
|
||||
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("focus"),
|
||||
NS_STATIC_CAST(nsIDOMFocusListener *, this),
|
||||
PR_TRUE);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("blur"),
|
||||
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);
|
||||
|
||||
target->RemoveEventListener(NS_LITERAL_STRING("input"),
|
||||
NS_STATIC_CAST(nsIDOMFormListener *, this),
|
||||
PR_TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
nsFormFillController::AddKeyListener(nsIDOMHTMLInputElement *aInput)
|
||||
{
|
||||
if (aInput) {
|
||||
mFocusedInput = aInput;
|
||||
if (!aInput)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> 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()
|
||||
{
|
||||
if (mFocusedInput) {
|
||||
if (!mFocusedInput)
|
||||
return;
|
||||
|
||||
nsCOMPtr<nsIDOMEventTarget> target = do_QueryInterface(mFocusedInput);
|
||||
|
||||
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);
|
||||
|
||||
mFocusedInput = nsnull;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -748,8 +878,8 @@ nsFormFillController::StartControllingInput(nsIDOMHTMLInputElement *aInput)
|
|||
// Cache the popup for the focused docShell
|
||||
mPopups->GetElementAt(index, getter_AddRefs(mFocusedPopup));
|
||||
|
||||
// Start listening for key events
|
||||
AddKeyListener(aInput);
|
||||
mFocusedInput = aInput;
|
||||
|
||||
// Now we are the autocomplete controller's bitch
|
||||
mController->SetInput(this);
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
*
|
||||
* Contributor(s):
|
||||
* Joe Hewitt <hewitt@netscape.com> (Original Author)
|
||||
* Dean Tessman <dean_tessman@hotmail.com>
|
||||
*
|
||||
* 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 @@ class nsFormFillController : public nsIFormFillController,
|
|||
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,12 +87,20 @@ public:
|
|||
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 AddWindowListeners(nsIDOMWindow *aWindow);
|
||||
void RemoveWindowListeners(nsIDOMWindow *aWindow);
|
||||
|
||||
void AddKeyListener(nsIDOMHTMLInputElement *aInput);
|
||||
void RemoveKeyListener();
|
||||
|
@ -121,6 +130,7 @@ protected:
|
|||
PRPackedBool mCompleteDefaultIndex;
|
||||
PRPackedBool mForceComplete;
|
||||
PRPackedBool mSuppressOnInput;
|
||||
PRPackedBool mIgnoreClick;
|
||||
};
|
||||
|
||||
#endif // __nsFormFillController__
|
||||
|
|
|
@ -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
|
||||
|
@ -424,7 +425,7 @@
|
|||
|
||||
<handlers>
|
||||
<handler event="input"
|
||||
action="if (!this.mIgnoreInput) this.mController.handleText();"/>
|
||||
action="if (!this.mIgnoreInput) this.mController.handleText(false);"/>
|
||||
|
||||
<handler event="keypress" phase="capturing"
|
||||
action="return this.onKeyPress(event);"/>
|
||||
|
|
Загрузка…
Ссылка в новой задаче