mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1058136 - Handle compose event to optimize composition usage; r=cpeterson
This commit is contained in:
parent
a7078841d8
commit
fd041139d8
@ -471,7 +471,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) {
|
||||
|
@ -744,6 +744,7 @@ public:
|
||||
IME_UPDATE_COMPOSITION = 4,
|
||||
IME_REMOVE_COMPOSITION = 5,
|
||||
IME_ACKNOWLEDGE_FOCUS = 6,
|
||||
IME_COMPOSE_TEXT = 7,
|
||||
dummy_ime_enum_list_end
|
||||
};
|
||||
|
||||
|
@ -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:
|
||||
@ -1710,6 +1712,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,
|
||||
@ -1718,27 +1721,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()
|
||||
@ -1751,31 +1760,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);
|
||||
@ -1788,16 +1814,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:
|
||||
{
|
||||
/*
|
||||
@ -1874,7 +1907,6 @@ nsWindow::OnIMEEvent(AndroidGeckoEvent *ae)
|
||||
*/
|
||||
AutoIMEMask selMask(mIMEMaskSelectionUpdate);
|
||||
AutoIMEMask textMask(mIMEMaskTextUpdate);
|
||||
RemoveIMEComposition();
|
||||
|
||||
WidgetTextEvent event(true, NS_TEXT_TEXT, this);
|
||||
InitEvent(event, nullptr);
|
||||
@ -1882,28 +1914,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,
|
||||
@ -1924,12 +1977,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:
|
||||
{
|
||||
/*
|
||||
|
@ -188,9 +188,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;
|
||||
|
Loading…
Reference in New Issue
Block a user