Bug 1275918 part.1 ContentCache should retrieve the latest composition start offset from TextComposition and send it to the parent process r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Mon, 13 Jun 2016 18:17:58 +0900
changeset 302166 eefc9532e7152d0b03e9489af0b54a1df7ea29f8
parent 302165 0cefc193909c8878ca39cae149a36f3d08739e82
child 302167 bbe31ff52ae422e4133e0eea6a1dcebba990100e
push id19717
push userkwierso@gmail.com
push dateTue, 21 Jun 2016 17:12:40 +0000
treeherderfx-team@448ad5bf7e92 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1275918
milestone50.0a1
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
widget/ContentCache.cpp
widget/ContentCache.h
widget/nsGUIEventIPC.h
--- 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) &&