diff --git a/widget/ContentCache.cpp b/widget/ContentCache.cpp index 9aac80145ff9..92cf4af6eda4 100644 --- a/widget/ContentCache.cpp +++ b/widget/ContentCache.cpp @@ -72,13 +72,11 @@ public: * mozilla::ContentCache *****************************************************************************/ -PRLogModuleInfo* sContentCacheLog = nullptr; +LazyLogModule sContentCacheLog("ContentCacheWidgets"); ContentCache::ContentCache() + : mCompositionStart(UINT32_MAX) { - if (!sContentCacheLog) { - sContentCacheLog = PR_NewLogModule("ContentCacheWidgets"); - } } /***************************************************************************** @@ -96,6 +94,7 @@ ContentCacheInChild::Clear() MOZ_LOG(sContentCacheLog, LogLevel::Info, ("ContentCacheInChild: 0x%p Clear()", this)); + mCompositionStart = UINT32_MAX; mText.Truncate(); mSelection.Clear(); mFirstCharRect.SetEmpty(); @@ -286,6 +285,7 @@ ContentCacheInChild::CacheTextRects(nsIWidget* aWidget, this, aWidget, GetNotificationName(aNotification), mCaret.mOffset, GetBoolName(mCaret.IsValid()))); + mCompositionStart = UINT32_MAX; mTextRectArray.Clear(); mSelection.mAnchorCharRect.SetEmpty(); mSelection.mFocusCharRect.SetEmpty(); @@ -300,12 +300,15 @@ ContentCacheInChild::CacheTextRects(nsIWidget* aWidget, RefPtr textComposition = IMEStateManager::GetTextCompositionFor(aWidget); if (textComposition) { + // mCompositionStart may be updated by some composition event handlers. + // So, let's update it with the latest information. + mCompositionStart = textComposition->NativeOffsetOfStartComposition(); // Note that TextComposition::String() may not be modified here because // it's modified after all edit action listeners are performed but this // is called while some of them are performed. uint32_t length = textComposition->LastData().Length(); mTextRectArray.mRects.SetCapacity(length); - mTextRectArray.mStart = textComposition->NativeOffsetOfStartComposition(); + mTextRectArray.mStart = mCompositionStart; uint32_t endOffset = mTextRectArray.mStart + length; for (uint32_t i = mTextRectArray.mStart; i < endOffset; i++) { LayoutDeviceIntRect charRect; @@ -428,7 +431,6 @@ ContentCacheInChild::SetSelection(nsIWidget* aWidget, ContentCacheInParent::ContentCacheInParent() : ContentCache() , mCommitStringByRequest(nullptr) - , mCompositionStart(UINT32_MAX) , mPendingEventsNeedingAck(0) , mIsComposing(false) { @@ -438,6 +440,7 @@ void ContentCacheInParent::AssignContent(const ContentCache& aOther, const IMENotification* aNotification) { + mCompositionStart = aOther.mCompositionStart; mText = aOther.mText; mSelection = aOther.mSelection; mFirstCharRect = aOther.mFirstCharRect; @@ -450,7 +453,7 @@ ContentCacheInParent::AssignContent(const ContentCache& aOther, "Succeeded, mText.Length()=%u, mSelection={ mAnchor=%u, mFocus=%u, " "mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s, mRect=%s }, " "mFirstCharRect=%s, mCaret={ mOffset=%u, mRect=%s }, mTextRectArray={ " - "mStart=%u, mRects.Length()=%u }, mEditorRect=%s", + "mStart=%u, mRects.Length()=%u }, mCompositionStart=%u, mEditorRect=%s", this, GetNotificationName(aNotification), mText.Length(), mSelection.mAnchor, mSelection.mFocus, GetWritingModeName(mSelection.mWritingMode).get(), @@ -458,7 +461,8 @@ ContentCacheInParent::AssignContent(const ContentCache& aOther, GetRectText(mSelection.mFocusCharRect).get(), GetRectText(mSelection.mRect).get(), GetRectText(mFirstCharRect).get(), mCaret.mOffset, GetRectText(mCaret.mRect).get(), mTextRectArray.mStart, - mTextRectArray.mRects.Length(), GetRectText(mEditorRect).get())); + mTextRectArray.mRects.Length(), mCompositionStart, + GetRectText(mEditorRect).get())); } bool @@ -835,6 +839,10 @@ ContentCacheInParent::OnCompositionEvent(const WidgetCompositionEvent& aEvent) mIsComposing = !aEvent.CausesDOMCompositionEndEvent(); + if (!mIsComposing) { + mCompositionStart = UINT32_MAX; + } + // During REQUEST_TO_COMMIT_COMPOSITION or REQUEST_TO_CANCEL_COMPOSITION, // widget usually sends a eCompositionChange and/or eCompositionCommit event // to finalize or clear the composition, respectively. In this time, diff --git a/widget/ContentCache.h b/widget/ContentCache.h index dde6f051937b..73814f63baed 100644 --- a/widget/ContentCache.h +++ b/widget/ContentCache.h @@ -41,6 +41,9 @@ protected: // Whole text in the target nsString mText; + // Start offset of the composition string. + uint32_t mCompositionStart; + struct Selection final { // Following values are offset in "flat text". @@ -360,8 +363,6 @@ private: // composition. Then, data value of dispatched composition events should // be stored into the instance. nsAString* mCommitStringByRequest; - // Start offset of the composition string. - uint32_t mCompositionStart; // mPendingEventsNeedingAck is increased before sending a composition event or // a selection event and decreased after they are received in the child // process. diff --git a/widget/nsGUIEventIPC.h b/widget/nsGUIEventIPC.h index 436eab6f9ace..b39744b583dd 100644 --- a/widget/nsGUIEventIPC.h +++ b/widget/nsGUIEventIPC.h @@ -975,6 +975,7 @@ struct ParamTraits static void Write(Message* aMsg, const paramType& aParam) { + WriteParam(aMsg, aParam.mCompositionStart); WriteParam(aMsg, aParam.mText); WriteParam(aMsg, aParam.mSelection.mAnchor); WriteParam(aMsg, aParam.mSelection.mFocus); @@ -992,7 +993,8 @@ struct ParamTraits static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult) { - return ReadParam(aMsg, aIter, &aResult->mText) && + return ReadParam(aMsg, aIter, &aResult->mCompositionStart) && + ReadParam(aMsg, aIter, &aResult->mText) && ReadParam(aMsg, aIter, &aResult->mSelection.mAnchor) && ReadParam(aMsg, aIter, &aResult->mSelection.mFocus) && ReadParam(aMsg, aIter, &aResult->mSelection.mWritingMode) &&