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
Родитель 745019c654
Коммит 8669b7866a
11 изменённых файлов: 223 добавлений и 12 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -1001,6 +1001,14 @@ nsEventListenerManager::GetIdentifiersForType(nsIAtom* aType,
*aArrayType = eEventArrayType_DOMUI; *aArrayType = eEventArrayType_DOMUI;
*aFlags = NS_EVENT_BITS_UI_FOCUSOUT; *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 { else {
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }

Просмотреть файл

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

Просмотреть файл

@ -40,7 +40,7 @@
interface nsIAutoCompleteInput; interface nsIAutoCompleteInput;
[scriptable, uuid(75866768-ED00-4ff4-B950-485449A67A88)] [scriptable, uuid(CF2ACA0C-4FB1-42e4-8A54-23E832CB2A98)]
interface nsIAutoCompleteController : nsISupports interface nsIAutoCompleteController : nsISupports
{ {
/* /*
@ -104,6 +104,16 @@ interface nsIAutoCompleteController : nsISupports
*/ */
boolean handleEscape(); 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. * Handle tab. Just closes up.
*/ */

Просмотреть файл

@ -23,6 +23,7 @@
* Joe Hewitt <hewitt@netscape.com> (Original Author) * Joe Hewitt <hewitt@netscape.com> (Original Author)
* Dean Tessman <dean_tessman@hotmail.com> * Dean Tessman <dean_tessman@hotmail.com>
* Johnny Stenback <jst@mozilla.jstenback.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 * 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 * either the GNU General Public License Version 2 or later (the "GPL"), or
@ -58,6 +59,9 @@ nsAutoCompleteController::nsAutoCompleteController() :
mEnterAfterSearch(PR_FALSE), mEnterAfterSearch(PR_FALSE),
mDefaultIndexCompleted(PR_FALSE), mDefaultIndexCompleted(PR_FALSE),
mBackspaced(PR_FALSE), mBackspaced(PR_FALSE),
mPopupClosedByCompositionStart(PR_FALSE),
mIsIMEComposing(PR_FALSE),
mIgnoreHandleText(PR_FALSE),
mSearchStatus(0), mSearchStatus(0),
mRowCount(0), mRowCount(0),
mSearchesOngoing(0) mSearchesOngoing(0)
@ -165,12 +169,11 @@ nsAutoCompleteController::StartSearch(const nsAString &aSearchString)
NS_IMETHODIMP NS_IMETHODIMP
nsAutoCompleteController::HandleText(PRBool aIgnoreSelection) nsAutoCompleteController::HandleText(PRBool aIgnoreSelection)
{ {
if (!mInput) {
// Stop current search in case it's async. // Stop current search in case it's async.
StopSearch(); StopSearch();
// Stop the queued up search on a timer // Stop the queued up search on a timer
ClearSearchTimer(); ClearSearchTimer();
if (!mInput) {
// Note: if now is after blur and IME end composition, // Note: if now is after blur and IME end composition,
// check mInput before calling. // check mInput before calling.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=193544#c31 // See https://bugzilla.mozilla.org/show_bug.cgi?id=193544#c31
@ -178,13 +181,34 @@ nsAutoCompleteController::HandleText(PRBool aIgnoreSelection)
return NS_OK; 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; PRBool disabled;
mInput->GetDisableAutoComplete(&disabled); mInput->GetDisableAutoComplete(&disabled);
NS_ENSURE_TRUE(!disabled, NS_OK); 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 // Don't search again if the new string is the same as the last search
if (newValue.Length() > 0 && newValue.Equals(mSearchString)) if (newValue.Length() > 0 && newValue.Equals(mSearchString))
return NS_OK; return NS_OK;
@ -262,6 +286,62 @@ nsAutoCompleteController::HandleEscape(PRBool *_retval)
return NS_OK; 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 NS_IMETHODIMP
nsAutoCompleteController::HandleTab() nsAutoCompleteController::HandleTab()
{ {
@ -275,6 +355,14 @@ nsAutoCompleteController::HandleKeyNavigation(PRUint16 aKey, PRBool *_retval)
// By default, don't cancel the event // By default, don't cancel the event
*_retval = PR_FALSE; *_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; nsCOMPtr<nsIAutoCompletePopup> popup;
mInput->GetPopup(getter_AddRefs(popup)); mInput->GetPopup(getter_AddRefs(popup));
NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE); NS_ENSURE_TRUE(popup != nsnull, NS_ERROR_FAILURE);

Просмотреть файл

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

Просмотреть файл

@ -53,6 +53,7 @@
#include "nsIContentViewer.h" #include "nsIContentViewer.h"
#include "nsIDOMEventTarget.h" #include "nsIDOMEventTarget.h"
#include "nsIDOMKeyEvent.h" #include "nsIDOMKeyEvent.h"
#include "nsIDOMCompositionListener.h"
#include "nsIDOMDocument.h" #include "nsIDOMDocument.h"
#include "nsIDOMElement.h" #include "nsIDOMElement.h"
#include "nsIDOMNSHTMLInputElement.h" #include "nsIDOMNSHTMLInputElement.h"
@ -79,6 +80,7 @@ NS_INTERFACE_MAP_BEGIN(nsFormFillController)
NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener) NS_INTERFACE_MAP_ENTRY(nsIDOMFormListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener) NS_INTERFACE_MAP_ENTRY(nsIDOMMouseListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener) NS_INTERFACE_MAP_ENTRY(nsIDOMLoadListener)
NS_INTERFACE_MAP_ENTRY(nsIDOMCompositionListener)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFormFillController) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIFormFillController)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFocusListener) NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsIDOMEventListener, nsIDOMFocusListener)
NS_INTERFACE_MAP_END NS_INTERFACE_MAP_END
@ -646,6 +648,49 @@ nsFormFillController::KeyPress(nsIDOMEvent* aEvent)
return NS_OK; 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 //// nsIDOMFormListener
@ -864,6 +909,14 @@ nsFormFillController::AddWindowListeners(nsIDOMWindow *aWindow)
target->AddEventListener(NS_LITERAL_STRING("unload"), target->AddEventListener(NS_LITERAL_STRING("unload"),
NS_STATIC_CAST(nsIDOMLoadListener *, this), NS_STATIC_CAST(nsIDOMLoadListener *, this),
PR_TRUE); 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 void
@ -907,6 +960,14 @@ nsFormFillController::RemoveWindowListeners(nsIDOMWindow *aWindow)
target->RemoveEventListener(NS_LITERAL_STRING("unload"), target->RemoveEventListener(NS_LITERAL_STRING("unload"),
NS_STATIC_CAST(nsIDOMLoadListener *, this), NS_STATIC_CAST(nsIDOMLoadListener *, this),
PR_TRUE); 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 void

Просмотреть файл

@ -47,6 +47,7 @@
#include "nsIAutoCompletePopup.h" #include "nsIAutoCompletePopup.h"
#include "nsIDOMFocusListener.h" #include "nsIDOMFocusListener.h"
#include "nsIDOMKeyListener.h" #include "nsIDOMKeyListener.h"
#include "nsIDOMCompositionListener.h"
#include "nsIDOMFormListener.h" #include "nsIDOMFormListener.h"
#include "nsIDOMMouseListener.h" #include "nsIDOMMouseListener.h"
#include "nsIDOMLoadListener.h" #include "nsIDOMLoadListener.h"
@ -62,6 +63,7 @@ class nsFormFillController : public nsIFormFillController,
public nsIAutoCompleteSearch, public nsIAutoCompleteSearch,
public nsIDOMFocusListener, public nsIDOMFocusListener,
public nsIDOMKeyListener, public nsIDOMKeyListener,
public nsIDOMCompositionListener,
public nsIDOMFormListener, public nsIDOMFormListener,
public nsIDOMMouseListener, public nsIDOMMouseListener,
public nsIDOMLoadListener public nsIDOMLoadListener
@ -82,6 +84,13 @@ public:
NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent); NS_IMETHOD KeyUp(nsIDOMEvent* aKeyEvent);
NS_IMETHOD KeyPress(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 // nsIDOMFormListener
NS_IMETHOD Submit(nsIDOMEvent* aEvent); NS_IMETHOD Submit(nsIDOMEvent* aEvent);
NS_IMETHOD Reset(nsIDOMEvent* aEvent); NS_IMETHOD Reset(nsIDOMEvent* aEvent);

Просмотреть файл

@ -438,6 +438,12 @@
<handler event="keypress" phase="capturing" <handler event="keypress" phase="capturing"
action="return this.onKeyPress(event);"/> 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" <handler event="focus" phase="capturing"
action="this.attachController();"/> action="this.attachController();"/>

Просмотреть файл

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