Bug 1171814 ContentCache should store first character rect because Yosemite's Japanese IME sometimes tries to query it r=m_kato
authorMasayuki Nakano <masayuki@d-toybox.com>
Wed, 17 Jun 2015 10:03:58 +0900
changeset 267390 5e35c779d79193d52fd20d5d73b7ff9a05642ae4
parent 267389 a633cd8ac3d9eb7ff9f7ebbf2993c123d96cfff9
child 267391 12afd3e6ae244c1df56f3eadf07a15b8aa005442
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-esr52@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1171814
milestone41.0a1
Bug 1171814 ContentCache should store first character rect because Yosemite's Japanese IME sometimes tries to query it r=m_kato
widget/ContentCache.cpp
widget/ContentCache.h
widget/nsGUIEventIPC.h
--- a/widget/ContentCache.cpp
+++ b/widget/ContentCache.cpp
@@ -133,49 +133,51 @@ ContentCache::AssignContent(const Conten
                             const IMENotification* aNotification)
 {
   if (NS_WARN_IF(!mIsChrome)) {
     return;
   }
 
   mText = aOther.mText;
   mSelection = aOther.mSelection;
+  mFirstCharRect = aOther.mFirstCharRect;
   mCaret = aOther.mCaret;
   mTextRectArray = aOther.mTextRectArray;
   mEditorRect = aOther.mEditorRect;
 
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("ContentCache: 0x%p (mIsChrome=%s) AssignContent(aNotification=%s), "
      "Succeeded, mText.Length()=%u, mSelection={ mAnchor=%u, mFocus=%u, "
      "mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s, mRect=%s }, "
-     "mCaret={ mOffset=%u, mRect=%s }, mTextRectArray={ mStart=%u, "
-     "mRects.Length()=%u }, mEditorRect=%s",
+     "mFirstCharRect=%s, mCaret={ mOffset=%u, mRect=%s }, mTextRectArray={ "
+     "mStart=%u, mRects.Length()=%u }, mEditorRect=%s",
      this, GetBoolName(mIsChrome), GetNotificationName(aNotification),
      mText.Length(), mSelection.mAnchor, mSelection.mFocus,
      GetWritingModeName(mSelection.mWritingMode).get(),
      GetRectText(mSelection.mAnchorCharRect).get(),
      GetRectText(mSelection.mFocusCharRect).get(),
-     GetRectText(mSelection.mRect).get(), mCaret.mOffset,
-     GetRectText(mCaret.mRect).get(), mTextRectArray.mStart,
+     GetRectText(mSelection.mRect).get(), GetRectText(mFirstCharRect).get(),
+     mCaret.mOffset, GetRectText(mCaret.mRect).get(), mTextRectArray.mStart,
      mTextRectArray.mRects.Length(), GetRectText(mEditorRect).get()));
 }
 
 void
 ContentCache::Clear()
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("ContentCache: 0x%p (mIsChrome=%s) Clear()",
      this, GetBoolName(mIsChrome)));
 
   if (NS_WARN_IF(mIsChrome)) {
     return;
   }
 
   mText.Truncate();
   mSelection.Clear();
+  mFirstCharRect.SetEmpty();
   mCaret.Clear();
   mTextRectArray.Clear();
   mEditorRect.SetEmpty();
 }
 
 bool
 ContentCache::HandleQueryContentEvent(WidgetQueryContentEvent& aEvent,
                                       nsIWidget* aWidget) const
@@ -592,16 +594,17 @@ ContentCache::CacheTextRects(nsIWidget* 
   if (NS_WARN_IF(mIsChrome)) {
     return false;
   }
 
   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.
   nsRefPtr<TextComposition> textComposition =
     IMEStateManager::GetTextCompositionFor(aWidget);
@@ -666,26 +669,44 @@ ContentCache::CacheTextRects(nsIWidget* 
         ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), FAILED, "
          "couldn't retrieve text rect of whole selected text",
          this, GetBoolName(mIsChrome)));
     } else {
       mSelection.mRect = textRect.mReply.mRect;
     }
   }
 
+  if (!mSelection.mFocus) {
+    mFirstCharRect = mSelection.mFocusCharRect;
+  } else if (!mSelection.mAnchor) {
+    mFirstCharRect = mSelection.mAnchorCharRect;
+  } else if (mTextRectArray.InRange(0)) {
+    mFirstCharRect = mTextRectArray.GetRect(0);
+  } else {
+    LayoutDeviceIntRect charRect;
+    if (NS_WARN_IF(!QueryCharRect(aWidget, 0, charRect))) {
+      MOZ_LOG(sContentCacheLog, LogLevel::Error,
+        ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), FAILED, "
+         "couldn't retrieve first char rect",
+         this, GetBoolName(mIsChrome)));
+    } else {
+      mFirstCharRect = charRect;
+    }
+  }
+
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("ContentCache: 0x%p (mIsChrome=%s) CacheTextRects(), Succeeded, "
      "mText.Length()=%u, mTextRectArray={ mStart=%u, mRects.Length()=%u }, "
      "mSelection={ mAnchor=%u, mAnchorCharRect=%s, mFocus=%u, "
-     "mFocusCharRect=%s, mRect=%s }",
+     "mFocusCharRect=%s, mRect=%s }, mFirstCharRect=%s",
      this, GetBoolName(mIsChrome), mText.Length(), mTextRectArray.mStart,
      mTextRectArray.mRects.Length(), mSelection.mAnchor,
      GetRectText(mSelection.mAnchorCharRect).get(), mSelection.mFocus,
      GetRectText(mSelection.mFocusCharRect).get(),
-     GetRectText(mSelection.mRect).get()));
+     GetRectText(mSelection.mRect).get(), GetRectText(mFirstCharRect).get()));
   return true;
 }
 
 void
 ContentCache::SetSelection(nsIWidget* aWidget,
                            uint32_t aStartOffset,
                            uint32_t aLength,
                            bool aReversed,
@@ -723,16 +744,21 @@ ContentCache::GetTextRect(uint32_t aOffs
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("ContentCache: 0x%p (mIsChrome=%s) GetTextRect(aOffset=%u), "
      "mTextRectArray={ mStart=%u, mRects.Length()=%u }, "
      "mSelection={ mAnchor=%u, mFocus=%u }",
      this, GetBoolName(mIsChrome), aOffset, mTextRectArray.mStart,
      mTextRectArray.mRects.Length(), mSelection.mAnchor, mSelection.mFocus));
 
+  if (!aOffset) {
+    NS_WARN_IF(mFirstCharRect.IsEmpty());
+    aTextRect = mFirstCharRect;
+    return !aTextRect.IsEmpty();
+  }
   if (aOffset == mSelection.mAnchor) {
     NS_WARN_IF(mSelection.mAnchorCharRect.IsEmpty());
     aTextRect = mSelection.mAnchorCharRect;
     return !aTextRect.IsEmpty();
   }
   if (aOffset == mSelection.mFocus) {
     NS_WARN_IF(mSelection.mFocusCharRect.IsEmpty());
     aTextRect = mSelection.mFocusCharRect;
@@ -763,16 +789,21 @@ ContentCache::GetUnionTextRects(uint32_t
   if (!mSelection.Collapsed() &&
       aOffset == mSelection.StartOffset() && aLength == mSelection.Length()) {
     NS_WARN_IF(mSelection.mRect.IsEmpty());
     aUnionTextRect = mSelection.mRect;
     return !aUnionTextRect.IsEmpty();
   }
 
   if (aLength == 1) {
+    if (!aOffset) {
+      NS_WARN_IF(mFirstCharRect.IsEmpty());
+      aUnionTextRect = mFirstCharRect;
+      return !aUnionTextRect.IsEmpty();
+    }
     if (aOffset == mSelection.mAnchor) {
       NS_WARN_IF(mSelection.mAnchorCharRect.IsEmpty());
       aUnionTextRect = mSelection.mAnchorCharRect;
       return !aUnionTextRect.IsEmpty();
     }
     if (aOffset == mSelection.mFocus) {
       NS_WARN_IF(mSelection.mFocusCharRect.IsEmpty());
       aUnionTextRect = mSelection.mFocusCharRect;
@@ -791,24 +822,26 @@ ContentCache::GetUnionTextRects(uint32_t
 bool
 ContentCache::GetCaretRect(uint32_t aOffset,
                            LayoutDeviceIntRect& aCaretRect) const
 {
   MOZ_LOG(sContentCacheLog, LogLevel::Info,
     ("ContentCache: 0x%p (mIsChrome=%s) GetCaretRect(aOffset=%u), "
      "mCaret={ mOffset=%u, mRect=%s, IsValid()=%s }, mTextRectArray={ "
      "mStart=%u, mRects.Length()=%u }, mSelection={ mAnchor=%u, mFocus=%u, "
-     "mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s }",
+     "mWritingMode=%s, mAnchorCharRect=%s, mFocusCharRect=%s }, "
+     "mFirstCharRect=%s",
      this, GetBoolName(mIsChrome), aOffset, mCaret.mOffset,
      GetRectText(mCaret.mRect).get(), GetBoolName(mCaret.IsValid()),
      mTextRectArray.mStart, mTextRectArray.mRects.Length(),
      mSelection.mAnchor, mSelection.mFocus,
      GetWritingModeName(mSelection.mWritingMode).get(),
      GetRectText(mSelection.mAnchorCharRect).get(),
-     GetRectText(mSelection.mFocusCharRect).get()));
+     GetRectText(mSelection.mFocusCharRect).get(),
+     GetRectText(mFirstCharRect).get()));
 
   if (mCaret.IsValid() && mCaret.mOffset == aOffset) {
     aCaretRect = mCaret.mRect;
     return true;
   }
 
   // Guess caret rect from the text rect if it's stored.
   if (!GetTextRect(aOffset, aCaretRect)) {
--- a/widget/ContentCache.h
+++ b/widget/ContentCache.h
@@ -224,16 +224,20 @@ private:
     }
   } mSelection;
 
   bool IsSelectionValid() const
   {
     return mSelection.IsValid() && mSelection.EndOffset() <= mText.Length();
   }
 
+  // Stores first char rect because Yosemite's Japanese IME sometimes tries
+  // to query it.  If there is no text, this is caret rect.
+  LayoutDeviceIntRect mFirstCharRect;
+
   struct Caret final
   {
     uint32_t mOffset;
     LayoutDeviceIntRect mRect;
 
     Caret()
       : mOffset(UINT32_MAX)
     {
--- a/widget/nsGUIEventIPC.h
+++ b/widget/nsGUIEventIPC.h
@@ -803,32 +803,34 @@ struct ParamTraits<mozilla::ContentCache
   {
     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);
     WriteParam(aMsg, aParam.mCaret.mOffset);
     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, void** aIter, paramType* aResult)
   {
     return 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) &&
            ReadParam(aMsg, aIter, &aResult->mCaret.mRect) &&
            ReadParam(aMsg, aIter, &aResult->mTextRectArray.mStart) &&
            ReadParam(aMsg, aIter, &aResult->mTextRectArray.mRects) &&
            ReadParam(aMsg, aIter, &aResult->mEditorRect);
   }
 };