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 249246 5e35c779d79193d52fd20d5d73b7ff9a05642ae4
parent 249245 a633cd8ac3d9eb7ff9f7ebbf2993c123d96cfff9
child 249247 12afd3e6ae244c1df56f3eadf07a15b8aa005442
push id61184
push usermasayuki@d-toybox.com
push dateWed, 17 Jun 2015 01:04:11 +0000
treeherdermozilla-inbound@12afd3e6ae24 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersm_kato
bugs1171814
milestone41.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 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);
   }
 };