Bug 1312649 part.1 TextInputHandler::InsertText() should dispatch composition events instead of keypress events when it replaces a range which is different from current selection r=m_kato

Vietnamese Telex IME handles Backspace key immediately after inputting a word even when there is no marked text.  At this time, it tries to replace the word with specific string.  In such case, our editor shouldn't remove anything at handling the Backspace keypress event.

For avoiding this issue, InserText() should dispatch a set of composition for inserting the specified text into the range.  Then, editor won't perform any action of the key.

Additionally, when a Backspace keydown tries to remove the last character of the word, Telex removes it with a composition.  At this time, it creates dummy marked text "a" and make it empty later. So, in this case, InsertText() won't be called, therefore, we need to consume the Backspace keypress when SetMarkedText() is called for preventing removing the previous character of the word.

MozReview-Commit-ID: LfeEHDWn0cZ

--HG--
extra : rebase_source : 4753262ef16bc3875754ae38e966d8512947ad89
This commit is contained in:
Masayuki Nakano 2016-11-07 10:30:05 +09:00
parent 10ea97a276
commit 5ddcf36aa2

View File

@ -1518,6 +1518,8 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
return false;
}
// Insert empty line to the log for easier to read.
MOZ_LOG(gLog, LogLevel::Info, (""));
MOZ_LOG(gLog, LogLevel::Info,
("%p TextInputHandler::HandleKeyDownEvent, aNativeEvent=%p, "
"type=%s, keyCode=%lld (0x%X), modifierFlags=0x%X, characters=\"%s\", "
@ -1686,6 +1688,8 @@ TextInputHandler::HandleKeyDownEvent(NSEvent* aNativeEvent)
this, TrueOrFalse(currentKeyEvent->mKeyDownHandled),
TrueOrFalse(currentKeyEvent->mKeyPressHandled),
TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents)));
// Insert empty line to the log for easier to read.
MOZ_LOG(gLog, LogLevel::Info, (""));
return currentKeyEvent->IsDefaultPrevented();
NS_OBJC_END_TRY_ABORT_BLOCK_RETURN(false);
@ -2188,10 +2192,20 @@ TextInputHandler::InsertText(NSAttributedString* aAttrString,
return;
}
// If this is not caused by pressing a key or there is a composition, let's
bool isReplacingSpecifiedRange =
isEditable && aReplacementRange &&
aReplacementRange->location != NSNotFound &&
!NSEqualRanges(selectedRange, *aReplacementRange);
// If this is not caused by pressing a key, there is a composition or
// replacing a range which is different from current selection, let's
// insert the text as committing a composition.
if (!currentKeyEvent || IsIMEComposing()) {
if (!currentKeyEvent || IsIMEComposing() || isReplacingSpecifiedRange) {
InsertTextAsCommittingComposition(aAttrString, aReplacementRange);
if (currentKeyEvent) {
currentKeyEvent->mKeyPressHandled = true;
currentKeyEvent->mKeyPressDispatched = true;
}
return;
}
@ -2201,16 +2215,8 @@ TextInputHandler::InsertText(NSAttributedString* aAttrString,
return;
}
// XXX Shouldn't we hold mDispatcher instead of mWidget?
RefPtr<nsChildView> widget(mWidget);
// If the replacement range is specified, select the range. Then, the
// selection will be replaced by the later keypress event.
if (isEditable &&
aReplacementRange && aReplacementRange->location != NSNotFound &&
!NSEqualRanges(selectedRange, *aReplacementRange)) {
NS_ENSURE_TRUE_VOID(SetSelection(*aReplacementRange));
}
nsresult rv = mDispatcher->BeginNativeInputTransaction();
if (NS_WARN_IF(NS_FAILED(rv))) {
MOZ_LOG(gLog, LogLevel::Error,
@ -3143,19 +3149,37 @@ IMEInputHandler::SetMarkedText(NSAttributedString* aAttrString,
{
NS_OBJC_BEGIN_TRY_ABORT_BLOCK;
KeyEventState* currentKeyEvent = GetCurrentKeyEvent();
MOZ_LOG(gLog, LogLevel::Info,
("%p IMEInputHandler::SetMarkedText, "
"aAttrString=\"%s\", aSelectedRange={ location=%llu, length=%llu }, "
"aReplacementRange=%p { location=%llu, length=%llu }, "
"Destroyed()=%s, IgnoreIMEComposition()=%s, IsIMEComposing()=%s, "
"mMarkedRange={ location=%llu, length=%llu }",
"mMarkedRange={ location=%llu, length=%llu }, keyevent=%p, "
"keydownHandled=%s, keypressDispatched=%s, causedOtherKeyEvents=%s",
this, GetCharacters([aAttrString string]),
aSelectedRange.location, aSelectedRange.length, aReplacementRange,
aReplacementRange ? aReplacementRange->location : 0,
aReplacementRange ? aReplacementRange->length : 0,
TrueOrFalse(Destroyed()), TrueOrFalse(IgnoreIMEComposition()),
TrueOrFalse(IsIMEComposing()),
mMarkedRange.location, mMarkedRange.length));
mMarkedRange.location, mMarkedRange.length,
currentKeyEvent ? currentKeyEvent->mKeyEvent : nullptr,
currentKeyEvent ?
TrueOrFalse(currentKeyEvent->mKeyDownHandled) : "N/A",
currentKeyEvent ?
TrueOrFalse(currentKeyEvent->mKeyPressDispatched) : "N/A",
currentKeyEvent ?
TrueOrFalse(currentKeyEvent->mCausedOtherKeyEvents) : "N/A"));
// If SetMarkedText() is called during composition, that means that
// the key event caused this composition. So, keypress event shouldn't
// be dispatched later, let's consume it here.
if (currentKeyEvent) {
currentKeyEvent->mKeyPressHandled = true;
currentKeyEvent->mKeyPressDispatched = true;
}
if (Destroyed() || IgnoreIMEComposition()) {
return;