Bug 1058136 - Handle compose event to optimize composition usage; r=cpeterson

This commit is contained in:
Jim Chen 2014-09-04 14:38:18 -04:00
parent 4e042d586f
commit 0567c72b22
4 changed files with 108 additions and 50 deletions

View File

@ -472,7 +472,8 @@ AndroidGeckoEvent::Init(JNIEnv *jenv, jobject jobj)
mStart = jenv->GetIntField(jobj, jStartField);
mEnd = jenv->GetIntField(jobj, jEndField);
if (mAction == IME_REPLACE_TEXT) {
if (mAction == IME_REPLACE_TEXT ||
mAction == IME_COMPOSE_TEXT) {
ReadCharactersField(jenv);
} else if (mAction == IME_UPDATE_COMPOSITION ||
mAction == IME_ADD_COMPOSITION_RANGE) {

View File

@ -745,6 +745,7 @@ public:
IME_UPDATE_COMPOSITION = 4,
IME_REMOVE_COMPOSITION = 5,
IME_ACKNOWLEDGE_FOCUS = 6,
IME_COMPOSE_TEXT = 7,
dummy_ime_enum_list_end
};

View File

@ -177,6 +177,7 @@ nsWindow::nsWindow() :
mParent(nullptr),
mFocus(nullptr),
mIMEComposing(false),
mIMEComposingStart(-1),
mIMEMaskSelectionUpdate(false),
mIMEMaskTextUpdate(false),
mIMEMaskEventsCount(1), // Mask IME events since there's no focus yet
@ -679,6 +680,7 @@ nsWindow::DispatchEvent(WidgetGUIEvent* aEvent)
case NS_COMPOSITION_END:
MOZ_ASSERT(mIMEComposing);
mIMEComposing = false;
mIMEComposingStart = -1;
mIMEComposingText.Truncate();
break;
case NS_TEXT_TEXT:
@ -1765,6 +1767,7 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
}
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
return;
} else if (ae->Action() == AndroidGeckoEvent::IME_UPDATE_CONTEXT) {
mozilla::widget::android::GeckoAppShell::NotifyIMEContext(mInputContext.mIMEState.mEnabled,
mInputContext.mHTMLInputType,
@ -1773,27 +1776,33 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
mIMEUpdatingContext = false;
return;
}
if (mIMEMaskEventsCount > 0) {
// Still reply to events, but don't do anything else
if (ae->Action() == AndroidGeckoEvent::IME_SYNCHRONIZE ||
ae->Action() == AndroidGeckoEvent::IME_COMPOSE_TEXT ||
ae->Action() == AndroidGeckoEvent::IME_REPLACE_TEXT) {
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
}
return;
}
switch (ae->Action()) {
case AndroidGeckoEvent::IME_FLUSH_CHANGES:
{
FlushIMEChanges();
}
break;
case AndroidGeckoEvent::IME_SYNCHRONIZE:
{
FlushIMEChanges();
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
}
break;
case AndroidGeckoEvent::IME_REPLACE_TEXT:
case AndroidGeckoEvent::IME_COMPOSE_TEXT:
{
/*
Replace text in Gecko thread from ae->Start() to ae->End()
@ -1806,31 +1815,48 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
Gecko text
*/
AutoIMEMask selMask(mIMEMaskSelectionUpdate);
RemoveIMEComposition();
{
WidgetSelectionEvent event(true, NS_SELECTION_SET, this);
InitEvent(event, nullptr);
event.mOffset = uint32_t(ae->Start());
event.mLength = uint32_t(ae->End() - ae->Start());
event.mExpandToClusterBoundary = false;
DispatchEvent(&event);
}
if (!mIMEKeyEvents.IsEmpty()) {
for (uint32_t i = 0; i < mIMEKeyEvents.Length(); i++) {
OnKeyEvent(&mIMEKeyEvents[i]);
if (!mIMEKeyEvents.IsEmpty() ||
mIMEComposingStart < 0 ||
ae->Start() != mIMEComposingStart ||
ae->End() != mIMEComposingStart +
int32_t(mIMEComposingText.Length())) {
// Only start a new composition if we have key events,
// if we don't have an existing composition, or
// the replaced text does not match our composition.
RemoveIMEComposition();
{
WidgetSelectionEvent event(true, NS_SELECTION_SET, this);
InitEvent(event, nullptr);
event.mOffset = uint32_t(ae->Start());
event.mLength = uint32_t(ae->End() - ae->Start());
event.mExpandToClusterBoundary = false;
DispatchEvent(&event);
}
if (!mIMEKeyEvents.IsEmpty()) {
for (uint32_t i = 0; i < mIMEKeyEvents.Length(); i++) {
OnKeyEvent(&mIMEKeyEvents[i]);
}
mIMEKeyEvents.Clear();
FlushIMEChanges();
mozilla::widget::android::GeckoAppShell::NotifyIME(
AndroidBridge::NOTIFY_IME_REPLY_EVENT);
// Break out of the switch block
break;
}
{
WidgetCompositionEvent event(
true, NS_COMPOSITION_START, this);
InitEvent(event, nullptr);
DispatchEvent(&event);
mIMEComposingStart = ae->Start();
}
mIMEKeyEvents.Clear();
FlushIMEChanges();
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
break;
}
{
WidgetCompositionEvent event(true, NS_COMPOSITION_START, this);
InitEvent(event, nullptr);
DispatchEvent(&event);
}
{
WidgetCompositionEvent event(true, NS_COMPOSITION_UPDATE, this);
InitEvent(event, nullptr);
@ -1843,16 +1869,23 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
event.theText = ae->Characters();
DispatchEvent(&event);
}
// Don't end composition when composing text.
if (ae->Action() != AndroidGeckoEvent::IME_COMPOSE_TEXT)
{
WidgetCompositionEvent event(true, NS_COMPOSITION_END, this);
InitEvent(event, nullptr);
event.data = ae->Characters();
DispatchEvent(&event);
FlushIMEChanges();
}
FlushIMEChanges();
mozilla::widget::android::GeckoAppShell::NotifyIME(AndroidBridge::NOTIFY_IME_REPLY_EVENT);
mozilla::widget::android::GeckoAppShell::NotifyIME(
AndroidBridge::NOTIFY_IME_REPLY_EVENT);
}
break;
case AndroidGeckoEvent::IME_SET_SELECTION:
{
/*
@ -1929,7 +1962,6 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
*/
AutoIMEMask selMask(mIMEMaskSelectionUpdate);
AutoIMEMask textMask(mIMEMaskTextUpdate);
RemoveIMEComposition();
WidgetTextEvent event(true, NS_TEXT_TEXT, this);
InitEvent(event, nullptr);
@ -1937,28 +1969,49 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
event.mRanges = new TextRangeArray();
mIMERanges.swap(event.mRanges);
{
WidgetSelectionEvent event(true, NS_SELECTION_SET, this);
InitEvent(event, nullptr);
event.mOffset = uint32_t(ae->Start());
event.mLength = uint32_t(ae->End() - ae->Start());
event.mExpandToClusterBoundary = false;
DispatchEvent(&event);
}
{
WidgetQueryContentEvent queryEvent(true,
NS_QUERY_SELECTED_TEXT,
this);
InitEvent(queryEvent, nullptr);
DispatchEvent(&queryEvent);
MOZ_ASSERT(queryEvent.mSucceeded && !queryEvent.mWasAsync);
event.theText = queryEvent.mReply.mString;
}
{
WidgetCompositionEvent event(true, NS_COMPOSITION_START, this);
InitEvent(event, nullptr);
DispatchEvent(&event);
if (mIMEComposingStart < 0 ||
ae->Start() != mIMEComposingStart ||
ae->End() != mIMEComposingStart +
int32_t(mIMEComposingText.Length())) {
// Only start new composition if we don't have an existing one,
// or if the existing composition doesn't match the new one.
RemoveIMEComposition();
{
WidgetSelectionEvent event(true, NS_SELECTION_SET, this);
InitEvent(event, nullptr);
event.mOffset = uint32_t(ae->Start());
event.mLength = uint32_t(ae->End() - ae->Start());
event.mExpandToClusterBoundary = false;
DispatchEvent(&event);
}
{
WidgetQueryContentEvent queryEvent(true,
NS_QUERY_SELECTED_TEXT,
this);
InitEvent(queryEvent, nullptr);
DispatchEvent(&queryEvent);
MOZ_ASSERT(queryEvent.mSucceeded && !queryEvent.mWasAsync);
event.theText = queryEvent.mReply.mString;
mIMEComposingStart = queryEvent.mReply.mOffset;
}
{
WidgetCompositionEvent event(
true, NS_COMPOSITION_START, this);
InitEvent(event, nullptr);
DispatchEvent(&event);
}
} else {
// If the new composition matches the existing composition,
// reuse the old composition.
event.theText = mIMEComposingText;
}
{
WidgetCompositionEvent compositionUpdate(true,
NS_COMPOSITION_UPDATE,
@ -1979,12 +2032,14 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
// Notify SelectionHandler of final caret position
// Required in cases of keyboards providing autoCorrections
AndroidGeckoEvent* broadcastEvent = AndroidGeckoEvent::MakeBroadcastEvent(
NS_LITERAL_CSTRING("TextSelection:UpdateCaretPos"),
NS_LITERAL_CSTRING(""));
AndroidGeckoEvent* broadcastEvent =
AndroidGeckoEvent::MakeBroadcastEvent(
NS_LITERAL_CSTRING("TextSelection:UpdateCaretPos"),
NS_LITERAL_CSTRING(""));
nsAppShell::gAppShell->PostEvent(broadcastEvent);
}
break;
case AndroidGeckoEvent::IME_REMOVE_COMPOSITION:
{
/*

View File

@ -189,9 +189,10 @@ protected:
nsCOMPtr<nsIIdleServiceInternal> mIdleService;
bool mIMEComposing;
int32_t mIMEComposingStart;
nsString mIMEComposingText;
bool mIMEMaskSelectionUpdate, mIMEMaskTextUpdate;
int32_t mIMEMaskEventsCount; // Mask events when > 0
nsString mIMEComposingText;
nsRefPtr<mozilla::TextRangeArray> mIMERanges;
bool mIMEUpdatingContext;
nsAutoTArray<mozilla::AndroidGeckoEvent, 8> mIMEKeyEvents;