Bug 1422230 - part 3: TSFTextStore should store composition string information until both TSF/TIP and our content finish handling composition r?m_kato
If remote process hasn't handled dispatched commit event yet, TSFTextStore
needs to dispatch query content event relative to latest composition string
information. So, TSFTextStore::mContentForTSF should cache composition start
and composition string length until pending composition events are handled
by content actually.
MozReview-Commit-ID: ARM851nNZGz
--- a/widget/windows/TSFTextStore.cpp
+++ b/widget/windows/TSFTextStore.cpp
@@ -6805,16 +6805,17 @@ TSFTextStore::Content::ReplaceTextWith(L
} else if (mMinTextModifiedOffset >=
static_cast<uint32_t>(mComposition.mStart) &&
mMinTextModifiedOffset <
static_cast<uint32_t>(mComposition.EndOffset())) {
// The previous change to the composition string is canceled.
mMinTextModifiedOffset = firstDifferentOffset =
mComposition.EndOffset();
}
+ mLatestCompositionEndOffset = mComposition.EndOffset();
MOZ_LOG(sTextStoreLog, LogLevel::Debug,
("0x%p TSFTextStore::Content::ReplaceTextWith(aStart=%d, "
"aLength=%d, aReplaceString=\"%s\"), mComposition={ mStart=%d, "
"mString=\"%s\" }, mLastCompositionString=\"%s\", "
"mMinTextModifiedOffset=%u, firstDifferentOffset=%u",
this, aStart, aLength, GetEscapedUTF8String(aReplaceString).get(),
mComposition.mStart, GetEscapedUTF8String(mComposition.mString).get(),
GetEscapedUTF8String(mLastCompositionString).get(),
@@ -6842,16 +6843,18 @@ TSFTextStore::Content::StartComposition(
MOZ_ASSERT(mInitialized);
MOZ_ASSERT(aCompositionView);
MOZ_ASSERT(!mComposition.mView);
MOZ_ASSERT(aCompStart.mType == PendingAction::COMPOSITION_START);
mComposition.Start(aCompositionView, aCompStart.mSelectionStart,
GetSubstring(static_cast<uint32_t>(aCompStart.mSelectionStart),
static_cast<uint32_t>(aCompStart.mSelectionLength)));
+ mLatestCompositionStartOffset = mComposition.mStart;
+ mLatestCompositionEndOffset = mComposition.EndOffset();
if (!aPreserveSelection) {
// XXX Do we need to set a new writing-mode here when setting a new
// selection? Currently, we just preserve the existing value.
mSelection.SetSelection(mComposition.mStart, mComposition.mString.Length(),
false, mSelection.GetWritingMode());
}
}
@@ -6872,16 +6875,18 @@ TSFTextStore::Content::RestoreCommittedC
static_cast<uint32_t>(aPendingCompositionStart.mSelectionStart),
static_cast<uint32_t>(aCanceledCompositionEnd.mData.Length())) ==
aCanceledCompositionEnd.mData);
// Restore the committed string as composing string.
mComposition.Start(aCompositionView,
aPendingCompositionStart.mSelectionStart,
aCanceledCompositionEnd.mData);
+ mLatestCompositionStartOffset = mComposition.mStart;
+ mLatestCompositionEndOffset = mComposition.EndOffset();
}
void
TSFTextStore::Content::EndComposition(const PendingAction& aCompEnd)
{
MOZ_ASSERT(mInitialized);
MOZ_ASSERT(mComposition.mView);
MOZ_ASSERT(aCompEnd.mType == PendingAction::COMPOSITION_END);
--- a/widget/windows/TSFTextStore.h
+++ b/widget/windows/TSFTextStore.h
@@ -794,16 +794,17 @@ protected:
{
mText = aText;
if (mComposition.IsComposing()) {
mLastCompositionString = mComposition.mString;
} else {
mLastCompositionString.Truncate();
}
mMinTextModifiedOffset = NOT_MODIFIED;
+ mLatestCompositionStartOffset = mLatestCompositionEndOffset = LONG_MAX;
mInitialized = true;
}
void OnLayoutChanged()
{
mMinTextModifiedOffset = NOT_MODIFIED;
}
@@ -845,16 +846,28 @@ protected:
MOZ_ASSERT(mInitialized);
return mLastCompositionString;
}
uint32_t MinTextModifiedOffset() const
{
MOZ_ASSERT(mInitialized);
return mMinTextModifiedOffset;
}
+ LONG LatestCompositionStartOffset() const
+ {
+ MOZ_ASSERT(mInitialized);
+ MOZ_ASSERT(HasOrHadComposition());
+ return mLatestCompositionStartOffset;
+ }
+ LONG LatestCompositionEndOffset() const
+ {
+ MOZ_ASSERT(mInitialized);
+ MOZ_ASSERT(HasOrHadComposition());
+ return mLatestCompositionEndOffset;
+ }
// Returns true if layout of the character at the aOffset has not been
// calculated.
bool IsLayoutChangedAt(uint32_t aOffset) const
{
return IsLayoutChanged() && (mMinTextModifiedOffset <= aOffset);
}
// Returns true if layout of the content has been changed, i.e., the new
@@ -864,27 +877,39 @@ protected:
return mInitialized && (mMinTextModifiedOffset != NOT_MODIFIED);
}
// Returns minimum offset of modified text range.
uint32_t MinOffsetOfLayoutChanged() const
{
return mInitialized ? mMinTextModifiedOffset : NOT_MODIFIED;
}
+ bool HasOrHadComposition() const
+ {
+ return mInitialized &&
+ mLatestCompositionStartOffset != LONG_MAX &&
+ mLatestCompositionEndOffset != LONG_MAX;
+ }
+
TSFTextStore::Composition& Composition() { return mComposition; }
TSFTextStore::Selection& Selection() { return mSelection; }
private:
nsString mText;
// mLastCompositionString stores the composition string when the document
// is locked. This is necessary to compute mMinTextModifiedOffset.
nsString mLastCompositionString;
TSFTextStore::Composition& mComposition;
TSFTextStore::Selection& mSelection;
+ // The latest composition's start and end offset. If composition hasn't
+ // been started since this instance is initialized, they are LONG_MAX.
+ LONG mLatestCompositionStartOffset;
+ LONG mLatestCompositionEndOffset;
+
// The minimum offset of modified part of the text.
enum : uint32_t
{
NOT_MODIFIED = UINT32_MAX
};
uint32_t mMinTextModifiedOffset;
bool mInitialized;