bug IME candidate list is hidden by autocomplete window (r=dbaron,bryner,smontagu,jst,sr=dbaron,bryner,neil) : patch by Masayuki Nakano

This commit is contained in:
jshin%mailaps.org 2005-03-05 08:19:05 +00:00
parent f9e9a4b85f
commit d28e19536e
11 changed files with 223 additions and 12 deletions

View File

@ -59,7 +59,8 @@ static const char* const sEventNames[] = {
"mouseout", "mousemove", "contextmenu", "keydown", "keyup", "keypress",
"focus", "blur", "load", "beforeunload", "unload", "abort", "error",
"submit", "reset", "change", "select", "input", "paint" ,"text",
"popupshowing", "popupshown", "popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate",
"compositionstart", "compositionend", "popupshowing", "popupshown",
"popuphiding", "popuphidden", "close", "command", "broadcast", "commandupdate",
"dragenter", "dragover", "dragexit", "dragdrop", "draggesture", "resize",
"scroll","overflow", "underflow", "overflowchanged",
"DOMSubtreeModified", "DOMNodeInserted", "DOMNodeRemoved",
@ -407,6 +408,11 @@ nsDOMEvent::SetEventType(const nsAString& aEventTypeArg)
mEvent->message = NS_KEY_UP;
else if (atom == nsLayoutAtoms::onkeypress)
mEvent->message = NS_KEY_PRESS;
} else if (mEvent->eventStructType == NS_COMPOSITION_EVENT) {
if (atom == nsLayoutAtoms::oncompositionstart)
mEvent->message = NS_COMPOSITION_START;
else if (atom == nsLayoutAtoms::oncompositionend)
mEvent->message = NS_COMPOSITION_END;
} else if (mEvent->eventStructType == NS_EVENT) {
if (atom == nsLayoutAtoms::onfocus)
mEvent->message = NS_FOCUS_CONTENT;
@ -765,6 +771,10 @@ const char* nsDOMEvent::GetEventName(PRUint32 aEventType)
return sEventNames[eDOMEvents_keydown];
case NS_KEY_PRESS:
return sEventNames[eDOMEvents_keypress];
case NS_COMPOSITION_START:
return sEventNames[eDOMEvents_compositionstart];
case NS_COMPOSITION_END:
return sEventNames[eDOMEvents_compositionend];
case NS_FOCUS_CONTENT:
return sEventNames[eDOMEvents_focus];
case NS_BLUR_CONTENT:

View File

@ -92,6 +92,8 @@ public:
eDOMEvents_input,
eDOMEvents_paint,
eDOMEvents_text,
eDOMEvents_compositionstart,
eDOMEvents_compositionend,
eDOMEvents_popupShowing,
eDOMEvents_popupShown,
eDOMEvents_popupHiding,

View File

@ -1001,6 +1001,14 @@ nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType,
*aArrayType = eEventArrayType_DOMUI;
*aFlags = NS_EVENT_BITS_UI_FOCUSOUT;
}
else if (aType == nsLayoutAtoms::oncompositionstart) {
*aArrayType = eEventArrayType_Composition;
*aFlags = NS_EVENT_BITS_COMPOSITION_START;
}
else if (aType == nsLayoutAtoms::oncompositionend) {
*aArrayType = eEventArrayType_Composition;
*aFlags = NS_EVENT_BITS_COMPOSITION_END;
}
else {
return NS_ERROR_FAILURE;
}

View File

@ -176,6 +176,8 @@ LAYOUT_ATOM(oninput, "oninput")
LAYOUT_ATOM(onkeydown, "onkeydown")
LAYOUT_ATOM(onkeypress, "onkeypress")
LAYOUT_ATOM(onkeyup, "onkeyup")
LAYOUT_ATOM(oncompositionstart, "oncompositionstart")
LAYOUT_ATOM(oncompositionend, "oncompositionend")
LAYOUT_ATOM(onload, "onload")
LAYOUT_ATOM(onmousedown, "onmousedown")
LAYOUT_ATOM(onmousemove, "onmousemove")

View File

@ -40,7 +40,7 @@
interface nsIAutoCompleteInput;
[scriptable, uuid(75866768-ED00-4ff4-B950-485449A67A88)]
[scriptable, uuid(CF2ACA0C-4FB1-42e4-8A54-23E832CB2A98)]
interface nsIAutoCompleteController : nsISupports
{
/*
@ -104,6 +104,16 @@ interface nsIAutoCompleteController : nsISupports
*/
boolean handleEscape();
/*
* Notify the controller that the user wishes to start composition
*/
void handleStartComposition();
/*
* Notify the controller that the user wishes to end composition
*/
void handleEndComposition();
/*
* Handle tab. Just closes up.
*/

View File

@ -23,6 +23,7 @@
* Joe Hewitt <hewitt@netscape.com> (Original Author)
* Dean Tessman <dean_tessman@hotmail.com>
* Johnny Stenback <jst@mozilla.jstenback.com>
* Masayuki Nakano <masayuki@d-toybox.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
@ -58,6 +59,9 @@ nsAutoCompleteController::nsAutoCompleteController() :
mEnterAfterSearch(PR_FALSE),
mDefaultIndexCompleted(PR_FALSE),
mBackspaced(PR_FALSE),
mPopupClosedByCompositionStart(PR_FALSE),
mIsIMEComposing(PR_FALSE),
mIgnoreHandleText(PR_FALSE),
mSearchStatus(0),
mRowCount(0),
mSearchesOngoing(0)
@ -165,12 +169,11 @@ nsAutoCompleteController::StartSearch(const nsAString &aSearchString)
NS_IMETHODIMP
nsAutoCompleteController::HandleText(PRBool aIgnoreSelection)
{
// Stop current search in case it's async.
StopSearch();
// Stop the queued up search on a timer
ClearSearchTimer();
if (!mInput) {
// Stop current search in case it's async.
StopSearch();
// Stop the queued up search on a timer
ClearSearchTimer();
// Note: if now is after blur and IME end composition,
// check mInput before calling.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=193544#c31
@ -178,17 +181,38 @@ nsAutoCompleteController::HandleText(PRBool aIgnoreSelection)
return NS_OK;
}
nsAutoString newValue;
mInput->GetTextValue(newValue);
// Note: the events occur in the following order when IME is used.
// 1. composition start event(HandleStartComposition)
// 2. composition end event(HandleEndComposition)
// 3. input event(HandleText)
// Note that the input event occurs if IME composition is cancelled, as well.
// In HandleEndComposition, we are processing the popup properly.
// Therefore, the input event after composition end event should do nothing.
// (E.g., calling StopSearch(), ClearSearchTimer() and ClosePopup().)
// If it is not, popup is always closed after composition end.
if (mIgnoreHandleText) {
mIgnoreHandleText = PR_FALSE;
if (newValue.Equals(mSearchString))
return NS_OK;
NS_ERROR("Now is after composition end event. But the value was changed.");
}
// Stop current search in case it's async.
StopSearch();
// Stop the queued up search on a timer
ClearSearchTimer();
PRBool disabled;
mInput->GetDisableAutoComplete(&disabled);
NS_ENSURE_TRUE(!disabled, NS_OK);
nsAutoString newValue;
mInput->GetTextValue(newValue);
// Don't search again if the new string is the same as the last search
if (newValue.Length() > 0 && newValue.Equals(mSearchString))
return NS_OK;
// Determine if the user has removed text from the end (probably by backspacing)
if (newValue.Length() < mSearchString.Length() &&
Substring(mSearchString, 0, newValue.Length()).Equals(newValue))
@ -262,6 +286,62 @@ nsAutoCompleteController::HandleEscape(PRBool *_retval)
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteController::HandleStartComposition()
{
NS_ENSURE_TRUE(!mIsIMEComposing, NS_OK);
mPopupClosedByCompositionStart = PR_FALSE;
mIsIMEComposing = PR_TRUE;
if (!mInput)
return NS_OK;
PRBool disabled;
mInput->GetDisableAutoComplete(&disabled);
if (disabled)
return NS_OK;
StopSearch();
ClearSearchTimer();
PRBool isOpen;
mInput->GetPopupOpen(&isOpen);
if (isOpen)
ClosePopup();
mPopupClosedByCompositionStart = isOpen;
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteController::HandleEndComposition()
{
NS_ENSURE_TRUE(mIsIMEComposing, NS_OK);
mIsIMEComposing = PR_FALSE;
PRBool forceOpenPopup = mPopupClosedByCompositionStart;
mPopupClosedByCompositionStart = PR_FALSE;
if (!mInput)
return NS_OK;
nsAutoString value;
mInput->GetTextValue(value);
SetSearchString(EmptyString());
if (!value.IsEmpty()) {
// Show the popup with a filtered result set
HandleText(PR_TRUE);
} else if (forceOpenPopup) {
PRBool cancel;
HandleKeyNavigation(nsIAutoCompleteController::KEY_DOWN, &cancel);
}
// On here, |value| and |mSearchString| are same. Therefore, next HandleText should be
// ignored. Because there are no reason to research.
mIgnoreHandleText = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP
nsAutoCompleteController::HandleTab()
{
@ -274,7 +354,15 @@ nsAutoCompleteController::HandleKeyNavigation(PRUint16 aKey, PRBool *_retval)
{
// By default, don't cancel the event
*_retval = PR_FALSE;
if (!mInput) {
// Note: if now is after blur and IME end composition,
// check mInput before calling.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=193544#c31
NS_ERROR("Called before attaching to the control or after detaching from the control");
return NS_OK;
}
nsCOMPtr<nsIAutoCompletePopup> popup;
mInput->GetPopup(getter_AddRefs(popup));
NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE);

View File

@ -104,6 +104,9 @@ protected:
PRPackedBool mEnterAfterSearch;
PRPackedBool mDefaultIndexCompleted;
PRPackedBool mBackspaced;
PRPackedBool mPopupClosedByCompositionStart;
PRPackedBool mIsIMEComposing;
PRPackedBool mIgnoreHandleText;
PRUint16 mSearchStatus;
PRUint32 mRowCount;
PRUint32 mSearchesOngoing;

View File

@ -53,6 +53,7 @@
#include "nsIContentViewer.h"
#include "nsIDOMEventTarget.h"
#include "nsIDOMKeyEvent.h"
#include "nsIDOMCompositionListener.h"
#include "nsIDOMDocument.h"
#include "nsIDOMElement.h"
#include "nsIDOMNSHTMLInputElement.h"
@ -79,6 +80,7 @@ NS_INTERFACE_MAP_BEGIN(nsFormFillController)
NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMCompositionListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFormFillController)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFocusListener)
NS_INTERFACE_MAP_END
@ -646,6 +648,49 @@ nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
//// nsIDOMCompositionListener
NS_IMETHODIMP
nsFormFillController::HandleStartComposition(nsIDOMEvent* aCompositionEvent)
{
NS_ASSERTION(mController, "should have a controller!");
if (mController && mFocusedInput)
mController->HandleStartComposition();
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::HandleEndComposition(nsIDOMEvent* aCompositionEvent)
{
NS_ASSERTION(mController, "should have a controller!");
if (mController && mFocusedInput)
mController->HandleEndComposition();
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::HandleQueryComposition(nsIDOMEvent* aCompositionEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::HandleQueryReconversion(nsIDOMEvent* aCompositionEvent)
{
return NS_OK;
}
NS_IMETHODIMP
nsFormFillController::HandleQueryCaretRect(nsIDOMEvent* aCompostionEvent)
{
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
//// nsIDOMFormListener
@ -864,6 +909,14 @@ nsFormFillController::AddWindowListeners(nsIDOMWindow *aWindow)
target->AddEventListener(NS_LITERAL_STRING("unload"),
NS_STATIC_CAST(nsIDOMLoadListener *, this),
PR_TRUE);
target->AddEventListener(NS_LITERAL_STRING("compositionstart"),
NS_STATIC_CAST(nsIDOMCompositionListener *, this),
PR_TRUE);
target->AddEventListener(NS_LITERAL_STRING("compositionend"),
NS_STATIC_CAST(nsIDOMCompositionListener *, this),
PR_TRUE);
}
void
@ -907,6 +960,14 @@ nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow)
target->RemoveEventListener(NS_LITERAL_STRING("unload"),
NS_STATIC_CAST(nsIDOMLoadListener *, this),
PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("compositionstart"),
NS_STATIC_CAST(nsIDOMCompositionListener *, this),
PR_TRUE);
target->RemoveEventListener(NS_LITERAL_STRING("compositionend"),
NS_STATIC_CAST(nsIDOMCompositionListener *, this),
PR_TRUE);
}
void

View File

@ -47,6 +47,7 @@
#include "nsIAutoCompletePopup.h"
#include "nsIDOMFocusListener.h"
#include "nsIDOMKeyListener.h"
#include "nsIDOMCompositionListener.h"
#include "nsIDOMFormListener.h"
#include "nsIDOMMouseListener.h"
#include "nsIDOMLoadListener.h"
@ -62,6 +63,7 @@ class nsFormFillController : public nsIFormFillController,
public nsIAutoCompleteSearch,
public nsIDOMFocusListener,
public nsIDOMKeyListener,
public nsIDOMCompositionListener,
public nsIDOMFormListener,
public nsIDOMMouseListener,
public nsIDOMLoadListener
@ -82,6 +84,13 @@ public:
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyPress(nsIDOMEvent* aKeyEvent);
// nsIDOMCompositionListener
NS_IMETHOD HandleStartComposition(nsIDOMEvent* aCompositionEvent);
NS_IMETHOD HandleEndComposition(nsIDOMEvent* aCompositionEvent);
NS_IMETHOD HandleQueryComposition(nsIDOMEvent* aCompositionEvent);
NS_IMETHOD HandleQueryReconversion(nsIDOMEvent* aCompositionEvent);
NS_IMETHOD HandleQueryCaretRect(nsIDOMEvent* aCompositionEvent);
// nsIDOMFormListener
NS_IMETHOD Submit(nsIDOMEvent* aEvent);
NS_IMETHOD Reset(nsIDOMEvent* aEvent);

View File

@ -438,6 +438,12 @@
<handler event="keypress" phase="capturing"
action="return this.onKeyPress(event);"/>
<handler event="compositionstart" phase="capturing"
action="if (this.mController.input == this) this.mController.handleStartComposition();"/>
<handler event="compositionend" phase="capturing"
action="if (this.mController.input == this) this.mController.handleEndComposition();"/>
<handler event="focus" phase="capturing"
action="this.attachController();"/>

View File

@ -931,6 +931,15 @@
]]></body>
</method>
<!-- -->
<method name="processStartComposition">
<body><![CDATA[
this.finishAutoComplete(false, false, null);
this.clearTimer();
this.closeResultPopup();
]]></body>
</method>
<!-- -->
<method name="keyNavigation">
<parameter name="aEvent"/>
@ -1317,6 +1326,9 @@
<handler event="keypress" phase="capturing"
action="return this.processKeyPress(event);"/>
<handler event="compositionstart" phase="capturing"
action="this.processStartComposition();"/>
<handler event="focus" phase="capturing"
action="this.userAction = 'typing';"/>