Bug 1456381 - TSFTextStore should discard pending composition update actions before recording composition end action r?m_kato
TSFTextStore should discard pending composition update actions when it records
end composition update action because end composition update action causes
dispatching eCompositionCommit event and it replaces old composition string
anyway. So, following eCompositionChange which is dispatched by preceding
composition update actions are just redundant.
MozReview-Commit-ID: HBHx2jA15ro
--- a/widget/windows/TSFTextStore.cpp
+++ b/widget/windows/TSFTextStore.cpp
@@ -5198,17 +5198,22 @@ TSFTextStore::RecordCompositionEndAction
MaybeDispatchKeyboardEventAsProcessedByIME();
if (mDestroyed) {
MOZ_LOG(sTextStoreLog, LogLevel::Error,
("0x%p TSFTextStore::RecordCompositionEndAction() FAILED due to "
"destroyed during dispatching a keyboard event", this));
return false;
}
- CompleteLastActionIfStillIncomplete();
+ // If we're handling incomplete composition update or already handled
+ // composition update, we can forget them since composition end will send
+ // the latest composition string and it overwrites the composition string
+ // even if we dispatch eCompositionChange event before that. So, let's
+ // forget all composition updates now.
+ RemoveLastCompositionUpdateActions();
PendingAction* action = mPendingActions.AppendElement();
action->mType = PendingAction::Type::eCompositionEnd;
action->mData = mComposition.mString;
Content& contentForTSF = ContentForTSFRef();
if (!contentForTSF.IsInitialized()) {
MOZ_LOG(sTextStoreLog, LogLevel::Error,
("0x%p TSFTextStore::RecordCompositionEndAction() FAILED due "
--- a/widget/windows/TSFTextStore.h
+++ b/widget/windows/TSFTextStore.h
@@ -777,16 +777,27 @@ protected:
void CompleteLastActionIfStillIncomplete()
{
if (!IsPendingCompositionUpdateIncomplete()) {
return;
}
RecordCompositionUpdateAction();
}
+ void RemoveLastCompositionUpdateActions()
+ {
+ while (!mPendingActions.IsEmpty()) {
+ const PendingAction& lastAction = mPendingActions.LastElement();
+ if (lastAction.mType != PendingAction::Type::eCompositionUpdate) {
+ break;
+ }
+ mPendingActions.RemoveLastElement();
+ }
+ }
+
// When On*Composition() is called without document lock, we need to flush
// the recorded actions at quitting the method.
// AutoPendingActionAndContentFlusher class is usedful for it.
class MOZ_STACK_CLASS AutoPendingActionAndContentFlusher final
{
public:
explicit AutoPendingActionAndContentFlusher(TSFTextStore* aTextStore)
: mTextStore(aTextStore)