Bug 1275918 part.1 ContentCache should retrieve the latest composition start offset from TextComposition and send it to the parent process r?m_kato
MozReview-Commit-ID: EoMZtqoMue3
--- a/widget/ContentCache.cpp
+++ b/widget/ContentCache.cpp
@@ -67,23 +67,21 @@ public:
}
virtual ~GetWritingModeName() {}
};
/*****************************************************************************
* mozilla::ContentCache
*****************************************************************************/
-PRLogModuleInfo* sContentCacheLog = nullptr;
+LazyLogModule sContentCacheLog("ContentCacheWidgets");
ContentCache::ContentCache()
+ : mCompositionStart(UINT32_MAX)
{
- if (!sContentCacheLog) {
- sContentCacheLog = PR_NewLogModule("ContentCacheWidgets");
- }
}
/*****************************************************************************
* mozilla::ContentCacheInChild
*****************************************************************************/
ContentCacheInChild::ContentCacheInChild()
: ContentCache()
@@ -91,16 +89,17 @@ ContentCacheInChild::ContentCacheInChild
}
void
ContentCacheInChild::Clear()
{
MOZ_LOG(sContentCacheLog, LogLevel::Info,
("ContentCacheInChild: 0x%p Clear()", this));
+ mCompositionStart = UINT32_MAX;
mText.Truncate();
mSelection.Clear();
mFirstCharRect.SetEmpty();
mCaret.Clear();
mTextRectArray.Clear();
mEditorRect.SetEmpty();
}
@@ -281,36 +280,40 @@ ContentCacheInChild::CacheTextRects(nsIW
const IMENotification* aNotification)
{
MOZ_LOG(sContentCacheLog, LogLevel::Info,
("ContentCacheInChild: 0x%p CacheTextRects(aWidget=0x%p, "
"aNotification=%s), mCaret={ mOffset=%u, IsValid()=%s }",
this, aWidget, GetNotificationName(aNotification), mCaret.mOffset,
GetBoolName(mCaret.IsValid())));
+ mCompositionStart = UINT32_MAX;
mTextRectArray.Clear();
mSelection.mAnchorCharRect.SetEmpty();
mSelection.mFocusCharRect.SetEmpty();
mSelection.mRect.SetEmpty();
mFirstCharRect.SetEmpty();
if (NS_WARN_IF(!mSelection.IsValid())) {
return false;
}
// Retrieve text rects in composition string if there is.
RefPtr<TextComposition> 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;
if (NS_WARN_IF(!QueryCharRect(aWidget, i, charRect))) {
MOZ_LOG(sContentCacheLog, LogLevel::Error,
("ContentCacheInChild: 0x%p CacheTextRects(), FAILED, "
"couldn't retrieve text rect at offset=%u", this, i));
mTextRectArray.Clear();
@@ -423,47 +426,48 @@ ContentCacheInChild::SetSelection(nsIWid
/*****************************************************************************
* mozilla::ContentCacheInParent
*****************************************************************************/
ContentCacheInParent::ContentCacheInParent()
: ContentCache()
, mCommitStringByRequest(nullptr)
- , mCompositionStart(UINT32_MAX)
, mPendingEventsNeedingAck(0)
, mIsComposing(false)
{
}
void
ContentCacheInParent::AssignContent(const ContentCache& aOther,
const IMENotification* aNotification)
{
+ mCompositionStart = aOther.mCompositionStart;
mText = aOther.mText;
mSelection = aOther.mSelection;
mFirstCharRect = aOther.mFirstCharRect;
mCaret = aOther.mCaret;
mTextRectArray = aOther.mTextRectArray;
mEditorRect = aOther.mEditorRect;
MOZ_LOG(sContentCacheLog, LogLevel::Info,
("ContentCacheInParent: 0x%p AssignContent(aNotification=%s), "
"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(),
GetRectText(mSelection.mAnchorCharRect).get(),
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
ContentCacheInParent::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
nsIWidget* aWidget) const
{
MOZ_ASSERT(aWidget);
@@ -830,16 +834,20 @@ ContentCacheInParent::OnCompositionEvent
mCompositionStart = 0;
} else {
mCompositionStart = mSelection.StartOffset();
}
}
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,
// we need to intercept all composition events here and pass the commit
// string for returning to the remote process as a result of
// RequestIMEToCommitComposition(). Then, eCommitComposition event will
// be dispatched with the committed string in the remote process internally.
if (mCommitStringByRequest) {
--- a/widget/ContentCache.h
+++ b/widget/ContentCache.h
@@ -36,16 +36,19 @@ public:
typedef widget::IMENotification IMENotification;
ContentCache();
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".
uint32_t mAnchor;
uint32_t mFocus;
WritingMode mWritingMode;
@@ -355,18 +358,16 @@ private:
IMENotification mPendingTextChange;
IMENotification mPendingLayoutChange;
IMENotification mPendingCompositionUpdate;
// This is not nullptr only while the instance is requesting IME to
// 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.
uint32_t mPendingEventsNeedingAck;
bool mIsComposing;
bool GetCaretRect(uint32_t aOffset, LayoutDeviceIntRect& aCaretRect) const;
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -970,16 +970,17 @@ struct ParamTraits<mozilla::WritingMode>
template<>
struct ParamTraits<mozilla::ContentCache>
{
typedef mozilla::ContentCache paramType;
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);
WriteParam(aMsg, aParam.mSelection.mWritingMode);
WriteParam(aMsg, aParam.mSelection.mAnchorCharRect);
WriteParam(aMsg, aParam.mSelection.mFocusCharRect);
WriteParam(aMsg, aParam.mSelection.mRect);
WriteParam(aMsg, aParam.mFirstCharRect);
@@ -987,17 +988,18 @@ struct ParamTraits<mozilla::ContentCache
WriteParam(aMsg, aParam.mCaret.mRect);
WriteParam(aMsg, aParam.mTextRectArray.mStart);
WriteParam(aMsg, aParam.mTextRectArray.mRects);
WriteParam(aMsg, aParam.mEditorRect);
}
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) &&
ReadParam(aMsg, aIter, &aResult->mSelection.mAnchorCharRect) &&
ReadParam(aMsg, aIter, &aResult->mSelection.mFocusCharRect) &&
ReadParam(aMsg, aIter, &aResult->mSelection.mRect) &&
ReadParam(aMsg, aIter, &aResult->mFirstCharRect) &&
ReadParam(aMsg, aIter, &aResult->mCaret.mOffset) &&