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 302152 eefc9532e7152d0b03e9489af0b54a1df7ea29f8
parent 302151 0cefc193909c8878ca39cae149a36f3d08739e82
child 302153 bbe31ff52ae422e4133e0eea6a1dcebba990100e
push id30353
push userkwierso@gmail.com
push dateTue, 21 Jun 2016 17:06:01 +0000
treeherdermozilla-central@20167cee53dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1275918
milestone50.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
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) &&